| t@@ -19,6 +19,8 @@
u32int maxblocksize;
int readonly;
+int findsubpart(Part *part, char *name);
+
static int
strtoullsuf(char *p, char **pp, int rad, u64int *u)
{
t@@ -56,17 +58,21 @@ strtoullsuf(char *p, char **pp, int rad, u64int *u)
}
static int
-parsepart(char *name, char **file, u64int *lo, u64int *hi)
+parsepart(char *name, char **file, char **subpart, u64int *lo, u64int *hi)
{
char *p;
*file = estrdup(name);
- if((p = strrchr(*file, ':')) == nil){
- *lo = 0;
- *hi = 0;
+ *lo = 0;
+ *hi = 0;
+ *subpart = nil;
+ if((p = strrchr(*file, ':')) == nil)
return 0;
- }
*p++ = 0;
+ if(isalpha(*p)){
+ *subpart = p;
+ return 0;
+ }
if(*p == '-')
*lo = 0;
else{
t@@ -93,11 +99,13 @@ initpart(char *name, int mode)
{
Part *part;
Dir *dir;
- char *file;
+ char *file, *subname;
u64int lo, hi;
- if(parsepart(name, &file, &lo, &hi) < 0)
+ if(parsepart(name, &file, &subname, &lo, &hi) < 0){
+ werrstr("cannot parse name %s", name);
return nil;
+ }
trace(TraceDisk, "initpart %s file %s lo 0x%llx hi 0x%llx", name, file, lo, hi);
part = MKZ(Part);
part->name = estrdup(name);
t@@ -124,7 +132,7 @@ initpart(char *name, int mode)
fprint(2, "warning: %s opened for reading only\n", name);
}
part->offset = lo;
- dir = dirfstat(part->fd);
+ dir = dirstat(file); /* no dirfstat; need name to identify disk devices */
if(dir == nil){
freepart(part);
seterr(EOk, "can't stat partition='%s': %r", file);
t@@ -155,6 +163,11 @@ initpart(char *name, int mode)
part->fsblocksize = sfs.f_bsize;
}
#endif
+ if(subname && findsubpart(part, subname) < 0){
+ werrstr("cannot find subpartition %s", subname);
+ freepart(part);
+ return nil;
+ }
free(dir);
return part;
}
t@@ -464,206 +477,106 @@ readfile(char *name)
return b;
}
-
-
-
-
-
-
-
-#ifndef PLAN9PORT
+/*
+ * Search for the Plan 9 partition with the given name.
+ * This lets you write things like /dev/ad4:arenas
+ * if you move a disk from a Plan 9 system to a FreeBSD system.
+ *
+ * God I hope I never write this code again.
+ */
+#define MAGIC "plan9 partitions"
static int
-sdreset(Part *part)
+tryplan9part(Part *part, char *name)
{
- char *name, *p;
- int i, fd, xfd[3], rv;
- static QLock resetlk;
- Dir *d, *dd;
-
- fprint(2, "sdreset %s\n", part->name);
- name = emalloc(strlen(part->filename)+20);
- strcpy(name, part->filename);
- p = strrchr(name, '/');
- if(p)
- p++;
- else
- p = name;
-
- strcpy(p, "ctl");
- d = dirstat(name);
- if(d == nil){
- free(name);
- return -1;
- }
+ uchar buf[512];
+ char *line[40], *f[4];
+ int i, n;
+ vlong start, end;
/*
- * We don't need multiple people resetting the disk.
+ * Partition table in second sector.
+ * Could also look on 2nd last sector and last sector,
+ * but those disks died out long before venti came along.
*/
- qlock(&resetlk);
- if((fd = open(name, OWRITE)) < 0)
- goto error;
- dd = dirfstat(fd);
- if(d && dd && d->qid.vers != dd->qid.vers){
- fprint(2, "sdreset %s: got scooped\n", part->name);
- /* Someone else got here first. */
- if(access(part->filename, AEXIST) >= 0)
- goto ok;
- goto error;
- }
-
- /*
- * Write "reset" to the ctl file to cause the chipset
- * to reinitialize itself (specific to sdmv driver).
- * Ignore error in case using other disk.
- */
- fprint(2, "sdreset %s: reset ctl\n", part->name);
- write(fd, "reset", 5);
-
- if(access(part->filename, AEXIST) >= 0)
- goto ok;
-
- /*
- * Re-run fdisk and prep. Don't use threadwaitchan
- * to avoid coordinating for it. Reopen ctl because
- * we reset the disk.
- */
- strcpy(p, "ctl");
- close(fd);
- if((fd = open(name, OWRITE)) < 0)
- goto error;
- strcpy(p, "data");
- xfd[0] = open("/dev/null", OREAD);
- xfd[1] = dup(fd, -1);
- xfd[2] = dup(2, -1);
- fprint(2, "sdreset %s: run fdisk %s\n", part->name, name);
- if(threadspawnl(xfd, "/bin/disk/fdisk", "disk/fdisk", "-p", name, nil) < 0){
- close(xfd[0]);
- close(xfd[1]);
- close(xfd[2]);
- goto error;
- }
- strcpy(p, "plan9");
- for(i=0; i<=20; i++){
- sleep(i*100);
- if(access(part->filename, AEXIST) >= 0)
- goto ok;
- if(access(name, AEXIST) >= 0)
- goto prep;
- }
- goto error;
-
-prep:
- strcpy(p, "ctl");
- close(fd);
- if((fd = open(name, OWRITE)) < 0)
- goto error;
- strcpy(p, "plan9");
- xfd[0] = open("/dev/null", OREAD);
- xfd[1] = dup(fd, -1);
- xfd[2] = dup(2, -1);
- fprint(2, "sdreset %s: run prep\n", part->name);
- if(threadspawnl(xfd, "/bin/disk/prep", "disk/prep", "-p", name, nil) < 0){
- close(xfd[0]);
- close(xfd[1]);
- close(xfd[2]);
- goto error;
- }
- for(i=0; i<=20; i++){
- sleep(i*100);
- if(access(part->filename, AEXIST) >= 0)
- goto ok;
- }
+ if(readpart(part, 512, buf, 512) != 512)
+ return -1;
-error:
- fprint(2, "sdreset %s: error: %r\n", part->name);
- rv = -1;
- if(fd >= 0)
- close(fd);
- goto out;
-
-ok:
- fprint(2, "sdreset %s: all okay\n", part->name);
- rv = 0;
- goto out;
-
-out:
- free(name);
- qunlock(&resetlk);
- return rv;
-}
+ /* Plan 9 partition table is just text strings */
+ if(strncmp((char*)buf, "part ", 5) != 0)
+ return -1;
-static int
-reopen(Part *part)
-{
- int fd;
-
- fprint(2, "reopen %s\n", part->filename);
- if((fd = open(part->filename, ORDWR)) < 0){
- if(access(part->filename, AEXIST) < 0){
- sdreset(part);
- fd = open(part->filename, ORDWR);
- }
- if(fd < 0){
- fprint(2, "reopen %s: %r\n", part->filename);
+ buf[511] = 0;
+ n = getfields((char*)buf, line, 40, 1, "\n");
+ for(i=0; isize){
+ part->offset += start;
+ part->size = end - start;
+ return 0;
+ }
return -1;
}
}
- if(fd != part->fd){
- dup(fd, part->fd);
- close(fd);
- }
- return 0;
+ return -1;
}
-typedef struct Spawn Spawn;
-struct Spawn
+#define GSHORT(p) (((p)[1]<<8)|(p)[0])
+#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
+
+typedef struct Dospart Dospart;
+struct Dospart
{
- Channel *c;
- int fd[3];
- char *file;
- char **argv;
+ uchar flag; /* active flag */
+ uchar shead; /* starting head */
+ uchar scs[2]; /* starting cylinder/sector */
+ uchar type; /* partition type */
+ uchar ehead; /* ending head */
+ uchar ecs[2]; /* ending cylinder/sector */
+ uchar offset[4]; /* starting sector */
+ uchar size[4]; /* length in sectors */
};
-static void
-spawnproc(void *v)
-{
- int i, *fd;
- Spawn *s;
-
- rfork(RFFDG);
- s = v;
- fd = s->fd;
- for(i=0; i<3; i++)
- dup(fd[i], i);
- if(fd[0] > 2)
- close(fd[0]);
- if(fd[1] > 2 && fd[1] != fd[0])
- close(fd[1]);
- if(fd[2] > 2 && fd[2] != fd[1] && fd[2] != fd[0])
- close(fd[2]);
- procexec(s->c, s->file, s->argv);
-}
-static int
-threadspawnl(int fd[3], char *file, char *argv0, ...)
+int
+findsubpart(Part *part, char *name)
{
- int pid;
- Spawn s;
+ int i;
+ uchar buf[512];
+ u64int size;
+ Dospart *dp;
+
+ /* See if this is a Plan 9 partition. */
+ if(tryplan9part(part, name) >= 0)
+ return 0;
- s.c = chancreate(sizeof(void*), 0);
- memmove(s.fd, fd, sizeof(s.fd));
- s.file = file;
- s.argv = &argv0;
- vtproc(spawnproc, &s);
- pid = recvul(s.c);
- if(pid < 0)
+ /* Otherwise try for an MBR and then narrow to Plan 9 partition. */
+ if(readpart(part, 0, buf, 512) != 512)
+ return -1;
+ if(buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)
return -1;
- close(fd[0]);
- if(fd[1] != fd[0])
- close(fd[1]);
- if(fd[2] != fd[1] && fd[2] != fd[0])
- close(fd[2]);
- return pid;
+ dp = (Dospart*)(buf+0x1BE);
+ size = part->size;
+ for(i=0; i<4; i++){
+ if(dp[i].type == '9'){
+ part->offset = 512LL*GLONG(dp[i].offset);
+ part->size = 512LL*GLONG(dp[i].size);
+ if(tryplan9part(part, name) >= 0)
+ return 0;
+ part->offset = 0;
+ part->size = size;
+ }
+ /* Not implementing extended partitions - enough is enough. */
+ }
+ return -1;
}
-#endif
+
+
+
+ |