Date: Mon, 10 Feb 2003 16:48:22 -0800 (PST) From: Juli Mallett <jmallett@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 24951 for review Message-ID: <200302110048.h1B0mMrs006368@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=24951 Change 24951 by jmallett@jmallett_dalek on 2003/02/10 16:47:29 Implement fxlabel editing and the necessary abstractions, also a few much-needed passing-arounds of a volume header. Affected files ... .. //depot/projects/mips/sbin/fxlabel/fxlabel.c#6 edit .. //depot/projects/mips/sys/sys/diskfx.h#7 edit Differences ... ==== //depot/projects/mips/sbin/fxlabel/fxlabel.c#6 (text+ko) ==== @@ -27,12 +27,16 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> +#include <sys/disk.h> #include <sys/diskfx.h> #include <sys/endian.h> #include <sys/param.h> #include <sys/stat.h> +#include <sys/wait.h> +#include <ctype.h> #include <err.h> #include <fcntl.h> +#include <paths.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> @@ -41,6 +45,7 @@ struct volhdr label; struct volpart *vhp = &label.vh_part[FX_VOLHDRPART]; +struct volpart *volp = &label.vh_part[FX_VOLPART]; static int bsize = 512; /* @@ -48,22 +53,27 @@ * programmers from shooting off feet. */ static void addfile(struct volhdr *, int, const char *); +static int bytesround2bsize(int); +static void clearpart(struct volhdr *); static void defrag(struct volhdr *, int); static void deletefile(struct volhdr *, int, const char *); static int dkopen(const char *, int); +static int disksize(int); static void dirlist(struct volhdr *); +static void editlabel(struct volhdr *, int, int); static void getfile(struct volhdr *, int, const char *); static bool goodlabel(struct volhdr *, const char **); static int32_t labelsum(struct volhdr *); -static void newlabel(struct volhdr *); -static void printlabel(struct volhdr *); -static bool readlabel(int); +static void newlabel(struct volhdr *, int, int); +static bool parselabel(struct volhdr *, FILE *); +static void printlabel(struct volhdr *, FILE *); +static bool readlabel(struct volhdr *, int); static void setpart(struct volhdr *, int, int, int, int); static void sumlabel(struct volhdr *); static void swap_dec_label(struct volhdr *); static void swap_enc_label(struct volhdr *); -static int startdisk(const char *, int); -static bool writelabel(int); +static int startdisk(struct volhdr *, const char *, int); +static bool writelabel(struct volhdr *, int); static void usage(void); @@ -78,16 +88,17 @@ main(int argc, char *argv[]) { const char *aflag, *dflag, *disk, *gflag; - bool pflag, wflag; + bool eflag, pflag, wflag; + int dksize; int sflag; int ch; int fd; aflag = dflag = gflag = NULL; - pflag = wflag = false; - sflag = 0; + eflag = pflag = wflag = false; + dksize = sflag = 0; - while ((ch = getopt(argc, argv, "a:d:g:ps:w")) != -1) { + while ((ch = getopt(argc, argv, "a:d:eg:ps:w")) != -1) { switch (ch) { case 'a': aflag = optarg; @@ -95,6 +106,9 @@ case 'd': dflag = optarg; break; + case 'e': + eflag = true; + break; case 'g': gflag = optarg; break; @@ -109,7 +123,7 @@ warnx("volume header size not >= %d", bsize); usage(); } - sflag = ((sflag + 511) / bsize) * bsize; + sflag = bytesround2bsize(sflag); break; case 'w': if (pflag) @@ -124,7 +138,8 @@ argc -= optind; argv += optind; - if (aflag == NULL && dflag == NULL && gflag == NULL && !pflag && !wflag) + if (aflag == NULL && dflag == NULL && !eflag && gflag == NULL && + !pflag && !wflag) pflag = true; if (!sflag) @@ -132,32 +147,42 @@ while ((disk = *argv++) != NULL) { if (aflag != NULL) { - fd = startdisk(disk, O_RDWR); + fd = startdisk(&label, disk, O_RDWR); defrag(&label, fd); addfile(&label, fd, aflag); - if (writelabel(fd)) + if (writelabel(&label, fd)) err(1, "%s (label write)", disk); close(fd); continue; } if (dflag != NULL) { - fd = startdisk(disk, O_RDWR); + fd = startdisk(&label, disk, O_RDWR); deletefile(&label, fd, dflag); defrag(&label, fd); - if (writelabel(fd)) + if (writelabel(&label, fd)) err(1, "%s (label write)", disk); close(fd); continue; } + if (eflag) { + fd = dkopen(disk, O_RDWR); + if (fd == -1) + err(1, "%s (open)", disk); + editlabel(&label, fd, sflag); + if (writelabel(&label, fd)) + err(1, "%s (label write)", disk); + continue; + } if (gflag != NULL) { - fd = startdisk(disk, O_RDONLY); + fd = startdisk(&label, disk, O_RDONLY); getfile(&label, fd, gflag); close(fd); continue; } if (pflag) { - fd = startdisk(disk, O_RDONLY); - printlabel(&label); + fd = startdisk(&label, disk, O_RDONLY); + printlabel(&label, stdout); + dirlist(&label); close(fd); continue; } @@ -165,9 +190,11 @@ fd = dkopen(disk, O_WRONLY); if (fd == -1) err(1, "%s (open)", disk); - newlabel(&label); - setpart(&label, FX_VOLHDRPART, FX_TYPEVOLHDR, 0, sflag); - if (writelabel(fd)) + dksize = disksize(fd); + if (dksize == -1) + err(1, "%s (disk size)", disk); + newlabel(&label, sflag, dksize); + if (writelabel(&label, fd)) err(1, "%s (label write)", disk); close(fd); continue; @@ -228,7 +255,7 @@ strncpy(dp->vd_name, file, FX_NAMELEN); dp->vd_addr = himark + 1; dp->vd_size = st.st_size; - rounded = ((st.st_size + 511) / bsize) * bsize; + rounded = bytesround2bsize(st.st_size); buf = malloc(rounded); if (buf == NULL) errx(1, "malloc failed"); @@ -241,6 +268,26 @@ err(1, "%s (input write)", file); } +static int +bytesround2bsize(int bytes) +{ + return (((bytes + (bsize - 1)) / bsize) * bsize); +} + +static void +clearpart(struct volhdr *vp) +{ + struct volpart *part; + int i; + + for (i = 0; i < FX_NPARTS; i++) { + part = &vp->vh_part[i]; + part->vp_type = 0; + part->vp_begin = 0; + part->vp_size = 0; + } +} + static void defrag(struct volhdr *vp, int fd) { @@ -304,6 +351,105 @@ } } +static int +disksize(int fd) +{ + off_t mediasize; + struct stat st; + int rv; + + rv = fstat(fd, &st); + if (rv == -1 || st.st_size <= 0) { + rv = ioctl(fd, DIOCGMEDIASIZE, &mediasize); + if (rv == -1) + return (-1); + } else + mediasize = st.st_size; + + rv = mediasize; + + return (rv); +} + +static void +editlabel(struct volhdr *vp, int fd, int hdrsize) +{ + char buf[] = "/tmp/fxlabel.XXXXXXX"; + const char *editor; + int dksize; + int status; + pid_t pid, xpid; + FILE *fp; + int efd; + int ch; + int rv; + + if (readlabel(vp, fd)) + err(1, "%d (label read)", fd); + + dksize = disksize(fd); + if (dksize == -1) + err(1, "%d (disk size)", fd); + + efd = mkstemp(buf); + if (efd == -1) + err(1, "make temp file"); + fp = fdopen(efd, "w+"); + if (fp == NULL) + err(1, "make temp file stream"); + if (goodlabel(vp, NULL)) { + newlabel(vp, hdrsize, dksize); + fputs("# Below is a new disk label, edit it wisely.\n", fp); + } else { + swap_dec_label(vp); + fputs("# Below is your disk label, edit it wisely.\n", fp); + } + printlabel(vp, fp); + clearpart(vp); + editor = getenv("EDITOR"); + if (editor == NULL) + editor = _PATH_VI; + pid = fork(); + if (pid < 0) + err(1, "%d (editor fork)", fd); + if (pid == 0) { + setgid(getgid()); + setuid(getuid()); + execlp(editor, editor, buf, NULL); + err(1, "%s", editor); + } + while ((xpid = wait(&status)) >= 0) + if (xpid == pid) + break; + rewind(fp); + + if (parselabel(vp, fp)) { + printf("WARNING: Possible errors detected. Write? [yN] "); + while ((ch = getc(stdin)) != EOF) { + switch (ch) { + case 'Y': + case 'y': + goto write; + case '\n': + case 'N': + case 'n': + break; + default: + continue; + } + break; + } + printf("NOT WRITING DISK LABEL, SAVED IN %s\n", buf); + exit(1); + } +write: printf("WRITING DISK LABEL TO DISK:\n"); + printlabel(vp, stdout); + rv = unlink(buf); + if (rv == -1) + warn("unlink %s", buf); + return; +} + static void getfile(struct volhdr *vp, int fd, const char *file) { @@ -326,7 +472,7 @@ buf = malloc(dp->vd_size); if (buf == NULL) errx(1, "malloc failed"); - rounded = ((dp->vd_size + 511) / bsize) * bsize; + rounded = bytesround2bsize(dp->vd_size); cnt = pread(fd, buf, rounded, dp->vd_addr * bsize); if (cnt != rounded) err(1, "%s (file read)", file); @@ -342,18 +488,25 @@ static bool goodlabel(struct volhdr *vp, const char **errorp) { + const char *error; int32_t sum; if (be32toh(vp->vh_magic) != FX_LABEL_MAGIC) { - *errorp = "bad magic"; - return (true); + if (vp->vh_magic == FX_LABEL_MAGIC) + error = "wrong endianness"; + else + error = "bad magick"; + goto bad; } sum = labelsum(vp); if (sum != 0) { - *errorp = "bad checksum"; - return (true); + error = "bad checksum"; + goto bad; } return (false); +bad: if (errorp != NULL) + *errorp = error; + return (true); } static int32_t @@ -369,14 +522,18 @@ for (i = 0; i < sizeof *vp / sizeof *words; i++) sum -= be32toh(words[i]); - return sum; + return (sum); } static void -newlabel(struct volhdr *vp) +newlabel(struct volhdr *vp, int volhdrsize, int dksize) { memset(vp, 0, sizeof *vp); vp->vh_magic = FX_LABEL_MAGIC; + if (volhdrsize > dksize) + errx(1, "volume header extends beyond volume"); + setpart(vp, FX_VOLHDRPART, FX_TYPEVOLHDR, 0, volhdrsize); + setpart(vp, FX_VOLPART, FX_TYPEVOL, 0, dksize); } static const char * @@ -390,41 +547,169 @@ return (fx_typename[vp->vp_type]); } +static bool +parselabel(struct volhdr *vp, FILE *fp) +{ + const char *r; + char *p, *q; + char *line; + size_t len; + int inparts, foundparts; + int part, type, begin, size; + char partch; + int errors; + int i; + + errors = inparts = foundparts = 0; + + while (!feof(fp) && !ferror(fp) && (line = fgetln(fp, &len)) != NULL) { + if (len == 0) + continue; + line[len - 1] = '\0'; + if (strstr(line, "--- PARTITION TABLE ---") == line) { + inparts = 1; + continue; + } + if (strstr(line, "--- FOUND") == line) { + inparts = 0; + foundparts = 1; + continue; + } + if (inparts) { + p = q = line; + while (isspace((unsigned char)*p)) + p++; + if (strstr(p, "PART") == p) + continue; + part = *p++ - 'a'; + if (part < 0 || part >= FX_NPARTS) { + printf("PARTITION NUMBER %d INVALID.\n", part); + goto badpart; + } + if (!isspace((unsigned char)*p)) { + printf("WHITESPACE SHOULD FOLLOW PARTITION.\n"); + goto badpart; + } + type = (int)strtoul(p, &q, 0); + /* + * If we could not read a partition type number, or + * if the end of it is not a space, look for a type + * name. The latter is for a case like "4.2BSD" for + * the type name. + */ + if (q == p || !isspace((unsigned char)*q)) { + type = -1; + while (isspace((unsigned char)*p)) + p++; + for (i = 0; i < FX_TYPEMAX; i++) { + r = fx_typename[i]; + if (strcasestr(p, r) == NULL) + continue; + type = i; + break; + } + if (type == -1) { + printf("INVALID PARTITION TYPE.\n"); + goto badpart; + } + p += strlen(r); + } else { + p = q; + /* + * We had a type number, if a type name follows + * we must SKIP it. + */ + r = fx_typename[type]; + if ((q = strstr(p, r)) != NULL) + p = q + strlen(r); + } + begin = (int)strtoul(p, &q, 0); + if (q == p) { + printf("NO BEGIN LBN.\n"); + goto badpart; + } else + p = q; + size = (int)strtoul(p, &q, 0); + if (q == p) { + printf("NO SIZE.\n"); + goto badpart; + } + if (!isspace((unsigned char)*q) && *q != '\0') { + printf("JUNK AFTER PARTITION DEFINITION.\n"); + goto badpart; + } + /* + * We need to add this partition w/ size in blocks. + */ + size = bytesround2bsize(size) / bsize; + setpart(vp, part, type, begin, size); + continue; +badpart: printf("INVALID PARTITION: %s\n", line); + errors++; + continue; + } + if (foundparts) { + if (strstr(line, "root at") == line) { + sscanf(line, "root at %c", &partch); + part = partch - 'a'; + vp->vh_root = part; + continue; + } + if (strstr(line, "swap at") == line) { + sscanf(line, "swap at %c", &partch); + part = partch - 'a'; + vp->vh_swap = part; + continue; + } + if (strstr(line, "boots from") == line) { + /* XXX h0h0magic number inline. */ + sscanf(line, "boots from %16c", vp->vh_kernel); + continue; + } + } + } + if (errors) { + printf("DISK LABEL HAS %d ERRORS\n", errors); + return true; + } + return false; +} + static void -printlabel(struct volhdr *vp) +printlabel(struct volhdr *vp, FILE *fp) { struct volpart *part; int i, nparts; nparts = 0; - printf("--- PARTITION TABLE ---\n"); - printf("%8s %-5s %-20s %-18s %s\n", + fprintf(fp, "--- PARTITION TABLE ---\n"); + fprintf(fp, "%8s %-5s %-20s %-18s %s\n", "PART", "TYPE", "(TYPE NAME)", "BEGIN LBN", "SIZE"); for (i = 0; i < FX_NPARTS; i++) { part = &vp->vh_part[i]; if (!part->vp_size) continue; nparts++; - printf("%8c %-5d %-20s %-18d %d\n", 'a' + i, part->vp_type, + fprintf(fp, "%8c %-5d %-20s %-18d %d\n", 'a' + i, part->vp_type, parttype(part), part->vp_begin, part->vp_size); } - printf("--- FOUND %d PARTITIONS ---\n", nparts); - printf("root at %c\n", 'a' + vp->vh_root); - printf("swap at %c\n", 'a' + vp->vh_swap); + fprintf(fp, "--- FOUND %d PARTITIONS ---\n", nparts); + fprintf(fp, "root at %c\n", 'a' + vp->vh_root); + fprintf(fp, "swap at %c\n", 'a' + vp->vh_swap); if (vp->vh_kernel[0] != '\0') - printf("boots from %s\n", vp->vh_kernel); + fprintf(fp, "boots from %s\n", vp->vh_kernel); else - printf("no kernel set\n"); - dirlist(vp); + fprintf(fp, "no kernel set\n"); + fflush(fp); } static bool -readlabel(int fd) +readlabel(struct volhdr *vp, int fd) { ssize_t cnt; - cnt = pread(fd, &label, sizeof label, 0); - if (cnt < 0 || (size_t)cnt != sizeof label) { + cnt = pread(fd, vp, sizeof *vp, 0); + if (cnt < 0 || (size_t)cnt != sizeof *vp) { return (true); } else { return (false); @@ -443,7 +728,7 @@ } static int -startdisk(const char *disk, int flags) +startdisk(struct volhdr *vp, const char *disk, int flags) { const char *error; int fd; @@ -451,11 +736,11 @@ fd = dkopen(disk, flags); if (fd == -1) err(1, "%s (open)", disk); - if (readlabel(fd)) + if (readlabel(vp, fd)) err(1, "%s (label read)", disk); - if (goodlabel(&label, &error)) + if (goodlabel(vp, &error)) errx(1, "%s (label check): %s", disk, error); - swap_dec_label(&label); + swap_dec_label(vp); return (fd); } @@ -525,14 +810,11 @@ } static bool -writelabel(int fd) +writelabel(struct volhdr *vp, int fd) { const char *error; - struct volhdr *vp; ssize_t cnt; - vp = &label; - swap_enc_label(vp); sumlabel(vp); if (goodlabel(vp, &error)) @@ -553,6 +835,7 @@ " fxlabel [-d file] disk [...]\n" " fxlabel [-g file] disk [...]\n" " fxlabel [-p] disk [...]\n" +" fxlabel [-e] [-s size] disk [...]\n" " fxlabel [-w] [-s size] disk [...]\n"); exit(-1); } ==== //depot/projects/mips/sys/sys/diskfx.h#7 (text+ko) ==== @@ -32,6 +32,7 @@ #define FX_DIRSIZE 15 #define FX_NPARTS 16 #define FX_VOLHDRPART 8 +#define FX_VOLPART 9 #define FX_NAMELEN 8 static const char *fx_typename[] = { To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200302110048.h1B0mMrs006368>