Index: stable/7/gnu/usr.bin/grep =================================================================== --- stable/7/gnu/usr.bin/grep (revision 190356) +++ stable/7/gnu/usr.bin/grep (revision 190357) Property changes on: stable/7/gnu/usr.bin/grep ___________________________________________________________________ Added: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/gnu/usr.bin/grep:r187907 Index: stable/7/include =================================================================== --- stable/7/include (revision 190356) +++ stable/7/include (revision 190357) Property changes on: stable/7/include ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/include:r187724,187969 Index: stable/7/lib/libelf =================================================================== --- stable/7/lib/libelf (revision 190356) +++ stable/7/lib/libelf (revision 190357) Property changes on: stable/7/lib/libelf ___________________________________________________________________ Added: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/lib/libelf:r189721 Index: stable/7/sbin/fsck/fsck.8 =================================================================== --- stable/7/sbin/fsck/fsck.8 (revision 190356) +++ stable/7/sbin/fsck/fsck.8 (revision 190357) @@ -1,203 +1,198 @@ .\" $NetBSD: fsck.8,v 1.19 1999/03/10 00:08:33 erh Exp $ .\" .\" Copyright (c) 1996 Christos Zoulas. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by Christos Zoulas. .\" 4. The name of the author may not be used to endorse or promote products .\" derived from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd January 25, 2009 +.Dd April 25, 2001 .Dt FSCK 8 .Os .Sh NAME .Nm fsck .Nd file system consistency check and interactive repair .Sh SYNOPSIS .Nm -.Op Fl Cdfnpvy +.Op Fl dfnpvy .Op Fl B | F .Op Fl T Ar fstype : Ns Ar fsoptions .Op Fl t Ar fstype .Oo Ar special | node Oc ... .Sh DESCRIPTION The .Nm utility invokes file system-specific programs to check the special devices listed in the .Xr fstab 5 file or in the command line for consistency. .Pp It is normally used in the script .Pa /etc/rc during automatic reboot. Traditionally, .Nm is invoked before the file systems are mounted and all checks are done to completion at that time. If background checking is available, .Nm is invoked twice. It is first invoked at the traditional time, before the file systems are mounted, with the .Fl F flag to do checking on all the file systems that cannot do background checking. It is then invoked a second time, after the system has completed going multiuser, with the .Fl B flag to do checking on all the file systems that can do background checking. Unlike the foreground checking, the background checking is started asynchronously so that other system activity can proceed even on the file systems that are being checked. .Pp If no file systems are specified, .Nm reads the table .Pa /etc/fstab to determine which file systems to check. Only partitions in .Pa /etc/fstab that are mounted .Dq rw , .Dq rq or .Dq ro and that have non-zero pass number are checked. File systems with pass number 1 (normally just the root file system) are always checked one at a time. .Pp If not in preen mode, the remaining entries are checked in order of increasing pass number one at a time. This is needed when interaction with .Nm is required. .Pp In preen mode, after pass 1 completes, all remaining file systems are checked, in pass number order running one process per disk drive in parallel for each pass number in increasing order. .Pp In other words: In preen mode all pass 1 partitions are checked sequentially. Next all pass 2 partitions are checked in parallel, one process per disk drive. Next all pass 3 partitions are checked in parallel, one process per disk drive. etc. .Pp The disk drive containing each file system is inferred from the shortest prefix of the device name that ends in a digit; the remaining characters are assumed to be the partition and slice designators. .Pp The options are as follows: .Bl -tag -width indent -.It Fl C -Check if the -.Dq clean -flag is set in the superblock and skip file system checks if file system was -properly dismounted and marked clean. .It Fl d Debugging mode. Just print the commands without executing them. Available only if .Nm is compiled to support it. .It Fl f Force checking of file systems, even when they are marked clean (for file systems that support this). .It Fl n Causes .Nm to assume no as the answer to all operator questions, except "CONTINUE?". .It Fl p Enter preen mode. In preen mode, only a restricted class of innocuous file system inconsistencies will be corrected. If unexpected inconsistencies caused by hardware or software failures are encountered, the check program will exit with a failure. See the manual pages for the individual check programs for a list of the sorts of failures that they correct when running in preen mode. .It Fl F Run in foreground mode. The check program for each file system is invoked with the .Fl F flag to determine whether it wishes to run as part of the boot up sequence, or if it is able to do its job in background after the system is up and running. A non-zero exit code indicates that it wants to run in foreground and the check program is invoked. A zero exit code indicates that it is able to run later in background and just a deferred message is printed. .It Fl B Run in background mode. The check program for each file system is invoked with the .Fl F flag to determine whether it wishes to run as part of the boot up sequence, or if it is able to do its job in background after the system is up and running. A non-zero exit code indicates that it wanted to run in foreground which is assumed to have been done, so the file system is skipped. A zero exit code indicates that it is able to run in background so the check program is invoked with the .Fl B flag to indicate that a check on the active file system should be done. When running in background mode, only one file system at a time will be checked. .It Fl t Ar fstype Invoke .Nm only for the comma separated list of file system types. If the list starts with .Dq no then invoke .Nm for the file system types that are not specified in the list. .It Fl v Print the commands before executing them. .It Fl y Causes .Nm to assume yes as the answer to all operator questions. .It Fl T Ar fstype : Ns Ar fsoptions List of comma separated file system specific options for the specified file system type, in the same format as .Xr mount 8 . .El .Sh FILES .Bl -tag -width /etc/fstab -compact .It Pa /etc/fstab file system table .El .Sh SEE ALSO .Xr fstab 5 , .Xr fsck_ffs 8 , .Xr fsck_msdosfs 8 , .Xr mount 8 Index: stable/7/sbin/fsck/fsck.c =================================================================== --- stable/7/sbin/fsck/fsck.c (revision 190356) +++ stable/7/sbin/fsck/fsck.c (revision 190357) @@ -1,577 +1,574 @@ /* $NetBSD: fsck.c,v 1.21 1999/04/22 04:20:53 abs Exp $ */ /* * Copyright (c) 1996 Christos Zoulas. All rights reserved. * Copyright (c) 1980, 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * From: @(#)mount.c 8.19 (Berkeley) 4/19/94 * From: $NetBSD: mount.c,v 1.24 1995/11/18 03:34:29 cgd Exp * $NetBSD: fsck.c,v 1.21 1999/04/22 04:20:53 abs Exp $ */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #define FSTYPENAMES #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fsutil.h" static enum { IN_LIST, NOT_IN_LIST } which = NOT_IN_LIST; TAILQ_HEAD(fstypelist, entry) opthead, selhead; struct entry { char *type; char *options; TAILQ_ENTRY(entry) entries; }; static char *options = NULL; static int flags = 0; static int forceflag = 0; static int checkfs(const char *, const char *, const char *, char *, pid_t *); static int selected(const char *); static void addoption(char *); static const char *getoptions(const char *); static void addentry(struct fstypelist *, const char *, const char *); static void maketypelist(char *); static void catopt(char **, const char *); static void mangle(char *, int *, const char ***, int *); static const char *getfslab(const char *); static void usage(void) __dead2; static int isok(struct fstab *); int main(int argc, char *argv[]) { struct fstab *fs; int i, rval = 0; const char *vfstype = NULL; char globopt[3]; globopt[0] = '-'; globopt[2] = '\0'; TAILQ_INIT(&selhead); TAILQ_INIT(&opthead); - while ((i = getopt(argc, argv, "BCdvpfFnyl:t:T:")) != -1) + while ((i = getopt(argc, argv, "BdvpfFnyl:t:T:")) != -1) switch (i) { case 'B': if (flags & CHECK_BACKGRD) errx(1, "Cannot specify -B and -F."); flags |= DO_BACKGRD; break; case 'd': flags |= CHECK_DEBUG; break; case 'v': flags |= CHECK_VERBOSE; break; case 'F': if (flags & DO_BACKGRD) errx(1, "Cannot specify -B and -F."); flags |= CHECK_BACKGRD; break; case 'p': flags |= CHECK_PREEN; /*FALLTHROUGH*/ - case 'C': - flags |= CHECK_CLEAN; - /*FALLTHROUGH*/ case 'n': case 'y': globopt[1] = i; catopt(&options, globopt); break; case 'f': forceflag = 1; globopt[1] = i; catopt(&options, globopt); break; case 'l': warnx("Ignoring obsolete -l option\n"); break; case 'T': if (*optarg) addoption(optarg); break; case 't': if (!TAILQ_EMPTY(&selhead)) errx(1, "only one -t option may be specified."); maketypelist(optarg); vfstype = optarg; break; case '?': default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; if (argc == 0) return checkfstab(flags, isok, checkfs); #define BADTYPE(type) \ (strcmp(type, FSTAB_RO) && \ strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) for (; argc--; argv++) { const char *spec, *mntpt, *type, *cp; char device[MAXPATHLEN]; struct statfs *mntp; spec = *argv; cp = strrchr(spec, '/'); if (cp == 0) { (void)snprintf(device, sizeof(device), "%s%s", _PATH_DEV, spec); spec = device; } mntp = getmntpt(spec); if (mntp != NULL) { spec = mntp->f_mntfromname; mntpt = mntp->f_mntonname; } if ((fs = getfsfile(spec)) == NULL && (fs = getfsspec(spec)) == NULL) { if (vfstype == NULL) vfstype = getfslab(spec); if (vfstype == NULL) errx(1, "Could not determine filesystem type"); type = vfstype; devcheck(spec); } else { spec = fs->fs_spec; type = fs->fs_vfstype; mntpt = fs->fs_file; if (BADTYPE(fs->fs_type)) errx(1, "%s has unknown file system type.", spec); } if ((flags & CHECK_BACKGRD) && checkfs(type, spec, mntpt, "-F", NULL) == 0) { printf("%s: DEFER FOR BACKGROUND CHECKING\n", *argv); continue; } if ((flags & DO_BACKGRD) && forceflag == 0 && checkfs(type, spec, mntpt, "-F", NULL) != 0) continue; rval |= checkfs(type, spec, mntpt, NULL, NULL); } return rval; } static int isok(struct fstab *fs) { int i; if (fs->fs_passno == 0) return (0); if (BADTYPE(fs->fs_type)) return (0); if (!selected(fs->fs_vfstype)) return (0); /* * If the -B flag has been given, then process the needed * background checks. Background checks cannot be run on * file systems that will be mounted read-only or that were * not mounted at boot time (typically those marked `noauto'). * If these basic tests are passed, check with the file system * itself to see if it is willing to do background checking * by invoking its check program with the -F flag. */ if (flags & DO_BACKGRD) { if (!strcmp(fs->fs_type, FSTAB_RO)) return (0); if (getmntpt(fs->fs_spec) == NULL) return (0); if (checkfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, "-F", 0)) return (0); return (1); } /* * If the -F flag has been given, then consider deferring the * check to background. Background checks cannot be run on * file systems that will be mounted read-only or that will * not be mounted at boot time (e.g., marked `noauto'). If * these basic tests are passed, check with the file system * itself to see if it is willing to defer to background * checking by invoking its check program with the -F flag. */ if ((flags & CHECK_BACKGRD) == 0 || !strcmp(fs->fs_type, FSTAB_RO)) return (1); for (i = strlen(fs->fs_mntops) - 6; i >= 0; i--) if (!strncmp(&fs->fs_mntops[i], "noauto", 6)) break; if (i >= 0) return (1); if (checkfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, "-F", NULL) != 0) return (1); printf("%s: DEFER FOR BACKGROUND CHECKING\n", fs->fs_spec); return (0); } static int checkfs(const char *pvfstype, const char *spec, const char *mntpt, char *auxopt, pid_t *pidp) { const char **argv; pid_t pid; int argc, i, status, maxargc; char *optbuf, execbase[MAXPATHLEN]; char *vfstype = NULL; const char *extra = NULL; #ifdef __GNUC__ /* Avoid vfork clobbering */ (void) &optbuf; (void) &vfstype; #endif /* * We convert the vfstype to lowercase and any spaces to underscores * to not confuse the issue * * XXX This is a kludge to make automatic filesystem type guessing * from the disklabel work for "4.2BSD" filesystems. It does a * very limited subset of transliteration to a normalised form of * filesystem name, and we do not seem to enforce a filesystem * name character set. */ vfstype = strdup(pvfstype); if (vfstype == NULL) perror("strdup(pvfstype)"); for (i = 0; i < strlen(vfstype); i++) { vfstype[i] = tolower(vfstype[i]); if (vfstype[i] == ' ') vfstype[i] = '_'; } extra = getoptions(vfstype); optbuf = NULL; if (options) catopt(&optbuf, options); if (extra) catopt(&optbuf, extra); if (auxopt) catopt(&optbuf, auxopt); else if (flags & DO_BACKGRD) catopt(&optbuf, "-B"); maxargc = 64; argv = emalloc(sizeof(char *) * maxargc); (void) snprintf(execbase, sizeof(execbase), "fsck_%s", vfstype); argc = 0; argv[argc++] = execbase; if (optbuf) mangle(optbuf, &argc, &argv, &maxargc); argv[argc++] = spec; argv[argc] = NULL; if (flags & (CHECK_DEBUG|CHECK_VERBOSE)) { (void)printf("start %s %swait", mntpt, pidp ? "no" : ""); for (i = 0; i < argc; i++) (void)printf(" %s", argv[i]); (void)printf("\n"); } switch (pid = vfork()) { case -1: /* Error. */ warn("vfork"); if (optbuf) free(optbuf); free(vfstype); return (1); case 0: /* Child. */ if ((flags & CHECK_DEBUG) && auxopt == NULL) _exit(0); /* Go find an executable. */ execvP(execbase, _PATH_SYSPATH, (char * const *)argv); if (spec) warn("exec %s for %s in %s", execbase, spec, _PATH_SYSPATH); else warn("exec %s in %s", execbase, _PATH_SYSPATH); _exit(1); /* NOTREACHED */ default: /* Parent. */ if (optbuf) free(optbuf); free(vfstype); if (pidp) { *pidp = pid; return 0; } if (waitpid(pid, &status, 0) < 0) { warn("waitpid"); return (1); } if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) return (WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { warnx("%s: %s", spec, strsignal(WTERMSIG(status))); return (1); } break; } return (0); } static int selected(const char *type) { struct entry *e; /* If no type specified, it's always selected. */ TAILQ_FOREACH(e, &selhead, entries) if (!strncmp(e->type, type, MFSNAMELEN)) return which == IN_LIST ? 1 : 0; return which == IN_LIST ? 0 : 1; } static const char * getoptions(const char *type) { struct entry *e; TAILQ_FOREACH(e, &opthead, entries) if (!strncmp(e->type, type, MFSNAMELEN)) return e->options; return ""; } static void addoption(char *optstr) { char *newoptions; struct entry *e; if ((newoptions = strchr(optstr, ':')) == NULL) errx(1, "Invalid option string"); *newoptions++ = '\0'; TAILQ_FOREACH(e, &opthead, entries) if (!strncmp(e->type, optstr, MFSNAMELEN)) { catopt(&e->options, newoptions); return; } addentry(&opthead, optstr, newoptions); } static void addentry(struct fstypelist *list, const char *type, const char *opts) { struct entry *e; e = emalloc(sizeof(struct entry)); e->type = estrdup(type); e->options = estrdup(opts); TAILQ_INSERT_TAIL(list, e, entries); } static void maketypelist(char *fslist) { char *ptr; if ((fslist == NULL) || (fslist[0] == '\0')) errx(1, "empty type list"); if (fslist[0] == 'n' && fslist[1] == 'o') { fslist += 2; which = NOT_IN_LIST; } else which = IN_LIST; while ((ptr = strsep(&fslist, ",")) != NULL) addentry(&selhead, ptr, ""); } static void catopt(char **sp, const char *o) { char *s; size_t i, j; s = *sp; if (s) { i = strlen(s); j = i + 1 + strlen(o) + 1; s = erealloc(s, j); (void)snprintf(s + i, j, ",%s", o); } else s = estrdup(o); *sp = s; } static void mangle(char *options, int *argcp, const char ***argvp, int *maxargcp) { char *p, *s; int argc, maxargc; const char **argv; argc = *argcp; argv = *argvp; maxargc = *maxargcp; for (s = options; (p = strsep(&s, ",")) != NULL;) { /* Always leave space for one more argument and the NULL. */ if (argc >= maxargc - 3) { maxargc <<= 1; argv = erealloc(argv, maxargc * sizeof(char *)); } if (*p != '\0') { if (*p == '-') { argv[argc++] = p; p = strchr(p, '='); if (p) { *p = '\0'; argv[argc++] = p+1; } } else { argv[argc++] = "-o"; argv[argc++] = p; } } } *argcp = argc; *argvp = argv; *maxargcp = maxargc; } const static char * getfslab(const char *str) { struct disklabel dl; int fd; char p; const char *vfstype; u_char t; /* deduce the file system type from the disk label */ if ((fd = open(str, O_RDONLY)) == -1) err(1, "cannot open `%s'", str); if (ioctl(fd, DIOCGDINFO, &dl) == -1) return(NULL); (void) close(fd); p = str[strlen(str) - 1]; if ((p - 'a') >= dl.d_npartitions) errx(1, "partition `%s' is not defined on disk", str); if ((t = dl.d_partitions[p - 'a'].p_fstype) >= FSMAXTYPES) errx(1, "partition `%s' is not of a legal vfstype", str); if ((vfstype = fstypenames[t]) == NULL) errx(1, "vfstype `%s' on partition `%s' is not supported", fstypenames[t], str); return vfstype; } static void usage(void) { static const char common[] = - "[-Cdfnpvy] [-B | -F] [-T fstype:fsoptions] [-t fstype]"; + "[-dfnpvy] [-B | -F] [-T fstype:fsoptions] [-t fstype]"; (void)fprintf(stderr, "usage: %s %s [special | node] ...\n", getprogname(), common); exit(1); } Index: stable/7/sbin/fsck/fsutil.h =================================================================== --- stable/7/sbin/fsck/fsutil.h (revision 190356) +++ stable/7/sbin/fsck/fsutil.h (revision 190357) @@ -1,55 +1,54 @@ /* $NetBSD: fsutil.h,v 1.4 1998/07/26 20:02:36 mycroft Exp $ */ /* * Copyright (c) 1996 Christos Zoulas. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Christos Zoulas. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ void perror(const char *); void pfatal(const char *, ...) __printflike(1, 2); void pwarn(const char *, ...) __printflike(1, 2); void panic(const char *, ...) __dead2 __printflike(1, 2); const char *devcheck(const char *); const char *cdevname(void); void setcdevname(const char *, int); struct statfs *getmntpt(const char *); void *emalloc(size_t); void *erealloc(void *, size_t); char *estrdup(const char *); #define CHECK_PREEN 0x0001 #define CHECK_VERBOSE 0x0002 #define CHECK_DEBUG 0x0004 #define CHECK_BACKGRD 0x0008 #define DO_BACKGRD 0x0010 -#define CHECK_CLEAN 0x0020 struct fstab; int checkfstab(int, int (*)(struct fstab *), int (*) (const char *, const char *, const char *, char *, pid_t *)); Index: stable/7/sbin/fsck =================================================================== --- stable/7/sbin/fsck (revision 190356) +++ stable/7/sbin/fsck (revision 190357) Property changes on: stable/7/sbin/fsck ___________________________________________________________________ Added: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/sbin/fsck:r187931 Index: stable/7/sbin/fsck_ffs/fsck.h =================================================================== --- stable/7/sbin/fsck_ffs/fsck.h (revision 190356) +++ stable/7/sbin/fsck_ffs/fsck.h (revision 190357) @@ -1,394 +1,393 @@ /* * Copyright (c) 2002 Networks Associates Technology, Inc. * All rights reserved. * * This software was developed for the FreeBSD Project by Marshall * Kirk McKusick and Network Associates Laboratories, the Security * Research Division of Network Associates, Inc. under DARPA/SPAWAR * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS * research program. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Copyright (c) 1980, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)fsck.h 8.4 (Berkeley) 5/9/95 * $FreeBSD$ */ #include #include #include #define MAXDUP 10 /* limit on dup blks (per inode) */ #define MAXBAD 10 /* limit on bad blks (per inode) */ #define MAXBUFSPACE 40*1024 /* maximum space to allocate to buffers */ #define INOBUFSIZE 56*1024 /* size of buffer to read inodes in pass1 */ union dinode { struct ufs1_dinode dp1; struct ufs2_dinode dp2; }; #define DIP(dp, field) \ ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ (dp)->dp1.field : (dp)->dp2.field) #define DIP_SET(dp, field, val) do { \ if (sblock.fs_magic == FS_UFS1_MAGIC) \ (dp)->dp1.field = (val); \ else \ (dp)->dp2.field = (val); \ } while (0) /* * Each inode on the file system is described by the following structure. * The linkcnt is initially set to the value in the inode. Each time it * is found during the descent in passes 2, 3, and 4 the count is * decremented. Any inodes whose count is non-zero after pass 4 needs to * have its link count adjusted by the value remaining in ino_linkcnt. */ struct inostat { char ino_state; /* state of inode, see below */ char ino_type; /* type of inode */ short ino_linkcnt; /* number of links not found */ }; /* * Inode states. */ #define USTATE 0x1 /* inode not allocated */ #define FSTATE 0x2 /* inode is file */ #define FZLINK 0x3 /* inode is file with a link count of zero */ #define DSTATE 0x4 /* inode is directory */ #define DZLINK 0x5 /* inode is directory with a zero link count */ #define DFOUND 0x6 /* directory found during descent */ /* 0x7 UNUSED - see S_IS_DVALID() definition */ #define DCLEAR 0x8 /* directory is to be cleared */ #define FCLEAR 0x9 /* file is to be cleared */ /* DUNFOUND === (state == DSTATE || state == DZLINK) */ #define S_IS_DUNFOUND(state) (((state) & ~0x1) == DSTATE) /* DVALID === (state == DSTATE || state == DZLINK || state == DFOUND) */ #define S_IS_DVALID(state) (((state) & ~0x3) == DSTATE) #define INO_IS_DUNFOUND(ino) S_IS_DUNFOUND(inoinfo(ino)->ino_state) #define INO_IS_DVALID(ino) S_IS_DVALID(inoinfo(ino)->ino_state) /* * Inode state information is contained on per cylinder group lists * which are described by the following structure. */ struct inostatlist { long il_numalloced; /* number of inodes allocated in this cg */ struct inostat *il_stat;/* inostat info for this cylinder group */ } *inostathead; /* * buffer cache structure. */ struct bufarea { struct bufarea *b_next; /* free list queue */ struct bufarea *b_prev; /* free list queue */ ufs2_daddr_t b_bno; int b_size; int b_errs; int b_flags; union { char *b_buf; /* buffer space */ ufs1_daddr_t *b_indir1; /* UFS1 indirect block */ ufs2_daddr_t *b_indir2; /* UFS2 indirect block */ struct fs *b_fs; /* super block */ struct cg *b_cg; /* cylinder group */ struct ufs1_dinode *b_dinode1; /* UFS1 inode block */ struct ufs2_dinode *b_dinode2; /* UFS2 inode block */ } b_un; char b_dirty; }; #define IBLK(bp, i) \ ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ (bp)->b_un.b_indir1[i] : (bp)->b_un.b_indir2[i]) #define IBLK_SET(bp, i, val) do { \ if (sblock.fs_magic == FS_UFS1_MAGIC) \ (bp)->b_un.b_indir1[i] = (val); \ else \ (bp)->b_un.b_indir2[i] = (val); \ } while (0) #define B_INUSE 1 #define MINBUFS 5 /* minimum number of buffers required */ struct bufarea bufhead; /* head of list of other blks in filesys */ struct bufarea sblk; /* file system superblock */ struct bufarea cgblk; /* cylinder group blocks */ struct bufarea *pdirbp; /* current directory contents */ struct bufarea *pbp; /* current inode block */ #define dirty(bp) do { \ if (fswritefd < 0) \ pfatal("SETTING DIRTY FLAG IN READ_ONLY MODE\n"); \ else \ (bp)->b_dirty = 1; \ } while (0) #define initbarea(bp) do { \ (bp)->b_dirty = 0; \ (bp)->b_bno = (ufs2_daddr_t)-1; \ (bp)->b_flags = 0; \ } while (0) #define sbdirty() dirty(&sblk) #define cgdirty() dirty(&cgblk) #define sblock (*sblk.b_un.b_fs) #define cgrp (*cgblk.b_un.b_cg) enum fixstate {DONTKNOW, NOFIX, FIX, IGNORE}; ino_t cursnapshot; struct inodesc { enum fixstate id_fix; /* policy on fixing errors */ int (*id_func)(struct inodesc *); /* function to be applied to blocks of inode */ ino_t id_number; /* inode number described */ ino_t id_parent; /* for DATA nodes, their parent */ ufs_lbn_t id_lbn; /* logical block number of current block */ ufs2_daddr_t id_blkno; /* current block number being examined */ int id_numfrags; /* number of frags contained in block */ off_t id_filesize; /* for DATA nodes, the size of the directory */ ufs2_daddr_t id_entryno;/* for DATA nodes, current entry number */ int id_loc; /* for DATA nodes, current location in dir */ struct direct *id_dirp; /* for DATA nodes, ptr to current entry */ char *id_name; /* for DATA nodes, name to find or enter */ char id_type; /* type of descriptor, DATA or ADDR */ }; /* file types */ #define DATA 1 /* a directory */ #define SNAP 2 /* a snapshot */ #define ADDR 3 /* anything but a directory or a snapshot */ /* * Linked list of duplicate blocks. * * The list is composed of two parts. The first part of the * list (from duplist through the node pointed to by muldup) * contains a single copy of each duplicate block that has been * found. The second part of the list (from muldup to the end) * contains duplicate blocks that have been found more than once. * To check if a block has been found as a duplicate it is only * necessary to search from duplist through muldup. To find the * total number of times that a block has been found as a duplicate * the entire list must be searched for occurences of the block * in question. The following diagram shows a sample list where * w (found twice), x (found once), y (found three times), and z * (found once) are duplicate block numbers: * * w -> y -> x -> z -> y -> w -> y * ^ ^ * | | * duplist muldup */ struct dups { struct dups *next; ufs2_daddr_t dup; }; struct dups *duplist; /* head of dup list */ struct dups *muldup; /* end of unique duplicate dup block numbers */ /* * Inode cache data structures. */ struct inoinfo { struct inoinfo *i_nexthash; /* next entry in hash chain */ ino_t i_number; /* inode number of this entry */ ino_t i_parent; /* inode number of parent */ ino_t i_dotdot; /* inode number of `..' */ size_t i_isize; /* size of inode */ u_int i_numblks; /* size of block array in bytes */ ufs2_daddr_t i_blks[1]; /* actually longer */ } **inphead, **inpsort; long numdirs, dirhash, listmax, inplast; long countdirs; /* number of directories we actually found */ #define MIBSIZE 3 /* size of fsck sysctl MIBs */ int adjrefcnt[MIBSIZE]; /* MIB command to adjust inode reference cnt */ int adjblkcnt[MIBSIZE]; /* MIB command to adjust inode block count */ int adjndir[MIBSIZE]; /* MIB command to adjust number of directories */ int adjnbfree[MIBSIZE]; /* MIB command to adjust number of free blocks */ int adjnifree[MIBSIZE]; /* MIB command to adjust number of free inodes */ int adjnffree[MIBSIZE]; /* MIB command to adjust number of free frags */ int adjnumclusters[MIBSIZE]; /* MIB command to adjust number of free clusters */ int freefiles[MIBSIZE]; /* MIB command to free a set of files */ int freedirs[MIBSIZE]; /* MIB command to free a set of directories */ int freeblks[MIBSIZE]; /* MIB command to free a set of data blocks */ struct fsck_cmd cmd; /* sysctl file system update commands */ char snapname[BUFSIZ]; /* when doing snapshots, the name of the file */ char *cdevname; /* name of device being checked */ long dev_bsize; /* computed value of DEV_BSIZE */ long secsize; /* actual disk sector size */ char nflag; /* assume a no response */ char yflag; /* assume a yes response */ int bkgrdflag; /* use a snapshot to run on an active system */ int bflag; /* location of alternate super block */ int debug; /* output debugging info */ char damagedflag; /* run in damaged mode */ -char ckclean; /* only do work if not cleanly unmounted */ int cvtlevel; /* convert to newer file system format */ int bkgrdcheck; /* determine if background check is possible */ int bkgrdsumadj; /* whether the kernel have ability to adjust superblock summary */ char usedsoftdep; /* just fix soft dependency inconsistencies */ char preen; /* just fix normal inconsistencies */ char rerun; /* rerun fsck. Only used in non-preen mode */ int returntosingle; /* 1 => return to single user mode on exit */ char resolved; /* cleared if unresolved changes => not clean */ char havesb; /* superblock has been read */ char skipclean; /* skip clean file systems if preening */ int fsmodified; /* 1 => write done to file system */ int fsreadfd; /* file descriptor for reading file system */ int fswritefd; /* file descriptor for writing file system */ ufs2_daddr_t maxfsblock; /* number of blocks in the file system */ char *blockmap; /* ptr to primary blk allocation map */ ino_t maxino; /* number of inodes in file system */ ino_t lfdir; /* lost & found directory inode number */ const char *lfname; /* lost & found directory name */ int lfmode; /* lost & found directory creation mode */ ufs2_daddr_t n_blks; /* number of blocks in use */ ino_t n_files; /* number of files in use */ int got_siginfo; /* received a SIGINFO */ int got_sigalarm; /* received a SIGALRM */ #define clearinode(dp) \ if (sblock.fs_magic == FS_UFS1_MAGIC) { \ (dp)->dp1 = ufs1_zino; \ } else { \ (dp)->dp2 = ufs2_zino; \ } struct ufs1_dinode ufs1_zino; struct ufs2_dinode ufs2_zino; #define setbmap(blkno) setbit(blockmap, blkno) #define testbmap(blkno) isset(blockmap, blkno) #define clrbmap(blkno) clrbit(blockmap, blkno) #define STOP 0x01 #define SKIP 0x02 #define KEEPON 0x04 #define ALTERED 0x08 #define FOUND 0x10 #define EEXIT 8 /* Standard error exit. */ struct fstab; void adjust(struct inodesc *, int lcnt); ufs2_daddr_t allocblk(long frags); ino_t allocdir(ino_t parent, ino_t request, int mode); ino_t allocino(ino_t request, int type); void blkerror(ino_t ino, const char *type, ufs2_daddr_t blk); char *blockcheck(char *name); int blread(int fd, char *buf, ufs2_daddr_t blk, long size); void bufinit(void); void blwrite(int fd, char *buf, ufs2_daddr_t blk, long size); void cacheino(union dinode *dp, ino_t inumber); void catch(int); void catchquit(int); int changeino(ino_t dir, const char *name, ino_t newnum); void check_cgmagic(int cg, struct cg *cgp); int chkrange(ufs2_daddr_t blk, int cnt); void ckfini(int markclean); int ckinode(union dinode *dp, struct inodesc *); void clri(struct inodesc *, const char *type, int flag); int clearentry(struct inodesc *); void direrror(ino_t ino, const char *errmesg); int dirscan(struct inodesc *); int dofix(struct inodesc *, const char *msg); int eascan(struct inodesc *, struct ufs2_dinode *dp); void ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t); void ffs_fragacct(struct fs *, int, int32_t [], int); int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t); void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t); void fileerror(ino_t cwd, ino_t ino, const char *errmesg); int findino(struct inodesc *); int findname(struct inodesc *); void flush(int fd, struct bufarea *bp); void freeblk(ufs2_daddr_t blkno, long frags); void freeino(ino_t ino); void freeinodebuf(void); int ftypeok(union dinode *dp); void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size); struct bufarea *getdatablk(ufs2_daddr_t blkno, long size); struct inoinfo *getinoinfo(ino_t inumber); union dinode *getnextinode(ino_t inumber); void getpathname(char *namebuf, ino_t curdir, ino_t ino); union dinode *ginode(ino_t inumber); void infohandler(int sig); void alarmhandler(int sig); void inocleanup(void); void inodirty(void); struct inostat *inoinfo(ino_t inum); int linkup(ino_t orphan, ino_t parentdir, char *name); int makeentry(ino_t parent, ino_t ino, const char *name); void panic(const char *fmt, ...) __printflike(1, 2); void pass1(void); void pass1b(void); int pass1check(struct inodesc *); void pass2(void); void pass3(void); void pass4(void); int pass4check(struct inodesc *); void pass5(void); void pfatal(const char *fmt, ...) __printflike(1, 2); void pinode(ino_t ino); void propagate(void); void pwarn(const char *fmt, ...) __printflike(1, 2); int readsb(int listerr); int reply(const char *question); void rwerror(const char *mesg, ufs2_daddr_t blk); void sblock_init(void); void setinodebuf(ino_t); int setup(char *dev); void gjournal_check(const char *filesys); Index: stable/7/sbin/fsck_ffs/fsck_ffs.8 =================================================================== --- stable/7/sbin/fsck_ffs/fsck_ffs.8 (revision 190356) +++ stable/7/sbin/fsck_ffs/fsck_ffs.8 (revision 190357) @@ -1,345 +1,337 @@ .\" .\" Copyright (c) 1980, 1989, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)fsck.8 8.4 (Berkeley) 5/9/95 .\" $FreeBSD$ .\" -.Dd January 25, 2009 +.Dd January 20, 2009 .Dt FSCK_FFS 8 .Os .Sh NAME .Nm fsck_ffs , .Nm fsck_ufs .Nd file system consistency check and interactive repair .Sh SYNOPSIS .Nm .Op Fl BDFpfny .Op Fl b Ar block .Op Fl c Ar level .Op Fl m Ar mode .Ar filesystem .Ar ... .Sh DESCRIPTION The specified disk partitions and/or file systems are checked. -In "preen" or "check clean" mode the clean flag of each file system's -superblock is examined and only those file systems that are not marked clean -are checked. +In "preen" mode the clean flag of each file system's superblock is examined +and only those file systems that +are not marked clean are checked. File systems are marked clean when they are unmounted, when they have been mounted read-only, or when .Nm runs on them successfully. If the .Fl f option is specified, the file systems will be checked regardless of the state of their clean flag. .Pp The kernel takes care that only a restricted class of innocuous file system inconsistencies can happen unless hardware or software failures intervene. These are limited to the following: .Pp .Bl -item -compact -offset indent .It Unreferenced inodes .It Link counts in inodes too large .It Missing blocks in the free map .It Blocks in the free map also in files .It Counts in the super-block wrong .El .Pp These are the only inconsistencies that .Nm with the .Fl p option will correct; if it encounters other inconsistencies, it exits with an abnormal return status and an automatic reboot will then fail. For each corrected inconsistency one or more lines will be printed identifying the file system on which the correction will take place, and the nature of the correction. After successfully correcting a file system, .Nm will print the number of files on that file system, the number of used and free blocks, and the percentage of fragmentation. .Pp If sent a .Dv QUIT signal, .Nm will finish the file system checks, then exit with an abnormal return status that causes an automatic reboot to fail. This is useful when you want to finish the file system checks during an automatic reboot, but do not want the machine to come up multiuser after the checks complete. .Pp If .Nm receives a .Dv SIGINFO (see the .Dq status argument for .Xr stty 1 ) signal, a line will be written to the standard output indicating the name of the device currently being checked, the current phase number and phase-specific progress information. .Pp Without the .Fl p option, .Nm audits and interactively repairs inconsistent conditions for file systems. If the file system is inconsistent the operator is prompted for concurrence before each correction is attempted. It should be noted that some of the corrective actions which are not correctable under the .Fl p option will result in some loss of data. The amount and severity of data lost may be determined from the diagnostic output. The default action for each consistency correction is to wait for the operator to respond .Li yes or .Li no . If the operator does not have write permission on the file system .Nm will default to a .Fl n action. .Pp The following flags are interpreted by .Nm : .Bl -tag -width indent .It Fl F Determine whether the file system needs to be cleaned immediately in foreground, or if its cleaning can be deferred to background. To be eligible for background cleaning it must have been running with soft updates, not have been marked as needing a foreground check, and be mounted and writable when the background check is to be done. If these conditions are met, then .Nm exits with a zero exit status. Otherwise it exits with a non-zero exit status. If the file system is clean, it will exit with a non-zero exit status so that the clean status of the file system can be verified and reported during the foreground checks. Note that when invoked with the .Fl F flag, no cleanups are done. The only thing that .Nm does is to determine whether a foreground or background check is needed and exit with an appropriate status code. .It Fl B A check is done on the specified and possibly active file system. The set of corrections that can be done is limited to those done when running in preen mode (see the .Fl p flag). If unexpected errors are found, the file system is marked as needing a foreground check and .Nm exits without attempting any further cleaning. .It Fl b Use the block specified immediately after the flag as the super block for the file system. An alternate super block is usually located at block 32 for UFS1, and block 160 for UFS2. -.It Fl C -Check if file system was dismouted cleanly. -If so, skip file system checks (like "preen"). -However, if the file system was not cleanly dismounted, do full checks, -is if -.Nm -was invoked without -.Fl C . .It Fl c Convert the file system to the specified level. Note that the level of a file system can only be raised. There are currently four levels defined: .Bl -tag -width indent .It 0 The file system is in the old (static table) format. .It 1 The file system is in the new (dynamic table) format. .It 2 The file system supports 32-bit uid's and gid's, short symbolic links are stored in the inode, and directories have an added field showing the file type. .It 3 If maxcontig is greater than one, build the free segment maps to aid in finding contiguous sets of blocks. If maxcontig is equal to one, delete any existing segment maps. .El .Pp In interactive mode, .Nm will list the conversion to be made and ask whether the conversion should be done. If a negative answer is given, no further operations are done on the file system. In preen mode, the conversion is listed and done if possible without user interaction. Conversion in preen mode is best used when all the file systems are being converted at once. The format of a file system can be determined from the first line of output from .Xr dumpfs 8 . .It Fl D Run .Nm in 'damaged recovery' mode, which will enable certain aggressive operations that can make .Nm to survive with file systems that has very serious data damage, which is an useful last resort when on disk data damage is very serious and causes .Nm to crash otherwise. Be .Em very careful using this flag, it is dangerous if there are data transmission hazards because a false positive cylinder group magic number mismatch could cause .Em irrevertible data loss! .Pp This option implies the .Fl f flag. .It Fl f Force .Nm to check .Sq clean file systems when preening. .It Fl m Use the mode specified in octal immediately after the flag as the permission bits to use when creating the .Pa lost+found directory rather than the default 1777. In particular, systems that do not wish to have lost files accessible by all users on the system should use a more restrictive set of permissions such as 700. .It Fl n Assume a no response to all questions asked by .Nm except for .Ql CONTINUE? , which is assumed to be affirmative; do not open the file system for writing. .It Fl p Preen file systems (see above). .It Fl y Assume a yes response to all questions asked by .Nm ; this should be used with great caution as this is a free license to continue after essentially unlimited trouble has been encountered. .El .Pp Inconsistencies checked are as follows: .Pp .Bl -enum -compact .It Blocks claimed by more than one inode or the free map. .It Blocks claimed by an inode outside the range of the file system. .It Incorrect link counts. .It Size checks: .Bl -item -offset indent -compact .It Directory size not a multiple of DIRBLKSIZ. .It Partially truncated file. .El .It Bad inode format. .It Blocks not accounted for anywhere. .It Directory checks: .Bl -item -offset indent -compact .It File pointing to unallocated inode. .It Inode number out of range. .It Directories with unallocated blocks (holes). .It Dot or dot-dot not the first two entries of a directory or having the wrong inode number. .El .It Super Block checks: .Bl -item -offset indent -compact .It More blocks for inodes than there are in the file system. .It Bad free block map format. .It Total free block and/or free inode count incorrect. .El .El .Pp Orphaned files and directories (allocated but unreferenced) are, with the operator's concurrence, reconnected by placing them in the .Pa lost+found directory. The name assigned is the inode number. If the .Pa lost+found directory does not exist, it is created. If there is insufficient space its size is increased. .Sh FILES .Bl -tag -width /etc/fstab -compact .It Pa /etc/fstab contains default list of file systems to check. .El .Sh EXIT STATUS .Ex -std .Sh DIAGNOSTICS The diagnostics produced by .Nm are fully enumerated and explained in Appendix A of .Rs .%T "Fsck \- The UNIX File System Check Program" .Re .Sh SEE ALSO .Xr fs 5 , .Xr fstab 5 , .Xr fsck 8 , .Xr fsdb 8 , .Xr newfs 8 , .Xr reboot 8 Index: stable/7/sbin/fsck_ffs/main.c =================================================================== --- stable/7/sbin/fsck_ffs/main.c (revision 190356) +++ stable/7/sbin/fsck_ffs/main.c (revision 190357) @@ -1,626 +1,622 @@ /* * Copyright (c) 1980, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1986, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fsck.h" static void usage(void) __dead2; static int argtoi(int flag, const char *req, const char *str, int base); static int checkfilesys(char *filesys); static int chkdoreload(struct statfs *mntp); static struct statfs *getmntpt(const char *); int main(int argc, char *argv[]) { int ch; struct rlimit rlimit; struct itimerval itimerval; int ret = 0; sync(); skipclean = 1; damagedflag = 0; - while ((ch = getopt(argc, argv, "b:Bc:CdDfFm:npy")) != -1) { + while ((ch = getopt(argc, argv, "b:Bc:dDfFm:npy")) != -1) { switch (ch) { case 'b': skipclean = 0; bflag = argtoi('b', "number", optarg, 10); printf("Alternate super block location: %d\n", bflag); break; case 'B': bkgrdflag = 1; break; case 'c': skipclean = 0; cvtlevel = argtoi('c', "conversion level", optarg, 10); if (cvtlevel < 3) errx(EEXIT, "cannot do level %d conversion", cvtlevel); break; case 'd': debug++; break; case 'D': damagedflag = 1; /* FALLTHROUGH */ case 'f': skipclean = 0; break; case 'F': bkgrdcheck = 1; break; case 'm': lfmode = argtoi('m', "mode", optarg, 8); if (lfmode &~ 07777) errx(EEXIT, "bad mode to -m: %o", lfmode); printf("** lost+found creation mode %o\n", lfmode); break; case 'n': nflag++; yflag = 0; break; case 'p': preen++; - /*FALLTHROUGH*/ - - case 'C': - ckclean++; break; case 'y': yflag++; nflag = 0; break; default: usage(); } } argc -= optind; argv += optind; if (!argc) usage(); if (signal(SIGINT, SIG_IGN) != SIG_IGN) (void)signal(SIGINT, catch); - if (ckclean) + if (preen) (void)signal(SIGQUIT, catchquit); signal(SIGINFO, infohandler); if (bkgrdflag) { signal(SIGALRM, alarmhandler); itimerval.it_interval.tv_sec = 5; itimerval.it_interval.tv_usec = 0; itimerval.it_value.tv_sec = 5; itimerval.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itimerval, NULL); } /* * Push up our allowed memory limit so we can cope * with huge file systems. */ if (getrlimit(RLIMIT_DATA, &rlimit) == 0) { rlimit.rlim_cur = rlimit.rlim_max; (void)setrlimit(RLIMIT_DATA, &rlimit); } while (argc-- > 0) (void)checkfilesys(*argv++); if (returntosingle) ret = 2; exit(ret); } static int argtoi(int flag, const char *req, const char *str, int base) { char *cp; int ret; ret = (int)strtol(str, &cp, base); if (cp == str || *cp) errx(EEXIT, "-%c flag requires a %s", flag, req); return (ret); } /* * Check the specified file system. */ /* ARGSUSED */ static int checkfilesys(char *filesys) { ufs2_daddr_t n_ffree, n_bfree; struct dups *dp; struct statfs *mntp; struct stat snapdir; struct group *grp; ufs2_daddr_t blks; struct iovec *iov; char errmsg[255]; int iovlen; int fflags; int cylno; ino_t files; size_t size; iov = NULL; iovlen = 0; errmsg[0] = '\0'; cdevname = filesys; - if (debug && ckclean) + if (debug && preen) pwarn("starting\n"); /* * Make best effort to get the disk name. Check first to see * if it is listed among the mounted file systems. Failing that * check to see if it is listed in /etc/fstab. */ mntp = getmntpt(filesys); if (mntp != NULL) filesys = mntp->f_mntfromname; else filesys = blockcheck(filesys); /* * If -F flag specified, check to see whether a background check * is possible and needed. If possible and needed, exit with * status zero. Otherwise exit with status non-zero. A non-zero * exit status will cause a foreground check to be run. */ sblock_init(); if (bkgrdcheck) { if ((fsreadfd = open(filesys, O_RDONLY)) < 0 || readsb(0) == 0) exit(3); /* Cannot read superblock */ close(fsreadfd); if (sblock.fs_flags & FS_NEEDSFSCK) exit(4); /* Earlier background failed */ if ((sblock.fs_flags & FS_DOSOFTDEP) == 0) exit(5); /* Not running soft updates */ size = MIBSIZE; if (sysctlnametomib("vfs.ffs.adjrefcnt", adjrefcnt, &size) < 0) exit(6); /* Lacks kernel support */ if ((mntp == NULL && sblock.fs_clean == 1) || (mntp != NULL && (sblock.fs_flags & FS_UNCLEAN) == 0)) exit(7); /* Filesystem clean, report it now */ exit(0); } - if (ckclean && skipclean) { + if (preen && skipclean) { /* * If file system is gjournaled, check it here. */ if ((fsreadfd = open(filesys, O_RDONLY)) < 0 || readsb(0) == 0) exit(3); /* Cannot read superblock */ close(fsreadfd); if ((sblock.fs_flags & FS_GJOURNAL) != 0) { //printf("GJournaled file system detected on %s.\n", // filesys); if (sblock.fs_clean == 1) { pwarn("FILE SYSTEM CLEAN; SKIPPING CHECKS\n"); exit(0); } if ((sblock.fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) == 0) { gjournal_check(filesys); if (chkdoreload(mntp) == 0) exit(0); exit(4); } else { pfatal("UNEXPECTED INCONSISTENCY, %s\n", "CANNOT RUN FAST FSCK\n"); } } } /* * If we are to do a background check: * Get the mount point information of the file system * create snapshot file * return created snapshot file * if not found, clear bkgrdflag and proceed with normal fsck */ if (bkgrdflag) { if (mntp == NULL) { bkgrdflag = 0; pfatal("NOT MOUNTED, CANNOT RUN IN BACKGROUND\n"); } else if ((mntp->f_flags & MNT_SOFTDEP) == 0) { bkgrdflag = 0; pfatal("NOT USING SOFT UPDATES, %s\n", "CANNOT RUN IN BACKGROUND"); } else if ((mntp->f_flags & MNT_RDONLY) != 0) { bkgrdflag = 0; pfatal("MOUNTED READ-ONLY, CANNOT RUN IN BACKGROUND\n"); } else if ((fsreadfd = open(filesys, O_RDONLY)) >= 0) { if (readsb(0) != 0) { if (sblock.fs_flags & FS_NEEDSFSCK) { bkgrdflag = 0; pfatal("UNEXPECTED INCONSISTENCY, %s\n", "CANNOT RUN IN BACKGROUND\n"); } if ((sblock.fs_flags & FS_UNCLEAN) == 0 && - skipclean && ckclean) { + skipclean && preen) { /* * file system is clean; * skip snapshot and report it clean */ pwarn("FILE SYSTEM CLEAN; %s\n", "SKIPPING CHECKS"); goto clean; } } close(fsreadfd); } if (bkgrdflag) { snprintf(snapname, sizeof snapname, "%s/.snap", mntp->f_mntonname); if (stat(snapname, &snapdir) < 0) { if (errno != ENOENT) { bkgrdflag = 0; pfatal("CANNOT FIND %s %s: %s, %s\n", "SNAPSHOT DIRECTORY", snapname, strerror(errno), "CANNOT RUN IN BACKGROUND"); } else if ((grp = getgrnam("operator")) == 0 || mkdir(snapname, 0770) < 0 || chown(snapname, -1, grp->gr_gid) < 0 || chmod(snapname, 0770) < 0) { bkgrdflag = 0; pfatal("CANNOT CREATE %s %s: %s, %s\n", "SNAPSHOT DIRECTORY", snapname, strerror(errno), "CANNOT RUN IN BACKGROUND"); } } else if (!S_ISDIR(snapdir.st_mode)) { bkgrdflag = 0; pfatal("%s IS NOT A DIRECTORY, %s\n", snapname, "CANNOT RUN IN BACKGROUND"); } } if (bkgrdflag) { snprintf(snapname, sizeof snapname, "%s/.snap/fsck_snapshot", mntp->f_mntonname); fflags = mntp->f_flags; /* * XXX: Need to kick out MNT_ROOTFS until we fix * nmount(). */ fflags &= ~MNT_ROOTFS; fflags = fflags | MNT_UPDATE | MNT_SNAPSHOT; build_iovec(&iov, &iovlen, "fstype", "ffs", 4); build_iovec(&iov, &iovlen, "from", snapname, (size_t)-1); build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname, (size_t)-1); build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); while (nmount(iov, iovlen, fflags) < 0) { if (errno == EEXIST && unlink(snapname) == 0) continue; bkgrdflag = 0; pfatal("CANNOT CREATE SNAPSHOT %s: %s %s\n", snapname, strerror(errno), errmsg); break; } if (bkgrdflag != 0) filesys = snapname; } } switch (setup(filesys)) { case 0: if (preen) pfatal("CAN'T CHECK FILE SYSTEM."); return (0); case -1: clean: pwarn("clean, %ld free ", (long)(sblock.fs_cstotal.cs_nffree + sblock.fs_frag * sblock.fs_cstotal.cs_nbfree)); printf("(%lld frags, %lld blocks, %.1f%% fragmentation)\n", (long long)sblock.fs_cstotal.cs_nffree, (long long)sblock.fs_cstotal.cs_nbfree, sblock.fs_cstotal.cs_nffree * 100.0 / sblock.fs_dsize); return (0); } /* * Cleared if any questions answered no. Used to decide if * the superblock should be marked clean. */ resolved = 1; /* * 1: scan inodes tallying blocks used */ if (preen == 0) { printf("** Last Mounted on %s\n", sblock.fs_fsmnt); if (mntp != NULL && mntp->f_flags & MNT_ROOTFS) printf("** Root file system\n"); printf("** Phase 1 - Check Blocks and Sizes\n"); } pass1(); /* * 1b: locate first references to duplicates, if any */ if (duplist) { if (preen || usedsoftdep) pfatal("INTERNAL ERROR: dups with -p"); printf("** Phase 1b - Rescan For More DUPS\n"); pass1b(); } /* * 2: traverse directories from root to mark all connected directories */ if (preen == 0) printf("** Phase 2 - Check Pathnames\n"); pass2(); /* * 3: scan inodes looking for disconnected directories */ if (preen == 0) printf("** Phase 3 - Check Connectivity\n"); pass3(); /* * 4: scan inodes looking for disconnected files; check reference counts */ if (preen == 0) printf("** Phase 4 - Check Reference Counts\n"); pass4(); /* * 5: check and repair resource counts in cylinder groups */ if (preen == 0) printf("** Phase 5 - Check Cyl groups\n"); pass5(); /* * print out summary statistics */ n_ffree = sblock.fs_cstotal.cs_nffree; n_bfree = sblock.fs_cstotal.cs_nbfree; files = maxino - ROOTINO - sblock.fs_cstotal.cs_nifree - n_files; blks = n_blks + sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); blks += howmany(sblock.fs_cssize, sblock.fs_fsize); blks = maxfsblock - (n_ffree + sblock.fs_frag * n_bfree) - blks; if (bkgrdflag && (files > 0 || blks > 0)) { countdirs = sblock.fs_cstotal.cs_ndir - countdirs; pwarn("Reclaimed: %ld directories, %ld files, %lld fragments\n", countdirs, (long)files - countdirs, (long long)blks); } pwarn("%ld files, %jd used, %ju free ", (long)n_files, (intmax_t)n_blks, (uintmax_t)n_ffree + sblock.fs_frag * n_bfree); printf("(%ju frags, %ju blocks, %.1f%% fragmentation)\n", (uintmax_t)n_ffree, (uintmax_t)n_bfree, n_ffree * 100.0 / sblock.fs_dsize); if (debug) { if (files < 0) printf("%d inodes missing\n", -files); if (blks < 0) printf("%lld blocks missing\n", -(long long)blks); if (duplist != NULL) { printf("The following duplicate blocks remain:"); for (dp = duplist; dp; dp = dp->next) printf(" %lld,", (long long)dp->dup); printf("\n"); } } duplist = (struct dups *)0; muldup = (struct dups *)0; inocleanup(); if (fsmodified) { sblock.fs_time = time(NULL); sbdirty(); } if (cvtlevel && sblk.b_dirty) { /* * Write out the duplicate super blocks */ for (cylno = 0; cylno < sblock.fs_ncg; cylno++) blwrite(fswritefd, (char *)&sblock, fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBLOCKSIZE); } if (rerun) resolved = 0; /* * Check to see if the file system is mounted read-write. */ if (bkgrdflag == 0 && mntp != NULL && (mntp->f_flags & MNT_RDONLY) == 0) resolved = 0; ckfini(resolved); for (cylno = 0; cylno < sblock.fs_ncg; cylno++) if (inostathead[cylno].il_stat != NULL) free((char *)inostathead[cylno].il_stat); free((char *)inostathead); inostathead = NULL; if (fsmodified && !preen) printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); if (rerun) printf("\n***** PLEASE RERUN FSCK *****\n"); if (chkdoreload(mntp) != 0) { if (!fsmodified) return (0); if (!preen) printf("\n***** REBOOT NOW *****\n"); sync(); return (4); } return (0); } static int chkdoreload(struct statfs *mntp) { struct iovec *iov; int iovlen; int fflags; char errmsg[255]; if (mntp == NULL) return (0); iov = NULL; iovlen = 0; errmsg[0] = '\0'; fflags = mntp->f_flags; /* * We modified a mounted file system. Do a mount update on * it unless it is read-write, so we can continue using it * as safely as possible. */ if (mntp->f_flags & MNT_RDONLY) { /* * XXX: Need to kick out MNT_ROOTFS until we fix * nmount(). */ fflags &= ~MNT_ROOTFS; fflags = fflags | MNT_RELOAD; build_iovec(&iov, &iovlen, "fstype", "ffs", 4); build_iovec(&iov, &iovlen, "from", mntp->f_mntfromname, (size_t)-1); build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname, (size_t)-1); build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); build_iovec(&iov, &iovlen, "update", NULL, 0); /* * XX: We need the following line until we clean up * nmount parsing of root mounts and NFS root mounts. */ build_iovec(&iov, &iovlen, "ro", NULL, 0); if (nmount(iov, iovlen, fflags) == 0) { return (0); } pwarn("mount reload of '%s' failed: %s %s\n\n", mntp->f_mntonname, strerror(errno), errmsg); return (1); } return (0); } /* * Get the mount point information for name. */ static struct statfs * getmntpt(const char *name) { struct stat devstat, mntdevstat; char device[sizeof(_PATH_DEV) - 1 + MNAMELEN]; char *ddevname; struct statfs *mntbuf, *statfsp; int i, mntsize, isdev; if (stat(name, &devstat) != 0) return (NULL); if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode)) isdev = 1; else isdev = 0; mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); for (i = 0; i < mntsize; i++) { statfsp = &mntbuf[i]; ddevname = statfsp->f_mntfromname; if (*ddevname != '/') { strcpy(device, _PATH_DEV); strcat(device, ddevname); strcpy(statfsp->f_mntfromname, device); } if (isdev == 0) { if (strcmp(name, statfsp->f_mntonname)) continue; return (statfsp); } if (stat(ddevname, &mntdevstat) == 0 && mntdevstat.st_rdev == devstat.st_rdev) return (statfsp); } statfsp = NULL; return (statfsp); } static void usage(void) { (void) fprintf(stderr, "usage: %s [-BCFpfny] [-b block] [-c level] [-m mode] " "filesystem ...\n", getprogname()); exit(1); } Index: stable/7/sbin/fsck_ffs/setup.c =================================================================== --- stable/7/sbin/fsck_ffs/setup.c (revision 190356) +++ stable/7/sbin/fsck_ffs/setup.c (revision 190357) @@ -1,533 +1,533 @@ /* * Copyright (c) 1980, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static const char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #define FSTYPENAMES #include #include #include #include #include #include #include #include #include #include #include #include "fsck.h" struct bufarea asblk; #define altsblock (*asblk.b_un.b_fs) #define POWEROF2(num) (((num) & ((num) - 1)) == 0) static void badsb(int listerr, const char *s); static int calcsb(char *dev, int devfd, struct fs *fs); static struct disklabel *getdisklabel(char *s, int fd); /* * Read in a superblock finding an alternate if necessary. * Return 1 if successful, 0 if unsuccessful, -1 if file system - * is already clean (ckclean and preen mode only). + * is already clean (preen mode only). */ int setup(char *dev) { long cg, asked, i, j; long bmapsize; struct stat statb; struct fs proto; size_t size; havesb = 0; fswritefd = -1; cursnapshot = 0; if (stat(dev, &statb) < 0) { printf("Can't stat %s: %s\n", dev, strerror(errno)); if (bkgrdflag) { unlink(snapname); bkgrdflag = 0; } return (0); } if ((statb.st_mode & S_IFMT) != S_IFCHR && (statb.st_mode & S_IFMT) != S_IFBLK) { if (bkgrdflag != 0 && (statb.st_flags & SF_SNAPSHOT) == 0) { unlink(snapname); printf("background fsck lacks a snapshot\n"); exit(EEXIT); } if ((statb.st_flags & SF_SNAPSHOT) != 0 && cvtlevel == 0) { cursnapshot = statb.st_ino; } else { if (cvtlevel == 0 || (statb.st_flags & SF_SNAPSHOT) == 0) { if (preen && bkgrdflag) { unlink(snapname); bkgrdflag = 0; } pfatal("%s is not a disk device", dev); if (reply("CONTINUE") == 0) { if (bkgrdflag) { unlink(snapname); bkgrdflag = 0; } return (0); } } else { if (bkgrdflag) { unlink(snapname); bkgrdflag = 0; } pfatal("cannot convert a snapshot"); exit(EEXIT); } } } if ((fsreadfd = open(dev, O_RDONLY)) < 0) { if (bkgrdflag) { unlink(snapname); bkgrdflag = 0; } printf("Can't open %s: %s\n", dev, strerror(errno)); return (0); } if (bkgrdflag) { unlink(snapname); size = MIBSIZE; if (sysctlnametomib("vfs.ffs.adjrefcnt", adjrefcnt, &size) < 0|| sysctlnametomib("vfs.ffs.adjblkcnt", adjblkcnt, &size) < 0|| sysctlnametomib("vfs.ffs.freefiles", freefiles, &size) < 0|| sysctlnametomib("vfs.ffs.freedirs", freedirs, &size) < 0 || sysctlnametomib("vfs.ffs.freeblks", freeblks, &size) < 0) { pfatal("kernel lacks background fsck support\n"); exit(EEXIT); } /* * When kernel is lack of runtime bgfsck superblock summary * adjustment functionality, it does not mean we can not * continue, as old kernels will recompute the summary at * mount time. However, it will be an unexpected softupdates * inconsistency if it turns out that the summary is still * incorrect. Set a flag so subsequent operation can know * this. */ bkgrdsumadj = 1; if (sysctlnametomib("vfs.ffs.adjndir", adjndir, &size) < 0 || sysctlnametomib("vfs.ffs.adjnbfree", adjnbfree, &size) < 0 || sysctlnametomib("vfs.ffs.adjnifree", adjnifree, &size) < 0 || sysctlnametomib("vfs.ffs.adjnffree", adjnffree, &size) < 0 || sysctlnametomib("vfs.ffs.adjnumclusters", adjnumclusters, &size) < 0) { bkgrdsumadj = 0; pwarn("kernel lacks runtime superblock summary adjustment support"); } cmd.version = FFS_CMD_VERSION; cmd.handle = fsreadfd; fswritefd = -1; } if (preen == 0) printf("** %s", dev); if (bkgrdflag == 0 && (nflag || (fswritefd = open(dev, O_WRONLY)) < 0)) { fswritefd = -1; if (preen) pfatal("NO WRITE ACCESS"); printf(" (NO WRITE)"); } if (preen == 0) printf("\n"); /* * Read in the superblock, looking for alternates if necessary */ if (readsb(1) == 0) { skipclean = 0; if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0) return(0); if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0) return (0); for (cg = 0; cg < proto.fs_ncg; cg++) { bflag = fsbtodb(&proto, cgsblock(&proto, cg)); if (readsb(0) != 0) break; } if (cg >= proto.fs_ncg) { printf("%s %s\n%s %s\n%s %s\n", "SEARCH FOR ALTERNATE SUPER-BLOCK", "FAILED. YOU MUST USE THE", "-b OPTION TO FSCK TO SPECIFY THE", "LOCATION OF AN ALTERNATE", "SUPER-BLOCK TO SUPPLY NEEDED", "INFORMATION; SEE fsck(8)."); bflag = 0; return(0); } pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag); bflag = 0; } - if (skipclean && ckclean && sblock.fs_clean) { + if (skipclean && preen && sblock.fs_clean) { pwarn("FILE SYSTEM CLEAN; SKIPPING CHECKS\n"); return (-1); } maxfsblock = sblock.fs_size; maxino = sblock.fs_ncg * sblock.fs_ipg; /* * Check and potentially fix certain fields in the super block. */ if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) { pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK"); if (reply("SET TO DEFAULT") == 1) { sblock.fs_optim = FS_OPTTIME; sbdirty(); } } if ((sblock.fs_minfree < 0 || sblock.fs_minfree > 99)) { pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK", sblock.fs_minfree); if (reply("SET TO DEFAULT") == 1) { sblock.fs_minfree = 10; sbdirty(); } } if (sblock.fs_magic == FS_UFS1_MAGIC && sblock.fs_old_inodefmt < FS_44INODEFMT) { pwarn("Format of file system is too old.\n"); pwarn("Must update to modern format using a version of fsck\n"); pfatal("from before 2002 with the command ``fsck -c 2''\n"); exit(EEXIT); } if (asblk.b_dirty && !bflag) { memmove(&altsblock, &sblock, (size_t)sblock.fs_sbsize); flush(fswritefd, &asblk); } /* * read in the summary info. */ asked = 0; sblock.fs_csp = calloc(1, sblock.fs_cssize); if (sblock.fs_csp == NULL) { printf("cannot alloc %u bytes for cg summary info\n", (unsigned)sblock.fs_cssize); goto badsb; } for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) { size = sblock.fs_cssize - i < sblock.fs_bsize ? sblock.fs_cssize - i : sblock.fs_bsize; if (blread(fsreadfd, (char *)sblock.fs_csp + i, fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag), size) != 0 && !asked) { pfatal("BAD SUMMARY INFORMATION"); if (reply("CONTINUE") == 0) { ckfini(0); exit(EEXIT); } asked++; } } /* * allocate and initialize the necessary maps */ bmapsize = roundup(howmany(maxfsblock, CHAR_BIT), sizeof(short)); blockmap = calloc((unsigned)bmapsize, sizeof (char)); if (blockmap == NULL) { printf("cannot alloc %u bytes for blockmap\n", (unsigned)bmapsize); goto badsb; } inostathead = calloc((unsigned)(sblock.fs_ncg), sizeof(struct inostatlist)); if (inostathead == NULL) { printf("cannot alloc %u bytes for inostathead\n", (unsigned)(sizeof(struct inostatlist) * (sblock.fs_ncg))); goto badsb; } numdirs = MAX(sblock.fs_cstotal.cs_ndir, 128); dirhash = numdirs; inplast = 0; listmax = numdirs + 10; inpsort = (struct inoinfo **)calloc((unsigned)listmax, sizeof(struct inoinfo *)); inphead = (struct inoinfo **)calloc((unsigned)numdirs, sizeof(struct inoinfo *)); if (inpsort == NULL || inphead == NULL) { printf("cannot alloc %ju bytes for inphead\n", (uintmax_t)numdirs * sizeof(struct inoinfo *)); goto badsb; } bufinit(); if (sblock.fs_flags & FS_DOSOFTDEP) usedsoftdep = 1; else usedsoftdep = 0; return (1); badsb: ckfini(0); return (0); } /* * Possible superblock locations ordered from most to least likely. */ static int sblock_try[] = SBLOCKSEARCH; #define BAD_MAGIC_MSG \ "The previous newfs operation on this volume did not complete.\n" \ "You must complete newfs before mounting this volume.\n" /* * Read in the super block and its summary info. */ int readsb(int listerr) { ufs2_daddr_t super; int i; if (bflag) { super = bflag; if ((blread(fsreadfd, (char *)&sblock, super, (long)SBLOCKSIZE))) return (0); if (sblock.fs_magic == FS_BAD_MAGIC) { fprintf(stderr, BAD_MAGIC_MSG); exit(11); } if (sblock.fs_magic != FS_UFS1_MAGIC && sblock.fs_magic != FS_UFS2_MAGIC) { fprintf(stderr, "%d is not a file system superblock\n", bflag); return (0); } } else { for (i = 0; sblock_try[i] != -1; i++) { super = sblock_try[i] / dev_bsize; if ((blread(fsreadfd, (char *)&sblock, super, (long)SBLOCKSIZE))) return (0); if (sblock.fs_magic == FS_BAD_MAGIC) { fprintf(stderr, BAD_MAGIC_MSG); exit(11); } if ((sblock.fs_magic == FS_UFS1_MAGIC || (sblock.fs_magic == FS_UFS2_MAGIC && sblock.fs_sblockloc == sblock_try[i])) && sblock.fs_ncg >= 1 && sblock.fs_bsize >= MINBSIZE && sblock.fs_bsize >= sizeof(struct fs)) break; } if (sblock_try[i] == -1) { fprintf(stderr, "Cannot find file system superblock\n"); return (0); } } /* * Compute block size that the file system is based on, * according to fsbtodb, and adjust superblock block number * so we can tell if this is an alternate later. */ super *= dev_bsize; dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); sblk.b_bno = super / dev_bsize; sblk.b_size = SBLOCKSIZE; if (bflag) goto out; /* * Compare all fields that should not differ in alternate super block. * When an alternate super-block is specified this check is skipped. */ getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize); if (asblk.b_errs) return (0); if (altsblock.fs_sblkno != sblock.fs_sblkno || altsblock.fs_cblkno != sblock.fs_cblkno || altsblock.fs_iblkno != sblock.fs_iblkno || altsblock.fs_dblkno != sblock.fs_dblkno || altsblock.fs_ncg != sblock.fs_ncg || altsblock.fs_bsize != sblock.fs_bsize || altsblock.fs_fsize != sblock.fs_fsize || altsblock.fs_frag != sblock.fs_frag || altsblock.fs_bmask != sblock.fs_bmask || altsblock.fs_fmask != sblock.fs_fmask || altsblock.fs_bshift != sblock.fs_bshift || altsblock.fs_fshift != sblock.fs_fshift || altsblock.fs_fragshift != sblock.fs_fragshift || altsblock.fs_fsbtodb != sblock.fs_fsbtodb || altsblock.fs_sbsize != sblock.fs_sbsize || altsblock.fs_nindir != sblock.fs_nindir || altsblock.fs_inopb != sblock.fs_inopb || altsblock.fs_cssize != sblock.fs_cssize || altsblock.fs_ipg != sblock.fs_ipg || altsblock.fs_fpg != sblock.fs_fpg || altsblock.fs_magic != sblock.fs_magic) { badsb(listerr, "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE"); return (0); } out: /* * If not yet done, update UFS1 superblock with new wider fields. */ if (sblock.fs_magic == FS_UFS1_MAGIC && sblock.fs_maxbsize != sblock.fs_bsize) { sblock.fs_maxbsize = sblock.fs_bsize; sblock.fs_time = sblock.fs_old_time; sblock.fs_size = sblock.fs_old_size; sblock.fs_dsize = sblock.fs_old_dsize; sblock.fs_csaddr = sblock.fs_old_csaddr; sblock.fs_cstotal.cs_ndir = sblock.fs_old_cstotal.cs_ndir; sblock.fs_cstotal.cs_nbfree = sblock.fs_old_cstotal.cs_nbfree; sblock.fs_cstotal.cs_nifree = sblock.fs_old_cstotal.cs_nifree; sblock.fs_cstotal.cs_nffree = sblock.fs_old_cstotal.cs_nffree; } havesb = 1; return (1); } static void badsb(int listerr, const char *s) { if (!listerr) return; if (preen) printf("%s: ", cdevname); pfatal("BAD SUPER BLOCK: %s\n", s); } void sblock_init(void) { struct disklabel *lp; fswritefd = -1; fsmodified = 0; lfdir = 0; initbarea(&sblk); initbarea(&asblk); sblk.b_un.b_buf = malloc(SBLOCKSIZE); asblk.b_un.b_buf = malloc(SBLOCKSIZE); if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL) errx(EEXIT, "cannot allocate space for superblock"); if ((lp = getdisklabel(NULL, fsreadfd))) dev_bsize = secsize = lp->d_secsize; else dev_bsize = secsize = DEV_BSIZE; } /* * Calculate a prototype superblock based on information in the disk label. * When done the cgsblock macro can be calculated and the fs_ncg field * can be used. Do NOT attempt to use other macros without verifying that * their needed information is available! */ static int calcsb(char *dev, int devfd, struct fs *fs) { struct disklabel *lp; struct partition *pp; char *cp; int i, nspf; cp = strchr(dev, '\0') - 1; if (cp == (char *)-1 || ((*cp < 'a' || *cp > 'h') && !isdigit(*cp))) { pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev); return (0); } lp = getdisklabel(dev, devfd); if (isdigit(*cp)) pp = &lp->d_partitions[0]; else pp = &lp->d_partitions[*cp - 'a']; if (pp->p_fstype != FS_BSDFFS) { pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n", dev, pp->p_fstype < FSMAXTYPES ? fstypenames[pp->p_fstype] : "unknown"); return (0); } if (pp->p_fsize == 0 || pp->p_frag == 0 || pp->p_cpg == 0 || pp->p_size == 0) { pfatal("%s: %s: type %s fsize %d, frag %d, cpg %d, size %d\n", dev, "INCOMPLETE LABEL", fstypenames[pp->p_fstype], pp->p_fsize, pp->p_frag, pp->p_cpg, pp->p_size); return (0); } memset(fs, 0, sizeof(struct fs)); fs->fs_fsize = pp->p_fsize; fs->fs_frag = pp->p_frag; fs->fs_size = pp->p_size; fs->fs_sblkno = roundup( howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize), fs->fs_frag); nspf = fs->fs_fsize / lp->d_secsize; for (fs->fs_fsbtodb = 0, i = nspf; i > 1; i >>= 1) fs->fs_fsbtodb++; dev_bsize = lp->d_secsize; if (fs->fs_magic == FS_UFS2_MAGIC) { fs->fs_fpg = pp->p_cpg; fs->fs_ncg = howmany(fs->fs_size, fs->fs_fpg); } else /* if (fs->fs_magic == FS_UFS1_MAGIC) */ { fs->fs_old_cpg = pp->p_cpg; fs->fs_old_cgmask = 0xffffffff; for (i = lp->d_ntracks; i > 1; i >>= 1) fs->fs_old_cgmask <<= 1; if (!POWEROF2(lp->d_ntracks)) fs->fs_old_cgmask <<= 1; fs->fs_old_cgoffset = roundup(howmany(lp->d_nsectors, nspf), fs->fs_frag); fs->fs_fpg = (fs->fs_old_cpg * lp->d_secpercyl) / nspf; fs->fs_ncg = howmany(fs->fs_size / lp->d_secpercyl, fs->fs_old_cpg); } return (1); } static struct disklabel * getdisklabel(char *s, int fd) { static struct disklabel lab; if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) { if (s == NULL) return ((struct disklabel *)NULL); pwarn("ioctl (GCINFO): %s\n", strerror(errno)); errx(EEXIT, "%s: can't read disk label", s); } return (&lab); } Index: stable/7/sbin/fsck_ffs =================================================================== --- stable/7/sbin/fsck_ffs (revision 190356) +++ stable/7/sbin/fsck_ffs (revision 190357) Property changes on: stable/7/sbin/fsck_ffs ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/sbin/fsck_ffs:r187931 Index: stable/7/sbin/mount =================================================================== --- stable/7/sbin/mount (revision 190356) +++ stable/7/sbin/mount (revision 190357) Property changes on: stable/7/sbin/mount ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/sbin/mount:r186504-186505 Index: stable/7/usr.bin/gprof =================================================================== --- stable/7/usr.bin/gprof (revision 190356) +++ stable/7/usr.bin/gprof (revision 190357) Property changes on: stable/7/usr.bin/gprof ___________________________________________________________________ Added: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/usr.bin/gprof:r187116 Index: stable/7/usr.bin/make =================================================================== --- stable/7/usr.bin/make (revision 190356) +++ stable/7/usr.bin/make (revision 190357) Property changes on: stable/7/usr.bin/make ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/usr.bin/make:r181021,186279,186502,186558-186559,186713,187475,188075 Index: stable/7/usr.sbin/crunch =================================================================== --- stable/7/usr.sbin/crunch (revision 190356) +++ stable/7/usr.sbin/crunch (revision 190357) Property changes on: stable/7/usr.sbin/crunch ___________________________________________________________________ Added: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/usr.sbin/crunch:r173065,173067,173412,187943 Index: stable/7/usr.sbin/sade/disks.c =================================================================== --- stable/7/usr.sbin/sade/disks.c (revision 190356) +++ stable/7/usr.sbin/sade/disks.c (revision 190357) @@ -1,1012 +1,1039 @@ /* * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sade.h" #include #include #include #include #include #include #ifdef WITH_SLICES enum size_units_t { UNIT_BLOCKS, UNIT_KILO, UNIT_MEG, UNIT_GIG, UNIT_SIZE }; #ifdef PC98 #define SUBTYPE_FREEBSD 50324 #define SUBTYPE_FAT 37218 #else #define SUBTYPE_FREEBSD 165 #define SUBTYPE_FAT 6 #endif #define SUBTYPE_EFI 239 #ifdef PC98 #define OTHER_SLICE_VALUES \ "Other popular values are 37218 for a\n" \ "DOS FAT partition.\n\n" #else #define OTHER_SLICE_VALUES \ "Other popular values are 6 for a\n" \ "DOS FAT partition, 131 for a Linux ext2fs partition, or\n" \ "130 for a Linux swap partition.\n\n" #endif #define NON_FREEBSD_NOTE \ "Note: If you choose a non-FreeBSD partition type, it will not\n" \ "be formatted or otherwise prepared, it will simply reserve space\n" \ "for you to use another tool, such as DOS format, to later format\n" \ "and actually use the partition." /* Where we start displaying chunk information on the screen */ #define CHUNK_START_ROW 5 /* Where we keep track of MBR chunks */ #define CHUNK_INFO_ENTRIES 16 static struct chunk *chunk_info[CHUNK_INFO_ENTRIES]; static int current_chunk; static void diskPartitionNonInteractive(Device *dev); #if !defined(__ia64__) static u_char * bootalloc(char *name, size_t *size); #endif static void record_chunks(Disk *d) { struct chunk *c1 = NULL; int i = 0; daddr_t last_free = 0; if (!d->chunks) msgFatal("No chunk list found for %s!", d->name); for (c1 = d->chunks->part; c1; c1 = c1->next) { if (c1->type == unused && c1->size > last_free) { last_free = c1->size; current_chunk = i; } chunk_info[i++] = c1; } chunk_info[i] = NULL; if (current_chunk >= i) current_chunk = i - 1; } static daddr_t Total; static void +check_geometry(Disk *d) +{ + int sg; + +#ifdef PC98 + if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256) +#else + if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) +#endif + { + dialog_clear_norefresh(); + sg = msgYesNo("WARNING: It is safe to use a geometry of %lu/%lu/%lu for %s on\n" + "computers with modern BIOS versions. If this disk is to be used\n" + "on rather old machines, however, it is recommended to ensure that\n" + "it does not have more than 65535 cylinders, or more than 255 heads\n" + "or more than " +#ifdef PC98 + "255" +#else + "63" +#endif + " sectors per track.\n" + "\n" + "Would you like that to keep using the current geometry?\n", + d->bios_cyl, d->bios_hd, d->bios_sect, d->name); + if (sg == 1) { + Sanitize_Bios_Geom(d); + msgConfirm("A geometry of %lu/%lu/%lu was calculated for %s.\n" + "\n" + "If you are not sure about this, please consult the Hardware Guide\n" + "in the Documentation submenu or use the (G)eometry command to\n" + "change it. Remember: you need to enter whatever your BIOS thinks\n" + "the geometry is! For IDE, it's what you were told in the BIOS\n" + "setup. For SCSI, it's the translation mode your controller is\n" + "using. Do NOT use a ``physical geometry''.\n", + d->bios_cyl, d->bios_hd, d->bios_sect, d->name); + } + } +} + +static void print_chunks(Disk *d, int u) { int row; int i; daddr_t sz; char *szstr; szstr = (u == UNIT_GIG ? "GB" : (u == UNIT_MEG ? "MB" : (u == UNIT_KILO ? "KB" : "ST"))); Total = 0; for (i = 0; chunk_info[i]; i++) Total += chunk_info[i]->size; -#ifdef PC98 - if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256) { -#else - if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) { -#endif - dialog_clear_norefresh(); - msgConfirm("WARNING: A geometry of %lu/%lu/%lu for %s is incorrect. Using\n" - "a more likely geometry. If this geometry is incorrect or you\n" - "are unsure as to whether or not it's correct, please consult\n" - "the Hardware Guide in the Documentation submenu or use the\n" - "(G)eometry command to change it now.\n\n" - "Remember: you need to enter whatever your BIOS thinks the\n" - "geometry is! For IDE, it's what you were told in the BIOS\n" - "setup. For SCSI, it's the translation mode your controller is\n" - "using. Do NOT use a ``physical geometry''.", - d->bios_cyl, d->bios_hd, d->bios_sect, d->name); - Sanitize_Bios_Geom(d); - msgDebug("Sanitized geometry for %s is %lu/%lu/%lu.\n", - d->name, d->bios_cyl, d->bios_hd, d->bios_sect); - } attrset(A_NORMAL); mvaddstr(0, 0, "Disk name:\t"); clrtobot(); attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL); attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL); mvprintw(1, 0, "DISK Geometry:\t%lu cyls/%lu heads/%lu sectors = %jd sectors (%jdMB)", d->bios_cyl, d->bios_hd, d->bios_sect, (intmax_t)d->bios_cyl * d->bios_hd * d->bios_sect, (intmax_t)d->bios_cyl * d->bios_hd * d->bios_sect / (1024/512) / 1024); mvprintw(3, 0, "%6s %10s(%s) %10s %8s %6s %10s %8s %8s", "Offset", "Size", szstr, "End", "Name", "PType", "Desc", "Subtype", "Flags"); for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { switch(u) { default: /* fall thru */ case UNIT_BLOCKS: sz = chunk_info[i]->size; break; case UNIT_KILO: sz = chunk_info[i]->size / (1024/512); break; case UNIT_MEG: sz = chunk_info[i]->size / (1024/512) / 1024; break; case UNIT_GIG: sz = chunk_info[i]->size / (1024/512) / 1024 / 1024; break; } if (i == current_chunk) attrset(ATTR_SELECTED); mvprintw(row, 0, "%10jd %10jd %10jd %8s %6d %10s %8d\t%-6s", (intmax_t)chunk_info[i]->offset, (intmax_t)sz, (intmax_t)chunk_info[i]->end, chunk_info[i]->name, chunk_info[i]->type, slice_type_name(chunk_info[i]->type, chunk_info[i]->subtype), chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i])); if (i == current_chunk) attrset(A_NORMAL); } } static void print_command_summary(void) { mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); mvprintw(16, 0, "A = Use Entire Disk G = set Drive Geometry C = Create Slice F = `DD' mode"); mvprintw(17, 0, "D = Delete Slice Z = Toggle Size Units S = Set Bootable | = Wizard m."); mvprintw(18, 0, "T = Change Type U = Undo All Changes Q = Finish"); mvprintw(18, 47, "W = Write Changes"); mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to select."); move(0, 0); } #ifdef PC98 static void getBootMgr(char *dname, u_char **bootipl, size_t *bootipl_size, u_char **bootmenu, size_t *bootmenu_size) { static u_char *boot0; static size_t boot0_size; static u_char *boot05; static size_t boot05_size; char str[80]; char *cp; int i = 0; cp = variable_get(VAR_BOOTMGR); if (!cp) { /* Figure out what kind of IPL the user wants */ sprintf(str, "Install Boot Manager for drive %s?", dname); MenuIPLType.title = str; i = dmenuOpenSimple(&MenuIPLType, FALSE); } else { if (!strncmp(cp, "boot", 4)) BootMgr = 0; else BootMgr = 1; } if (cp || i) { switch (BootMgr) { case 0: if (!boot0) boot0 = bootalloc("boot0", &boot0_size); *bootipl = boot0; *bootipl_size = boot0_size; if (!boot05) boot05 = bootalloc("boot0.5", &boot05_size); *bootmenu = boot05; *bootmenu_size = boot05_size; return; case 1: default: break; } } *bootipl = NULL; *bootipl_size = 0; *bootmenu = NULL; *bootmenu_size = 0; } #else static void getBootMgr(char *dname, u_char **bootCode, size_t *bootCodeSize) { #if defined(__i386__) || defined(__amd64__) /* only meaningful on x86 */ static u_char *mbr, *boot0; static size_t mbr_size, boot0_size; char str[80]; char *cp; int i = 0; cp = variable_get(VAR_BOOTMGR); if (!cp) { /* Figure out what kind of MBR the user wants */ sprintf(str, "Install Boot Manager for drive %s?", dname); MenuMBRType.title = str; i = dmenuOpenSimple(&MenuMBRType, FALSE); } else { if (!strncmp(cp, "boot", 4)) BootMgr = 0; else if (!strcmp(cp, "standard")) BootMgr = 1; else BootMgr = 2; } if (cp || i) { switch (BootMgr) { case 0: if (!boot0) boot0 = bootalloc("boot0", &boot0_size); *bootCode = boot0; *bootCodeSize = boot0_size; return; case 1: if (!mbr) mbr = bootalloc("mbr", &mbr_size); *bootCode = mbr; *bootCodeSize = mbr_size; return; case 2: default: break; } } #endif *bootCode = NULL; *bootCodeSize = 0; } #endif #endif /* WITH_SLICES */ int diskGetSelectCount(Device ***devs) { int i, cnt, enabled; char *cp; Device **dp; cp = variable_get(VAR_DISK); dp = *devs = deviceFind(cp, DEVICE_TYPE_DISK); cnt = deviceCount(dp); if (!cnt) return -1; for (i = 0, enabled = 0; i < cnt; i++) { if (dp[i]->enabled) ++enabled; } return enabled; } #ifdef WITH_SLICES void diskPartition(Device *dev) { char *cp, *p; int rv, key = 0; int i; Boolean chunking; char *msg = NULL; #ifdef PC98 u_char *bootipl; size_t bootipl_size; u_char *bootmenu; size_t bootmenu_size; #else u_char *mbrContents; size_t mbrSize; #endif WINDOW *w = savescr(); Disk *d = (Disk *)dev->private; int size_unit; size_unit = UNIT_BLOCKS; chunking = TRUE; keypad(stdscr, TRUE); /* Flush both the dialog and curses library views of the screen since we don't always know who called us */ dialog_clear_norefresh(), clear(); current_chunk = 0; /* Set up the chunk array */ record_chunks(d); + /* Give the user a chance to sanitize the disk geometry, if necessary */ + check_geometry(d); + while (chunking) { char *val, geometry[80]; /* Now print our overall state */ if (d) print_chunks(d, size_unit); print_command_summary(); if (msg) { attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); beep(); msg = NULL; } else { move(23, 0); clrtoeol(); } /* Get command character */ key = getch(); switch (toupper(key)) { case '\014': /* ^L (redraw) */ clear(); msg = NULL; break; case '\020': /* ^P */ case KEY_UP: case '-': if (current_chunk != 0) --current_chunk; break; case '\016': /* ^N */ case KEY_DOWN: case '+': case '\r': case '\n': if (chunk_info[current_chunk + 1]) ++current_chunk; break; case KEY_HOME: current_chunk = 0; break; case KEY_END: while (chunk_info[current_chunk + 1]) ++current_chunk; break; case KEY_F(1): case '?': systemDisplayHelp("slice"); clear(); break; case 'A': case 'F': /* Undocumented magic Dangerously Dedicated mode */ #if !defined(__i386__) && !defined(__amd64__) rv = 1; #else /* The rest is only relevant on x86 */ cp = variable_get(VAR_DEDICATE_DISK); if (cp && !strcasecmp(cp, "always")) rv = 1; else if (toupper(key) == 'A') rv = 0; else { rv = msgYesNo("Do you want to do this with a true partition entry\n" "so as to remain cooperative with any future possible\n" "operating systems on the drive(s)?\n" "(See also the section about ``dangerously dedicated''\n" "disks in the FreeBSD FAQ.)"); if (rv == -1) rv = 0; } #endif All_FreeBSD(d, rv); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); clear(); break; case 'C': if (chunk_info[current_chunk]->type != unused) msg = "Slice in use, delete it first or move to an unused one."; else { char *val, tmp[20], name[16], *cp; daddr_t size; int subtype; chunk_e partitiontype; #ifdef PC98 snprintf(name, sizeof (name), "%s", "FreeBSD"); val = msgGetInput(name, "Please specify the name for new FreeBSD slice."); if (val) strncpy(name, val, sizeof (name)); #else name[0] = '\0'; #endif snprintf(tmp, 20, "%jd", (intmax_t)chunk_info[current_chunk]->size); val = msgGetInput(tmp, "Please specify the size for new FreeBSD slice in blocks\n" "or append a trailing `M' for megabytes (e.g. 20M)."); if (val && (size = strtoimax(val, &cp, 0)) > 0) { if (*cp && toupper(*cp) == 'M') size *= ONE_MEG; else if (*cp && toupper(*cp) == 'G') size *= ONE_GIG; sprintf(tmp, "%d", SUBTYPE_FREEBSD); val = msgGetInput(tmp, "Enter type of partition to create:\n\n" "Pressing Enter will choose the default, a native FreeBSD\n" "slice (type %u). " OTHER_SLICE_VALUES NON_FREEBSD_NOTE, SUBTYPE_FREEBSD); if (val && (subtype = strtol(val, NULL, 0)) > 0) { if (subtype == SUBTYPE_FREEBSD) partitiontype = freebsd; else if (subtype == SUBTYPE_FAT) partitiontype = fat; else if (subtype == SUBTYPE_EFI) partitiontype = efi; else #ifdef PC98 partitiontype = pc98; #else partitiontype = mbr; #endif Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype, (chunk_info[current_chunk]->flags & CHUNK_ALIGN), name); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); } } clear(); } break; case KEY_DC: case 'D': if (chunk_info[current_chunk]->type == unused) msg = "Slice is already unused!"; else { Delete_Chunk(d, chunk_info[current_chunk]); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); } break; case 'T': if (chunk_info[current_chunk]->type == unused) msg = "Slice is currently unused (use create instead)"; else { char *val, tmp[20]; int subtype; chunk_e partitiontype; sprintf(tmp, "%d", chunk_info[current_chunk]->subtype); val = msgGetInput(tmp, "New partition type:\n\n" "Pressing Enter will use the current type. To choose a native\n" "FreeBSD slice enter %u. " OTHER_SLICE_VALUES NON_FREEBSD_NOTE, SUBTYPE_FREEBSD); if (val && (subtype = strtol(val, NULL, 0)) > 0) { if (subtype == SUBTYPE_FREEBSD) partitiontype = freebsd; else if (subtype == SUBTYPE_FAT) partitiontype = fat; else if (subtype == SUBTYPE_EFI) partitiontype = efi; else #ifdef PC98 partitiontype = pc98; #else partitiontype = mbr; #endif chunk_info[current_chunk]->type = partitiontype; chunk_info[current_chunk]->subtype = subtype; } } break; case 'G': snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect); val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n" "Don't forget to use the two slash (/) separator characters!\n" "It's not possible to parse the field without them."); if (val) { long nc, nh, ns; nc = strtol(val, &val, 0); nh = strtol(val + 1, &val, 0); ns = strtol(val + 1, 0, 0); Set_Bios_Geom(d, nc, nh, ns); } clear(); break; case 'S': /* Clear active states so we won't have two */ for (i = 0; (chunk_info[i] != NULL) && (i < CHUNK_INFO_ENTRIES); i++) chunk_info[i]->flags &= !CHUNK_ACTIVE; /* Set Bootable */ chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; break; case 'U': if (!variable_cmp(DISK_LABELLED, "written")) { msgConfirm("You've already written this information out - you\n" "can't undo it."); } else if (!msgNoYes("Are you SURE you want to Undo everything?")) { char cp[BUFSIZ]; sstrncpy(cp, d->name, sizeof cp); Free_Disk(dev->private); d = Open_Disk(cp); if (!d) msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp); dev->private = d; variable_unset(DISK_PARTITIONED); variable_unset(DISK_LABELLED); if (d) record_chunks(d); } clear(); break; case 'W': if (!msgNoYes("WARNING: You are about to modify an EXISTING installation.\n" "You should simply type Q when you are finished\n" "here and write to the disk from the label editor.\n\n" "Are you absolutely sure you want to continue?")) { variable_set2(DISK_PARTITIONED, "yes", 0); #ifdef PC98 /* * Don't trash the IPL if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has * requested a FreeBSD Boot Manager -- both would be fatal in * this case. */ /* * Don't offer to update the IPL on this disk if the first * "real" chunk looks like a FreeBSD "all disk" partition, * or the disk is entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) getBootMgr(d->name, &bootipl, &bootipl_size, &bootmenu, &bootmenu_size); else { bootipl = NULL; bootipl_size = 0; bootmenu = NULL; bootmenu_size = 0; } Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size); #else /* * Don't trash the MBR if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has * requested booteasy or a "standard" MBR -- both would be * fatal in this case. */ /* * Don't offer to update the MBR on this disk if the first * "real" chunk looks like a FreeBSD "all disk" partition, * or the disk is entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) getBootMgr(d->name, &mbrContents, &mbrSize); else { mbrContents = NULL; mbrSize = 0; } Set_Boot_Mgr(d, mbrContents, mbrSize); #endif if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS) msgConfirm("Disk partition write returned an error status!"); else msgConfirm("Wrote FDISK partition information out successfully."); } clear(); break; case '|': if (!msgNoYes("Are you SURE you want to go into Wizard mode?\n" "No seat belts whatsoever are provided!")) { clear(); refresh(); slice_wizard(d); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); } else msg = "Wise choice!"; clear(); break; case '\033': /* ESC */ case 'Q': chunking = FALSE; #ifdef PC98 /* * Don't trash the IPL if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has requested * a FreeBSD Boot Manager -- both would be fatal in this case. */ /* * Don't offer to update the IPL on this disk if the first "real" * chunk looks like a FreeBSD "all disk" partition, or the disk is * entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) { if (variable_cmp(DISK_PARTITIONED, "written")) { getBootMgr(d->name, &bootipl, &bootipl_size, &bootmenu, &bootmenu_size); if (bootipl != NULL && bootmenu != NULL) Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size); } } #else /* * Don't trash the MBR if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has requested * booteasy or a "standard" MBR -- both would be fatal in this case. */ /* * Don't offer to update the MBR on this disk if the first "real" * chunk looks like a FreeBSD "all disk" partition, or the disk is * entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) { if (variable_cmp(DISK_PARTITIONED, "written")) { getBootMgr(d->name, &mbrContents, &mbrSize); if (mbrContents != NULL) Set_Boot_Mgr(d, mbrContents, mbrSize); } } #endif break; case 'Z': size_unit = (size_unit + 1) % UNIT_SIZE; break; default: beep(); msg = "Type F1 or ? for help"; break; } } p = CheckRules(d); if (p) { char buf[FILENAME_MAX]; use_helpline("Press F1 to read more about disk slices."); use_helpfile(systemHelpFile("partition", buf)); if (!variable_get(VAR_NO_WARN)) dialog_mesgbox("Disk slicing warning:", p, -1, -1); free(p); } restorescr(w); } #endif /* WITH_SLICES */ #if !defined(__ia64__) static u_char * bootalloc(char *name, size_t *size) { char buf[FILENAME_MAX]; struct stat sb; snprintf(buf, sizeof buf, "/boot/%s", name); if (stat(buf, &sb) != -1) { int fd; fd = open(buf, O_RDONLY); if (fd != -1) { u_char *cp; cp = malloc(sb.st_size); if (read(fd, cp, sb.st_size) != sb.st_size) { free(cp); close(fd); msgDebug("bootalloc: couldn't read %ld bytes from %s\n", (long)sb.st_size, buf); return NULL; } close(fd); if (size != NULL) *size = sb.st_size; return cp; } msgDebug("bootalloc: couldn't open %s\n", buf); } else msgDebug("bootalloc: can't stat %s\n", buf); return NULL; } #endif /* !__ia64__ */ #ifdef WITH_SLICES static int partitionHook(dialogMenuItem *selected) { Device **devs = NULL; devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); if (!devs) { msgConfirm("Unable to find disk %s!", selected->prompt); return DITEM_FAILURE; } /* Toggle enabled status? */ if (!devs[0]->enabled) { devs[0]->enabled = TRUE; diskPartition(devs[0]); } else devs[0]->enabled = FALSE; return DITEM_SUCCESS; } static int partitionCheck(dialogMenuItem *selected) { Device **devs = NULL; devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); if (!devs || devs[0]->enabled == FALSE) return FALSE; return TRUE; } int diskPartitionEditor(dialogMenuItem *self) { DMenu *menu; Device **devs; int i, cnt, devcnt; cnt = diskGetSelectCount(&devs); devcnt = deviceCount(devs); if (cnt == -1) { msgConfirm("No disks found! Please verify that your disk controller is being\n" "properly probed at boot time. See the Hardware Guide on the\n" "Documentation menu for clues on diagnosing this type of problem."); return DITEM_FAILURE; } else if (cnt) { /* Some are already selected */ for (i = 0; i < devcnt; i++) { if (devs[i]->enabled) { if (variable_get(VAR_NONINTERACTIVE) && !variable_get(VAR_DISKINTERACTIVE)) diskPartitionNonInteractive(devs[i]); else diskPartition(devs[i]); } } } else { /* No disks are selected, fall-back case now */ if (devcnt == 1) { devs[0]->enabled = TRUE; if (variable_get(VAR_NONINTERACTIVE) && !variable_get(VAR_DISKINTERACTIVE)) diskPartitionNonInteractive(devs[0]); else diskPartition(devs[0]); return DITEM_SUCCESS; } else { menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); if (!menu) { msgConfirm("No devices suitable for installation found!\n\n" "Please verify that your disk controller (and attached drives)\n" "were detected properly. This can be done by pressing the\n" "[Scroll Lock] key and using the Arrow keys to move back to\n" "the boot messages. Press [Scroll Lock] again to return."); return DITEM_FAILURE; } else { i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; free(menu); } return i; } } return DITEM_SUCCESS; } #endif /* WITH_SLICES */ int diskPartitionWrite(dialogMenuItem *self) { Device **devs; int i; if (!variable_cmp(DISK_PARTITIONED, "written")) return DITEM_SUCCESS; devs = deviceFind(NULL, DEVICE_TYPE_DISK); if (!devs) { msgConfirm("Unable to find any disks to write to??"); return DITEM_FAILURE; } if (isDebug()) msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); for (i = 0; devs[i]; i++) { Disk *d = (Disk *)devs[i]->private; #if !defined(__ia64__) static u_char *boot1; #endif #if defined(__i386__) || defined(__amd64__) static u_char *boot2; #endif if (!devs[i]->enabled) continue; #if defined(__i386__) || defined(__amd64__) if (!boot1) boot1 = bootalloc("boot1", NULL); if (!boot2) boot2 = bootalloc("boot2", NULL); Set_Boot_Blocks(d, boot1, boot2); #elif !defined(__ia64__) if (!boot1) boot1 = bootalloc("boot1", NULL); Set_Boot_Blocks(d, boot1, NULL); #endif msgNotify("Writing partition information to drive %s", d->name); if (!Fake && Write_Disk(d)) { msgConfirm("ERROR: Unable to write data to disk %s!", d->name); return DITEM_FAILURE; } } /* Now it's not "yes", but "written" */ variable_set2(DISK_PARTITIONED, "written", 0); return DITEM_SUCCESS | DITEM_RESTORE; } #ifdef WITH_SLICES /* Partition a disk based wholly on which variables are set */ static void diskPartitionNonInteractive(Device *dev) { char *cp; int i, all_disk = 0; daddr_t sz; #ifdef PC98 u_char *bootipl; size_t bootipl_size; u_char *bootmenu; size_t bootmenu_size; #else u_char *mbrContents; size_t mbrSize; #endif Disk *d = (Disk *)dev->private; record_chunks(d); cp = variable_get(VAR_GEOMETRY); if (cp) { - msgDebug("Setting geometry from script to: %s\n", cp); - d->bios_cyl = strtol(cp, &cp, 0); - d->bios_hd = strtol(cp + 1, &cp, 0); - d->bios_sect = strtol(cp + 1, 0, 0); - } - + if (!strcasecmp(cp, "sane")) { #ifdef PC98 - if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256) { + if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256) #else - if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) { + if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) #endif - msgDebug("Warning: A geometry of %lu/%lu/%lu for %s is incorrect.\n", - d->bios_cyl, d->bios_hd, d->bios_sect, d->name); - Sanitize_Bios_Geom(d); - msgDebug("Sanitized geometry for %s is %lu/%lu/%lu.\n", - d->name, d->bios_cyl, d->bios_hd, d->bios_sect); + { + msgDebug("Warning: A geometry of %lu/%lu/%lu for %s is incorrect.\n", + d->bios_cyl, d->bios_hd, d->bios_sect, d->name); + Sanitize_Bios_Geom(d); + msgDebug("Sanitized geometry for %s is %lu/%lu/%lu.\n", + d->name, d->bios_cyl, d->bios_hd, d->bios_sect); + } + } else { + msgDebug("Setting geometry from script to: %s\n", cp); + d->bios_cyl = strtol(cp, &cp, 0); + d->bios_hd = strtol(cp + 1, &cp, 0); + d->bios_sect = strtol(cp + 1, 0, 0); + } } cp = variable_get(VAR_PARTITION); if (cp) { if (!strcmp(cp, "free")) { /* Do free disk space case */ for (i = 0; chunk_info[i]; i++) { /* If a chunk is at least 10MB in size, use it. */ if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) { Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN), "FreeBSD"); variable_set2(DISK_PARTITIONED, "yes", 0); break; } } if (!chunk_info[i]) { msgConfirm("Unable to find any free space on this disk!"); return; } } else if (!strcmp(cp, "all")) { /* Do all disk space case */ msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); All_FreeBSD(d, FALSE); } else if (!strcmp(cp, "exclusive")) { /* Do really-all-the-disk-space case */ msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); All_FreeBSD(d, all_disk = TRUE); } else if ((sz = strtoimax(cp, &cp, 0))) { /* Look for sz bytes free */ if (*cp && toupper(*cp) == 'M') sz *= ONE_MEG; else if (*cp && toupper(*cp) == 'G') sz *= ONE_GIG; for (i = 0; chunk_info[i]; i++) { /* If a chunk is at least sz MB, use it. */ if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) { Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN), "FreeBSD"); variable_set2(DISK_PARTITIONED, "yes", 0); break; } } if (!chunk_info[i]) { msgConfirm("Unable to find %jd free blocks on this disk!", (intmax_t)sz); return; } } else if (!strcmp(cp, "existing")) { /* Do existing FreeBSD case */ for (i = 0; chunk_info[i]; i++) { if (chunk_info[i]->type == freebsd) break; } if (!chunk_info[i]) { msgConfirm("Unable to find any existing FreeBSD partitions on this disk!"); return; } } else { msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION); return; } if (!all_disk) { #ifdef PC98 getBootMgr(d->name, &bootipl, &bootipl_size, &bootmenu, &bootmenu_size); Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size); #else getBootMgr(d->name, &mbrContents, &mbrSize); Set_Boot_Mgr(d, mbrContents, mbrSize); #endif } variable_set2(DISK_PARTITIONED, "yes", 0); } } #endif /* WITH_SLICES */ Index: stable/7/usr.sbin/sade =================================================================== --- stable/7/usr.sbin/sade (revision 190356) +++ stable/7/usr.sbin/sade (revision 190357) Property changes on: stable/7/usr.sbin/sade ___________________________________________________________________ Added: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/usr.sbin/sade:r178940-178941,178946,179308,181430,183242,183387,183422,183629,186581,186844-186848 Index: stable/7/usr.sbin/sysinstall/disks.c =================================================================== --- stable/7/usr.sbin/sysinstall/disks.c (revision 190356) +++ stable/7/usr.sbin/sysinstall/disks.c (revision 190357) @@ -1,1019 +1,1048 @@ /* * The new sysinstall program. * * This is probably the last program in the `sysinstall' line - the next * generation being essentially a complete rewrite. * * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sysinstall.h" #include #include #include #include #include #include #ifdef WITH_SLICES enum size_units_t { UNIT_BLOCKS, UNIT_KILO, UNIT_MEG, UNIT_GIG, UNIT_SIZE }; #ifdef PC98 #define SUBTYPE_FREEBSD 50324 #define SUBTYPE_FAT 37218 #else #define SUBTYPE_FREEBSD 165 #define SUBTYPE_FAT 6 #endif #define SUBTYPE_EFI 239 #ifdef PC98 #define OTHER_SLICE_VALUES \ "Other popular values are 37218 for a\n" \ "DOS FAT partition.\n\n" #else #define OTHER_SLICE_VALUES \ "Other popular values are 6 for a\n" \ "DOS FAT partition, 131 for a Linux ext2fs partition, or\n" \ "130 for a Linux swap partition.\n\n" #endif #define NON_FREEBSD_NOTE \ "Note: If you choose a non-FreeBSD partition type, it will not\n" \ "be formatted or otherwise prepared, it will simply reserve space\n" \ "for you to use another tool, such as DOS format, to later format\n" \ "and actually use the partition." /* Where we start displaying chunk information on the screen */ #define CHUNK_START_ROW 5 /* Where we keep track of MBR chunks */ #define CHUNK_INFO_ENTRIES 16 static struct chunk *chunk_info[CHUNK_INFO_ENTRIES]; static int current_chunk; static void diskPartitionNonInteractive(Device *dev); static u_char * bootalloc(char *name, size_t *size); static void record_chunks(Disk *d) { struct chunk *c1 = NULL; int i = 0; daddr_t last_free = 0; if (!d->chunks) msgFatal("No chunk list found for %s!", d->name); for (c1 = d->chunks->part; c1; c1 = c1->next) { if (c1->type == unused && c1->size > last_free) { last_free = c1->size; current_chunk = i; } chunk_info[i++] = c1; } chunk_info[i] = NULL; if (current_chunk >= i) current_chunk = i - 1; } static daddr_t Total; static void +check_geometry(Disk *d) +{ + int sg; + +#ifdef PC98 + if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256) +#else + if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) +#endif + { + dialog_clear_norefresh(); + sg = msgYesNo("WARNING: It is safe to use a geometry of %lu/%lu/%lu for %s on\n" + "computers with modern BIOS versions. If this disk is to be used\n" + "on rather old machines, however, it is recommended to ensure that\n" + "it does not have more than 65535 cylinders, or more than 255 heads\n" + "or more than " +#ifdef PC98 + "255" +#else + "63" +#endif + " sectors per track.\n" + "\n" + "Would you like that to keep using the current geometry?\n", + d->bios_cyl, d->bios_hd, d->bios_sect, d->name); + if (sg == 1) { + Sanitize_Bios_Geom(d); + msgConfirm("A geometry of %lu/%lu/%lu was calculated for %s.\n" + "\n" + "If you are not sure about this, please consult the Hardware Guide\n" + "in the Documentation submenu or use the (G)eometry command to\n" + "change it. Remember: you need to enter whatever your BIOS thinks\n" + "the geometry is! For IDE, it's what you were told in the BIOS\n" + "setup. For SCSI, it's the translation mode your controller is\n" + "using. Do NOT use a ``physical geometry''.\n", + d->bios_cyl, d->bios_hd, d->bios_sect, d->name); + } + } +} + +static void print_chunks(Disk *d, int u) { int row; int i; daddr_t sz; char *szstr; szstr = (u == UNIT_GIG ? "GB" : (u == UNIT_MEG ? "MB" : (u == UNIT_KILO ? "KB" : "ST"))); Total = 0; for (i = 0; chunk_info[i]; i++) Total += chunk_info[i]->size; -#ifdef PC98 - if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256) { -#else - if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) { -#endif - dialog_clear_norefresh(); - msgConfirm("WARNING: A geometry of %lu/%lu/%lu for %s is incorrect. Using\n" - "a more likely geometry. If this geometry is incorrect or you\n" - "are unsure as to whether or not it's correct, please consult\n" - "the Hardware Guide in the Documentation submenu or use the\n" - "(G)eometry command to change it now.\n\n" - "Remember: you need to enter whatever your BIOS thinks the\n" - "geometry is! For IDE, it's what you were told in the BIOS\n" - "setup. For SCSI, it's the translation mode your controller is\n" - "using. Do NOT use a ``physical geometry''.", - d->bios_cyl, d->bios_hd, d->bios_sect, d->name); - Sanitize_Bios_Geom(d); - } attrset(A_NORMAL); mvaddstr(0, 0, "Disk name:\t"); clrtobot(); attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL); attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL); mvprintw(1, 0, "DISK Geometry:\t%lu cyls/%lu heads/%lu sectors = %jd sectors (%jdMB)", d->bios_cyl, d->bios_hd, d->bios_sect, (intmax_t)d->bios_cyl * d->bios_hd * d->bios_sect, (intmax_t)d->bios_cyl * d->bios_hd * d->bios_sect / (1024/512) / 1024); mvprintw(3, 0, "%6s %10s(%s) %10s %8s %6s %10s %8s %8s", "Offset", "Size", szstr, "End", "Name", "PType", "Desc", "Subtype", "Flags"); for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { switch(u) { default: /* fall thru */ case UNIT_BLOCKS: sz = chunk_info[i]->size; break; case UNIT_KILO: sz = chunk_info[i]->size / (1024/512); break; case UNIT_MEG: sz = chunk_info[i]->size / (1024/512) / 1024; break; case UNIT_GIG: sz = chunk_info[i]->size / (1024/512) / 1024 / 1024; break; } if (i == current_chunk) attrset(ATTR_SELECTED); mvprintw(row, 0, "%10jd %10jd %10jd %8s %6d %10s %8d\t%-6s", (intmax_t)chunk_info[i]->offset, (intmax_t)sz, (intmax_t)chunk_info[i]->end, chunk_info[i]->name, chunk_info[i]->type, slice_type_name(chunk_info[i]->type, chunk_info[i]->subtype), chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i])); if (i == current_chunk) attrset(A_NORMAL); } } static void print_command_summary(void) { mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); mvprintw(16, 0, "A = Use Entire Disk G = set Drive Geometry C = Create Slice F = `DD' mode"); mvprintw(17, 0, "D = Delete Slice Z = Toggle Size Units S = Set Bootable | = Wizard m."); mvprintw(18, 0, "T = Change Type U = Undo All Changes Q = Finish"); if (!RunningAsInit) mvprintw(18, 47, "W = Write Changes"); mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to select."); move(0, 0); } #ifdef PC98 static void getBootMgr(char *dname, u_char **bootipl, size_t *bootipl_size, u_char **bootmenu, size_t *bootmenu_size) { static u_char *boot0; static size_t boot0_size; static u_char *boot05; static size_t boot05_size; char str[80]; char *cp; int i = 0; cp = variable_get(VAR_BOOTMGR); if (!cp) { /* Figure out what kind of IPL the user wants */ sprintf(str, "Install Boot Manager for drive %s?", dname); MenuIPLType.title = str; i = dmenuOpenSimple(&MenuIPLType, FALSE); } else { if (!strncmp(cp, "boot", 4)) BootMgr = 0; else BootMgr = 1; } if (cp || i) { switch (BootMgr) { case 0: if (!boot0) boot0 = bootalloc("boot0", &boot0_size); *bootipl = boot0; *bootipl_size = boot0_size; if (!boot05) boot05 = bootalloc("boot0.5", &boot05_size); *bootmenu = boot05; *bootmenu_size = boot05_size; return; case 1: default: break; } } *bootipl = NULL; *bootipl_size = 0; *bootmenu = NULL; *bootmenu_size = 0; } #else static void getBootMgr(char *dname, u_char **bootCode, size_t *bootCodeSize) { #if defined(__i386__) || defined(__amd64__) /* only meaningful on x86 */ static u_char *mbr, *boot0; static size_t mbr_size, boot0_size; char str[80]; char *cp; int i = 0; cp = variable_get(VAR_BOOTMGR); if (!cp) { /* Figure out what kind of MBR the user wants */ sprintf(str, "Install Boot Manager for drive %s?", dname); MenuMBRType.title = str; i = dmenuOpenSimple(&MenuMBRType, FALSE); } else { if (!strncmp(cp, "boot", 4)) BootMgr = 0; else if (!strcmp(cp, "standard")) BootMgr = 1; else BootMgr = 2; } if (cp || i) { switch (BootMgr) { case 0: if (!boot0) boot0 = bootalloc("boot0", &boot0_size); *bootCode = boot0; *bootCodeSize = boot0_size; return; case 1: if (!mbr) mbr = bootalloc("mbr", &mbr_size); *bootCode = mbr; *bootCodeSize = mbr_size; return; case 2: default: break; } } #endif *bootCode = NULL; *bootCodeSize = 0; } #endif #endif /* WITH_SLICES */ int diskGetSelectCount(Device ***devs) { int i, cnt, enabled; char *cp; Device **dp; cp = variable_get(VAR_DISK); dp = *devs = deviceFind(cp, DEVICE_TYPE_DISK); cnt = deviceCount(dp); if (!cnt) return -1; for (i = 0, enabled = 0; i < cnt; i++) { if (dp[i]->enabled) ++enabled; } return enabled; } #ifdef WITH_SLICES void diskPartition(Device *dev) { char *cp, *p; int rv, key = 0; int i; Boolean chunking; char *msg = NULL; #ifdef PC98 u_char *bootipl; size_t bootipl_size; u_char *bootmenu; size_t bootmenu_size; #else u_char *mbrContents; size_t mbrSize; #endif WINDOW *w = savescr(); Disk *d = (Disk *)dev->private; int size_unit; size_unit = UNIT_BLOCKS; chunking = TRUE; keypad(stdscr, TRUE); /* Flush both the dialog and curses library views of the screen since we don't always know who called us */ dialog_clear_norefresh(), clear(); current_chunk = 0; /* Set up the chunk array */ record_chunks(d); + /* Give the user a chance to sanitize the disk geometry, if necessary */ + check_geometry(d); + while (chunking) { char *val, geometry[80]; /* Now print our overall state */ if (d) print_chunks(d, size_unit); print_command_summary(); if (msg) { attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); beep(); msg = NULL; } else { move(23, 0); clrtoeol(); } /* Get command character */ key = getch(); switch (toupper(key)) { case '\014': /* ^L (redraw) */ clear(); msg = NULL; break; case '\020': /* ^P */ case KEY_UP: case '-': if (current_chunk != 0) --current_chunk; break; case '\016': /* ^N */ case KEY_DOWN: case '+': case '\r': case '\n': if (chunk_info[current_chunk + 1]) ++current_chunk; break; case KEY_HOME: current_chunk = 0; break; case KEY_END: while (chunk_info[current_chunk + 1]) ++current_chunk; break; case KEY_F(1): case '?': systemDisplayHelp("slice"); clear(); break; case 'A': case 'F': /* Undocumented magic Dangerously Dedicated mode */ #if !defined(__i386__) && !defined(__amd64__) rv = 1; #else /* The rest is only relevant on x86 */ cp = variable_get(VAR_DEDICATE_DISK); if (cp && !strcasecmp(cp, "always")) rv = 1; else if (toupper(key) == 'A') rv = 0; else { rv = msgYesNo("Do you want to do this with a true partition entry\n" "so as to remain cooperative with any future possible\n" "operating systems on the drive(s)?\n" "(See also the section about ``dangerously dedicated''\n" "disks in the FreeBSD FAQ.)"); if (rv == -1) rv = 0; } #endif All_FreeBSD(d, rv); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); clear(); break; case 'C': if (chunk_info[current_chunk]->type != unused) msg = "Slice in use, delete it first or move to an unused one."; else { char *val, tmp[20], name[16], *cp; daddr_t size; int subtype; chunk_e partitiontype; #ifdef PC98 snprintf(name, sizeof (name), "%s", "FreeBSD"); val = msgGetInput(name, "Please specify the name for new FreeBSD slice."); if (val) strncpy(name, val, sizeof (name)); #else name[0] = '\0'; #endif snprintf(tmp, 20, "%jd", (intmax_t)chunk_info[current_chunk]->size); val = msgGetInput(tmp, "Please specify the size for new FreeBSD slice in blocks\n" "or append a trailing `M' for megabytes (e.g. 20M)."); if (val && (size = strtoimax(val, &cp, 0)) > 0) { if (*cp && toupper(*cp) == 'M') size *= ONE_MEG; else if (*cp && toupper(*cp) == 'G') size *= ONE_GIG; sprintf(tmp, "%d", SUBTYPE_FREEBSD); val = msgGetInput(tmp, "Enter type of partition to create:\n\n" "Pressing Enter will choose the default, a native FreeBSD\n" "slice (type %u). " OTHER_SLICE_VALUES NON_FREEBSD_NOTE, SUBTYPE_FREEBSD); if (val && (subtype = strtol(val, NULL, 0)) > 0) { if (subtype == SUBTYPE_FREEBSD) partitiontype = freebsd; else if (subtype == SUBTYPE_FAT) partitiontype = fat; else if (subtype == SUBTYPE_EFI) partitiontype = efi; else #ifdef PC98 partitiontype = pc98; #else partitiontype = mbr; #endif Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype, (chunk_info[current_chunk]->flags & CHUNK_ALIGN), name); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); } } clear(); } break; case KEY_DC: case 'D': if (chunk_info[current_chunk]->type == unused) msg = "Slice is already unused!"; else { Delete_Chunk(d, chunk_info[current_chunk]); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); } break; case 'T': if (chunk_info[current_chunk]->type == unused) msg = "Slice is currently unused (use create instead)"; else { char *val, tmp[20]; int subtype; chunk_e partitiontype; sprintf(tmp, "%d", chunk_info[current_chunk]->subtype); val = msgGetInput(tmp, "New partition type:\n\n" "Pressing Enter will use the current type. To choose a native\n" "FreeBSD slice enter %u. " OTHER_SLICE_VALUES NON_FREEBSD_NOTE, SUBTYPE_FREEBSD); if (val && (subtype = strtol(val, NULL, 0)) > 0) { if (subtype == SUBTYPE_FREEBSD) partitiontype = freebsd; else if (subtype == SUBTYPE_FAT) partitiontype = fat; else if (subtype == SUBTYPE_EFI) partitiontype = efi; else #ifdef PC98 partitiontype = pc98; #else partitiontype = mbr; #endif chunk_info[current_chunk]->type = partitiontype; chunk_info[current_chunk]->subtype = subtype; } } break; case 'G': snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect); val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n" "Don't forget to use the two slash (/) separator characters!\n" "It's not possible to parse the field without them."); if (val) { long nc, nh, ns; nc = strtol(val, &val, 0); nh = strtol(val + 1, &val, 0); ns = strtol(val + 1, 0, 0); Set_Bios_Geom(d, nc, nh, ns); } clear(); break; case 'S': /* Clear active states so we won't have two */ for (i = 0; (chunk_info[i] != NULL) && (i < CHUNK_INFO_ENTRIES); i++) chunk_info[i]->flags &= !CHUNK_ACTIVE; /* Set Bootable */ chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; break; case 'U': if (!variable_cmp(DISK_LABELLED, "written")) { msgConfirm("You've already written this information out - you\n" "can't undo it."); } else if (!msgNoYes("Are you SURE you want to Undo everything?")) { char cp[BUFSIZ]; sstrncpy(cp, d->name, sizeof cp); Free_Disk(dev->private); d = Open_Disk(cp); if (!d) msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp); dev->private = d; variable_unset(DISK_PARTITIONED); variable_unset(DISK_LABELLED); if (d) record_chunks(d); } clear(); break; case 'W': if (!msgNoYes("WARNING: This should only be used when modifying an EXISTING\n" "installation. If you are installing FreeBSD for the first time\n" "then you should simply type Q when you're finished here and your\n" "changes will be committed in one batch automatically at the end of\n" "these questions. If you're adding a disk, you should NOT write\n" "from this screen, you should do it from the label editor.\n\n" "Are you absolutely sure you want to do this now?")) { variable_set2(DISK_PARTITIONED, "yes", 0); #ifdef PC98 /* * Don't trash the IPL if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has * requested a FreeBSD Boot Manager -- both would be fatal in * this case. */ /* * Don't offer to update the IPL on this disk if the first * "real" chunk looks like a FreeBSD "all disk" partition, * or the disk is entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) getBootMgr(d->name, &bootipl, &bootipl_size, &bootmenu, &bootmenu_size); else { bootipl = NULL; bootipl_size = 0; bootmenu = NULL; bootmenu_size = 0; } Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size); #else /* * Don't trash the MBR if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has * requested booteasy or a "standard" MBR -- both would be * fatal in this case. */ /* * Don't offer to update the MBR on this disk if the first * "real" chunk looks like a FreeBSD "all disk" partition, * or the disk is entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) getBootMgr(d->name, &mbrContents, &mbrSize); else { mbrContents = NULL; mbrSize = 0; } Set_Boot_Mgr(d, mbrContents, mbrSize); #endif if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS) msgConfirm("Disk partition write returned an error status!"); else msgConfirm("Wrote FDISK partition information out successfully."); } clear(); break; case '|': if (!msgNoYes("Are you SURE you want to go into Wizard mode?\n" "No seat belts whatsoever are provided!")) { clear(); refresh(); slice_wizard(d); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); } else msg = "Wise choice!"; clear(); break; case '\033': /* ESC */ case 'Q': chunking = FALSE; #ifdef PC98 /* * Don't trash the IPL if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has requested * a FreeBSD Boot Manager -- both would be fatal in this case. */ /* * Don't offer to update the IPL on this disk if the first "real" * chunk looks like a FreeBSD "all disk" partition, or the disk is * entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) { if (variable_cmp(DISK_PARTITIONED, "written")) { getBootMgr(d->name, &bootipl, &bootipl_size, &bootmenu, &bootmenu_size); if (bootipl != NULL && bootmenu != NULL) Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size); } } #else /* * Don't trash the MBR if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has requested * booteasy or a "standard" MBR -- both would be fatal in this case. */ /* * Don't offer to update the MBR on this disk if the first "real" * chunk looks like a FreeBSD "all disk" partition, or the disk is * entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) { if (variable_cmp(DISK_PARTITIONED, "written")) { getBootMgr(d->name, &mbrContents, &mbrSize); if (mbrContents != NULL) Set_Boot_Mgr(d, mbrContents, mbrSize); } } #endif break; case 'Z': size_unit = (size_unit + 1) % UNIT_SIZE; break; default: beep(); msg = "Type F1 or ? for help"; break; } } p = CheckRules(d); if (p) { char buf[FILENAME_MAX]; use_helpline("Press F1 to read more about disk slices."); use_helpfile(systemHelpFile("partition", buf)); if (!variable_get(VAR_NO_WARN)) dialog_mesgbox("Disk slicing warning:", p, -1, -1); free(p); } restorescr(w); } #endif /* WITH_SLICES */ static u_char * bootalloc(char *name, size_t *size) { char buf[FILENAME_MAX]; struct stat sb; snprintf(buf, sizeof buf, "/boot/%s", name); if (stat(buf, &sb) != -1) { int fd; fd = open(buf, O_RDONLY); if (fd != -1) { u_char *cp; cp = malloc(sb.st_size); if (read(fd, cp, sb.st_size) != sb.st_size) { free(cp); close(fd); msgDebug("bootalloc: couldn't read %ld bytes from %s\n", (long)sb.st_size, buf); return NULL; } close(fd); if (size != NULL) *size = sb.st_size; return cp; } msgDebug("bootalloc: couldn't open %s\n", buf); } else msgDebug("bootalloc: can't stat %s\n", buf); return NULL; } #ifdef WITH_SLICES static int partitionHook(dialogMenuItem *selected) { Device **devs = NULL; devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); if (!devs) { msgConfirm("Unable to find disk %s!", selected->prompt); return DITEM_FAILURE; } /* Toggle enabled status? */ if (!devs[0]->enabled) { devs[0]->enabled = TRUE; diskPartition(devs[0]); } else devs[0]->enabled = FALSE; return DITEM_SUCCESS; } static int partitionCheck(dialogMenuItem *selected) { Device **devs = NULL; devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); if (!devs || devs[0]->enabled == FALSE) return FALSE; return TRUE; } int diskPartitionEditor(dialogMenuItem *self) { DMenu *menu; Device **devs; int i, cnt, devcnt; cnt = diskGetSelectCount(&devs); devcnt = deviceCount(devs); if (cnt == -1) { msgConfirm("No disks found! Please verify that your disk controller is being\n" "properly probed at boot time. See the Hardware Guide on the\n" "Documentation menu for clues on diagnosing this type of problem."); return DITEM_FAILURE; } else if (cnt) { /* Some are already selected */ for (i = 0; i < devcnt; i++) { if (devs[i]->enabled) { if (variable_get(VAR_NONINTERACTIVE) && !variable_get(VAR_DISKINTERACTIVE)) diskPartitionNonInteractive(devs[i]); else diskPartition(devs[i]); } } } else { /* No disks are selected, fall-back case now */ if (devcnt == 1) { devs[0]->enabled = TRUE; if (variable_get(VAR_NONINTERACTIVE) && !variable_get(VAR_DISKINTERACTIVE)) diskPartitionNonInteractive(devs[0]); else diskPartition(devs[0]); return DITEM_SUCCESS; } else { menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); if (!menu) { msgConfirm("No devices suitable for installation found!\n\n" "Please verify that your disk controller (and attached drives)\n" "were detected properly. This can be done by pressing the\n" "[Scroll Lock] key and using the Arrow keys to move back to\n" "the boot messages. Press [Scroll Lock] again to return."); return DITEM_FAILURE; } else { i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; free(menu); } return i; } } return DITEM_SUCCESS; } #endif /* WITH_SLICES */ int diskPartitionWrite(dialogMenuItem *self) { Device **devs; int i; if (!variable_cmp(DISK_PARTITIONED, "written")) return DITEM_SUCCESS; devs = deviceFind(NULL, DEVICE_TYPE_DISK); if (!devs) { msgConfirm("Unable to find any disks to write to??"); return DITEM_FAILURE; } if (isDebug()) msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); for (i = 0; devs[i]; i++) { Disk *d = (Disk *)devs[i]->private; static u_char *boot1; #if defined(__i386__) || defined(__amd64__) static u_char *boot2; #endif if (!devs[i]->enabled) continue; #if defined(__i386__) || defined(__amd64__) if (!boot1) boot1 = bootalloc("boot1", NULL); if (!boot2) boot2 = bootalloc("boot2", NULL); Set_Boot_Blocks(d, boot1, boot2); #elif !defined(__ia64__) if (!boot1) boot1 = bootalloc("boot1", NULL); Set_Boot_Blocks(d, boot1, NULL); #endif msgNotify("Writing partition information to drive %s", d->name); if (!Fake && Write_Disk(d)) { if (RunningAsInit) { msgConfirm("ERROR: Unable to write data to disk %s!", d->name); } else { msgConfirm("ERROR: Unable to write data to disk %s!\n\n" "To edit the labels on a running system set\n" "sysctl kern.geom.debugflags=16 and try again.", d->name); } return DITEM_FAILURE; } } /* Now it's not "yes", but "written" */ variable_set2(DISK_PARTITIONED, "written", 0); return DITEM_SUCCESS | DITEM_RESTORE; } #ifdef WITH_SLICES /* Partition a disk based wholly on which variables are set */ static void diskPartitionNonInteractive(Device *dev) { char *cp; int i, all_disk = 0; daddr_t sz; #ifdef PC98 u_char *bootipl; size_t bootipl_size; u_char *bootmenu; size_t bootmenu_size; #else u_char *mbrContents; size_t mbrSize; #endif Disk *d = (Disk *)dev->private; record_chunks(d); cp = variable_get(VAR_GEOMETRY); if (cp) { - msgDebug("Setting geometry from script to: %s\n", cp); - d->bios_cyl = strtol(cp, &cp, 0); - d->bios_hd = strtol(cp + 1, &cp, 0); - d->bios_sect = strtol(cp + 1, 0, 0); - } else { + if (!strcasecmp(cp, "sane")) { #ifdef PC98 - if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256) { + if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256) #else - if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) { + if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) #endif - msgDebug("Warning: A geometry of %lu/%lu/%lu for %s is incorrect.\n", - d->bios_cyl, d->bios_hd, d->bios_sect, d->name); - Sanitize_Bios_Geom(d); - msgDebug("Sanitized geometry for %s is %lu/%lu/%lu.\n", - d->name, d->bios_cyl, d->bios_hd, d->bios_sect); + { + msgDebug("Warning: A geometry of %lu/%lu/%lu for %s is incorrect.\n", + d->bios_cyl, d->bios_hd, d->bios_sect, d->name); + Sanitize_Bios_Geom(d); + msgDebug("Sanitized geometry for %s is %lu/%lu/%lu.\n", + d->name, d->bios_cyl, d->bios_hd, d->bios_sect); + } + } else { + msgDebug("Setting geometry from script to: %s\n", cp); + d->bios_cyl = strtol(cp, &cp, 0); + d->bios_hd = strtol(cp + 1, &cp, 0); + d->bios_sect = strtol(cp + 1, 0, 0); } } cp = variable_get(VAR_PARTITION); if (cp) { if (!strcmp(cp, "free")) { /* Do free disk space case */ for (i = 0; chunk_info[i]; i++) { /* If a chunk is at least 10MB in size, use it. */ if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) { Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN), "FreeBSD"); variable_set2(DISK_PARTITIONED, "yes", 0); break; } } if (!chunk_info[i]) { msgConfirm("Unable to find any free space on this disk!"); return; } } else if (!strcmp(cp, "all")) { /* Do all disk space case */ msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); All_FreeBSD(d, FALSE); } else if (!strcmp(cp, "exclusive")) { /* Do really-all-the-disk-space case */ msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); All_FreeBSD(d, all_disk = TRUE); } else if ((sz = strtoimax(cp, &cp, 0))) { /* Look for sz bytes free */ if (*cp && toupper(*cp) == 'M') sz *= ONE_MEG; else if (*cp && toupper(*cp) == 'G') sz *= ONE_GIG; for (i = 0; chunk_info[i]; i++) { /* If a chunk is at least sz MB, use it. */ if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) { Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN), "FreeBSD"); variable_set2(DISK_PARTITIONED, "yes", 0); break; } } if (!chunk_info[i]) { msgConfirm("Unable to find %jd free blocks on this disk!", (intmax_t)sz); return; } } else if (!strcmp(cp, "existing")) { /* Do existing FreeBSD case */ for (i = 0; chunk_info[i]; i++) { if (chunk_info[i]->type == freebsd) break; } if (!chunk_info[i]) { msgConfirm("Unable to find any existing FreeBSD partitions on this disk!"); return; } } else { msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION); return; } if (!all_disk) { #ifdef PC98 getBootMgr(d->name, &bootipl, &bootipl_size, &bootmenu, &bootmenu_size); Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size); #else getBootMgr(d->name, &mbrContents, &mbrSize); Set_Boot_Mgr(d, mbrContents, mbrSize); #endif } variable_set2(DISK_PARTITIONED, "yes", 0); } } #endif /* WITH_SLICES */ Index: stable/7/usr.sbin/sysinstall/sysinstall.8 =================================================================== --- stable/7/usr.sbin/sysinstall/sysinstall.8 (revision 190356) +++ stable/7/usr.sbin/sysinstall/sysinstall.8 (revision 190357) @@ -1,947 +1,953 @@ .\" Copyright (c) 1997 .\" Jordan Hubbard . All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY Jordan Hubbard AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL Jordan Hubbard OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd February 18, 2007 .Dt SYSINSTALL 8 .Os .Sh NAME .Nm sysinstall .Nd system installation and configuration tool .Sh SYNOPSIS .Nm .Op Ar var=value .Op Ar function .Op Ar ... .Sh DESCRIPTION The .Nm utility is used for installing and configuring .Fx systems. It is the first utility invoked by the .Fx installation boot floppy and is also available as .Pa /usr/sbin/sysinstall on newly installed .Fx systems for use in later configuring the system. .Pp The .Nm utility is generally invoked without arguments for the default behavior, where the main installation/configuration menu is presented. .Pp On those occasions where it is deemed necessary to invoke a subsystem of sysinstall directly, however, it is also possible to do so by naming the appropriate function entry points on the command line. Since this action is essentially identical to running an installation script, each command-line argument corresponding to a line of script, the reader is encouraged to read the section on scripting for more information on this feature. .Sh NOTES The .Nm utility is essentially nothing more than a monolithic C program with the ability to write MBRs and disk labels (through the services of the .Xr libdisk 3 library) and install distributions or packages onto new and existing .Fx systems. It also contains some extra intelligence for running as a replacement for .Xr init 8 when it is invoked by the .Fx installation boot procedure. It assumes very little in the way of additional utility support and performs most file system operations by calling the relevant syscalls (such as .Xr mount 2 ) directly. .Pp The .Nm utility currently uses the .Xr dialog 3 library to do user interaction with simple ANSI line graphics, color support for which is enabled by either running on a syscons VTY or some other color-capable terminal emulator (newer versions of xterm will support color when using the .Dq xterm-color termcap entry). .Pp This product is currently at the end of its life cycle and will eventually be replaced. .Sh RUNNING SCRIPTS The .Nm utility may be either driven interactively through its various internal menus or run in batch mode, driven by an external script. Such a script may be loaded and executed in one of 3 ways: .Bl -tag -width Ds .It Sy "LOAD_CONFIG_FILE" If .Nm is compiled with LOAD_CONFIG_FILE set in the environment (or in the Makefile) to some value, then that value will be used as the filename to automatically look for and load when .Nm starts up and with no user interaction required. This option is aimed primarily at large sites who wish to create a single prototype install for multiple machines with largely identical configurations and/or installation options. .It Sy "MAIN MENU" If .Nm is run interactively, that is to say in the default manner, it will bring up a main menu which contains a "load config file" option. Selecting this option will prompt for the name of a script file which it then will attempt to load from a DOS or UFS formatted floppy. .It Sy "COMMAND LINE" Each command line argument is treated as a script directive when .Nm is run in multi-user mode. Execution ends either by explicit request (e.g.\& calling the .Ar shutdown directive), upon reaching the end of the argument list or on error. .Pp For example: .Bd -literal /usr/sbin/sysinstall _ftpPath=ftp://ziggy/pub/ mediaSetFTP configPackages .Ed .Pp Would initialize .Nm for FTP installation media (using the server `ziggy') and then bring up the package installation editor, exiting when finished. .El .Sh SCRIPT SYNTAX A script is a list of one or more directives, each directive taking the form of: .Pp .Ar var=value .Pp .Ar function .Pp or .Ar #somecomment .Pp Where .Ar var=value is the assignment of some internal .Nm variable, e.g.\& "ftpPass=FuNkYChiKn", and .Ar function is the name of an internal .Nm function, e.g.\& "mediaSetFTP", and .Ar #comment is a single-line comment for documentation purposes (ignored by sysinstall). Each directive must be by itself on a single line, functions taking their arguments by examining known variable names. This requires that you be sure to assign the relevant variables before calling a function which requires them. .Pp The .Ar noError variable can be assigned before each directive: this will cause any error detected while processing the directive itself to be ignored. The value of .Ar noError will automatically reset to the default "unassigned" every time a directive is processed. .Pp When and where a function depends on the settings of one or more variables will be noted in the following table: .Pp .Sy "Function Glossary" : .Pp .Bl -tag -width indent .It configAnonFTP Invoke the Anonymous FTP configuration menu. .Pp .Sy Variables : None .It configRouter Select which routing daemon you wish to use, potentially loading any required 3rd-party routing daemons as necessary. .Pp .Sy Variables : .Bl -tag -width indent .It router can be set to the name of the desired routing daemon, e.g.\& .Dq routed or .Dq gated , otherwise it is prompted for. .El .It configNFSServer Configure host as an NFS server. .Pp .Sy Variables : None .It configNTP Configure host as a user of the Network Time Protocol. .Pp .Sy Variables : .Bl -tag -width indent .It ntpdate_flags The flags to .Xr ntpdate 8 , that is to say the name of the server to sync from. .El .It configPCNFSD Configure host to support PC NFS. .Pp .Sy Variables : .Bl -tag -width indent .It pcnfsd_pkg The name of the PCNFSD package to load if necessary (defaults to hard coded version). .El .It configPackages Bring up the interactive package management menu. .Pp .Sy Variables : None .It configUsers Add users and/or groups to the system. .Pp .Sy Variables : None .It diskPartitionEditor Invokes the disk partition (MBR) editor. .Pp .Sy Variables : .Bl -tag -width findx .It geometry The disk geometry, as a cyls/heads/sectors formatted string. +The word "sane" instructs +.Nm +to calculate a safe (not necessarily optimal) geometry if the +current one has more than 65535 cylinders, more than 256 heads or +more than 63 sectors per track (255 sectors on the PC98 +architecture). Default: no change to geometry. .It partition Set to disk partitioning type or size, its value being .Ar free in order to use only remaining free space for .Fx , .Ar all to use the entire disk for .Fx but maintain a proper partition table, .Ar existing to use an existing .Fx partition (first found), .Ar exclusive to use the disk in .Dq dangerously dedicated mode or, finally, .Ar somenumber to allocate .Ar somenumber blocks of available free space to a new .Fx partition. Default: Interactive mode. .It bootManager is set to one of .Ar boot to signify the installation of a boot manager, .Ar standard to signify installation of a "standard" non-boot MGR DOS MBR or .Ar none to indicate that no change to the boot manager is desired. Default: none. .It diskInteractive If set, bring up the interactive disk partition editor. .El .Pp Note: Nothing is actually written to disk by this function, an explicit call to .Ar diskPartitionWrite being required for that to happen. .It diskPartitionWrite Causes any pending MBR changes (typically from the .Ar diskPartitionEditor function) to be written out. .Pp .Sy Variables : None .It diskLabelEditor Invokes the disk label editor. This is a bit trickier from a script since you need to essentially label everything inside each .Fx (type 0xA5) partition created by the .Ar diskPartitionEditor function, and that requires knowing a few rules about how things are laid out. When creating a script to automatically allocate disk space and partition it up, it is suggested that you first perform the installation interactively at least once and take careful notes as to what the slice names will be, then and only then hardwiring them into the script. .Pp For example, let's say you have a SCSI disk on which you have created a new .Fx partition in slice 2 (your DOS partition residing in slice 1). The slice name would be .Ar da0s2 for the whole .Fx partition .Ar ( da0s1 being your DOS primary partition). Now let's further assume that you have 4GB in this partition and you want to sub-partition that space into root, swap, var and usr file systems for .Fx . Your invocation of the .Ar diskLabelEditor function might involve setting the following variables: .Bl -tag -width findx .It Li "da0s2-1=ufs 2097152 /" A 1GB root file system (all sizes are in 512 byte blocks). .It Li "da0s2-2=swap 1048576 /" A 512MB swap partition. .It Li "da0s2-3=ufs 524288 /var" A 256MB /var file system. .It Li "da0s2-4=ufs 0 /usr 1" With the balance of free space (around 2.25GB) going to the /usr file system and with soft-updates enabled (the argument following the mount point, if non-zero, means to set the soft updates flag). .El .Pp One can also use the .Ar diskLabelEditor for mounting or erasing existing partitions as well as creating new ones. Using the previous example again, let's say that we also wanted to mount our DOS partition and make sure that an .Pa /etc/fstab entry is created for it in the new installation. Before calling the .Ar diskLabelEditor function, we simply add an additional line: .Pp .Dl "da0s1=/dos_c N" .Pp before the call. This tells the label editor that you want to mount the first slice on .Pa /dos_c and not to attempt to newfs it (not that .Nm would attempt this for a DOS partition in any case, but it could just as easily be an existing UFS partition being named here and the 2nd field is non-optional). .Pp You can also set the .Ar diskInteractive variable to request that the disk label editor use an interactive dialog to partition the disk instead of using variables to explicitly layout the disk as described above. .Pp Note: No file system data is actually written to disk until an explicit call to .Ar diskLabelCommit is made. .It diskLabelCommit Writes out all pending disklabel information and creates and/or mounts any file systems which have requests pending from the .Ar diskLabelEditor function. .Pp .Sy Variables : None .It distReset Resets all selected distributions to the empty set (no distributions selected). .Pp .Sy Variables : None .It distSetCustom Allows the selection of a custom distribution set (e.g.\& not just one of the existing "canned" sets) with no user interaction. .Pp .Sy Variables : .Bl -tag -width indent .It dists List of distributions to load. Possible distribution values are: .Bl -tag -width indentxx .It Li base The base binary distribution. .It Li generic The GENERIC kernel. .It Li smp A kernel suitable for multiple processor systems. .It Li doc Miscellaneous documentation .It Li games Games .It Li manpages Manual pages (unformatted) .It Li catpages Pre-formatted manual pages .It Li proflibs Profiled libraries for developers. .It Li dict Dictionary information (for tools like spell). .It Li info GNU info files and other extra docs. .It Li lib32 (amd64 only) 32-bit runtime compatibility libraries. .It Li ports The ports collection. .It Li ssecure /usr/src/secure .It Li sbase /usr/src/[top level files] .It Li scontrib /usr/src/contrib .It Li scrypto /usr/src/crypto .It Li sgnu /usr/src/gnu .It Li setc /usr/src/etc .It Li sgames /usr/src/games .It Li sinclude /usr/src/include .It Li skrb5 /usr/src/kerberos5 .It Li slib /usr/src/lib .It Li slibexec /usr/src/libexec .It Li srelease /usr/src/release .It Li srescue /usr/src/rescue .It Li stools /usr/src/tools .It Li sbin /usr/src/bin .It Li ssbin /usr/src/sbin .It Li sshare /usr/src/share .It Li ssys /usr/src/sys .It Li stools /usr/src/tools .It Li subin /usr/src/usr.bin .It Li susbin /usr/src/usr.sbin .It Li Xbin X.Org client applications. .It Li Xlib X.Org libraries. .It Li Xman X.Org manual pages. .It Li Xdoc X.Org protocol and library documentation. .It Li Xprog X.Org imake distribution. .It Li Xsrv X.Org X server. .It Li Xnest X.Org nested X server. .It Li Xprt X.Org print server. .It Li Xvfb X.Org virtual frame-buffer X server. .It Li Xfmsc X.Org miscellaneous font set. .It Li Xf75 X.Org 75DPI font set. .It Li Xf100 X.Org 100DPI font set. .It Li Xfcyr X.Org Cyrillic font set. .It Li Xft1 X.Org Type 1 font set. .It Li Xftt X.Org TrueType font set. .It Li Xfs X.Org font server. .It Li local Local additions collection. .El .El .It distSetDeveloper Selects the standard Developer's distribution set. .Pp .Sy Variables : None .It distSetXDeveloper Selects the standard X Developer's distribution set. .Pp .Sy Variables : None .It distSetKernDeveloper Selects the standard kernel Developer's distribution set. .Pp .Sy Variables : None .It distSetUser Selects the standard user distribution set. .Pp .Sy Variables : None .It distSetXUser Selects the standard X user's distribution set. .Pp .Sy Variables : None .It distSetMinimum Selects the very minimum distribution set. .Pp .Sy Variables : None .It distSetEverything Selects the full whack - all available distributions. .Pp .Sy Variables : None .It distSetSrc Interactively select source subcomponents. .Pp .Sy Variables : None .It distSetXOrg Interactively select X.Org subcomponents. .Pp .Sy Variables : None .It distExtractAll Install all currently selected distributions (requires that media device also be selected). .Pp .Sy Variables : None .It docBrowser Install (if necessary) an HTML documentation browser and go to the HTML documentation submenu. .Pp .Sy Variables : .Bl -tag -width indent .It browserPackage The name of the browser package to try and install as necessary. Defaults to latest links package. .It browserBinary The name of the browser binary itself (if overriding the .Ar browserPackage variable). Defaults to links. .El .It installCommit Commit any and all pending changes to disk. This function is essentially shorthand for a number of more granular "commit" functions. .Pp .Sy Variables : None .It installExpress Start an "express" installation, asking few questions of the user. .Pp .Sy Variables : None .It installStandard Start a "standard" installation, the most user-friendly installation type available. .Pp .Sy Variables : None .It installUpgrade Start an upgrade installation. .Pp .Sy Variables : None .It installFixitHoloShell Start up the "emergency holographic shell" over on VTY4 if running as init. This will also happen automatically as part of the installation process unless .Ar noHoloShell is set. .Pp .Sy Variables : None .It installFixitCDROM Go into "fixit" mode, assuming a live file system CDROM currently in the drive. .Pp .Sy Variables : None .It installFixitFloppy Go into "fixit" mode, assuming an available fixit floppy disk (user will be prompted for it). .Pp .Sy Variables : None .It installFilesystems Do just the file system initialization part of an install. .Pp .Sy Variables : None .It installVarDefaults Initialize all variables to their defaults, overriding any previous settings. .Pp .Sy Variables : None .It loadConfig Sort of like an #include statement, it allows you to load one configuration file from another. .Pp .Sy Variables : .Bl -tag -width indent .It configFile The fully qualified pathname of the file to load. .El .It mediaOpen If a media device is set, mount it. .Pp .Sy Variables : None .It mediaClose If a media device is open, close it. .Pp .Sy Variables : None .It mediaSetCDROM Select a .Fx CDROM as the installation media. .Pp .Sy Variables : None .It mediaSetFloppy Select a pre-made floppy installation set as the installation media. .Pp .Sy Variables : None .It mediaSetDOS Select an existing DOS primary partition as the installation media. The first primary partition found is used (e.g.\& C:). .Pp .Sy Variables : None .It mediaSetTape Select a tape device as the installation media. .Pp .Sy Variables : None .It mediaSetFTP Select an FTP site as the installation media. .Pp .Sy Variables : .Bl -tag -width indent .It hostname The name of the host being installed (non-optional). .It domainname The domain name of the host being installed (optional). .It defaultrouter The default router for this host (non-optional). .It netDev Which host interface to use .Ar ( ed0 or .Ar ep0 , for example. Non-optional). .It netInteractive If set, bring up the interactive network setup form even if all relevant configuration variables are already set (optional). .It ipaddr The IP address for the selected host interface (non-optional). .It netmask The netmask for the selected host interface (non-optional). .It _ftpPath The fully qualified URL of the FTP site containing the .Fx distribution you are interested in, e.g.\& .Ar ftp://ftp.FreeBSD.org/pub/FreeBSD/ . .El .It mediaSetFTPActive Alias for .Ar mediaSetFTP using "active" FTP transfer mode. .Pp .Sy Variables : Same as for .Ar mediaSetFTP . .It mediaSetFTPPassive Alias for .Ar mediaSetFTP using "passive" FTP transfer mode. .Pp .Sy Variables : Same as for .Ar mediaSetFTP . .It mediaSetHTTP Alias for .Ar mediaSetFTP using an HTTP proxy. .Pp .Sy Variables : See .Ar mediaSetFTP , plus .Bl -tag -width indent .It _httpPath The proxy to use (host:port) (non-optional). .El .It mediaSetUFS Select an existing UFS partition (mounted with the label editor) as the installation media. .Pp .Sy Variables : .Bl -tag -width indent .It ufs full /path to directory containing the .Fx distribution you are interested in. .El .It mediaSetNFS .Pp .Sy Variables : .Bl -tag -width indent .It hostname The name of the host being installed (non-optional). .It domainname The domain name of the host being installed (optional). .It defaultrouter The default router for this host (non-optional). .It netDev Which host interface to use .Ar ( ed0 or .Ar ep0 , for example. Non-optional). .It netInteractive If set, bring up the interactive network setup form even if all relevant configuration variables are already set (optional). .It ipaddr The IP address for the selected host interface (non-optional). .It netmask The netmask for the selected host interface (non-optional). .It nfs full hostname:/path specification for directory containing the .Fx distribution you are interested in. .El .It mediaSetFTPUserPass .Pp .Sy Variables : .Bl -tag -width indent .It ftpUser The username to log in as on the ftp server site. Default: ftp .It ftpPass The password to use for this username on the ftp server site. Default: user@host .El .It mediaSetCPIOVerbosity .Pp .Sy Variables : .Bl -tag -width indent .It cpioVerbose Can be used to set the verbosity of cpio extractions to low, medium or high. .El .It mediaGetType Interactively get the user to specify some type of media. .Pp .Sy Variables : None .It optionsEditor Invoke the interactive options editor. .Pp .Sy Variables : None .It packageAdd Try to fetch and add a package to the system (requires that a media type be set), .Pp .Sy Variables : .Bl -tag -width indent .It package The name of the package to add, e.g.\& bash-1.14.7 or ncftp-2.4.2. .El .It addGroup Invoke the interactive group editor. .Pp .Sy Variables : None .It addUser Invoke the interactive user editor. .Pp .Sy Variables : None .It shutdown Stop the script, terminate sysinstall and reboot the system. On the sparc64 platform, the system is halted rather than rebooted. .Pp .Sy Variables : None .It system Execute an arbitrary command with .Xr system 3 .Pp .Sy Variables : .Bl -tag -width indent .It command The name of the command to execute. When running from a boot floppy, very minimal expectations should be made as to what is available until/unless a relatively full system installation has just been done. .El .It tcpMenuSelect Configure a network device. .Pp .Sy Variables : Same as for .Ar mediaSetFTP except that .Ar _ftpPath is not used. .El .Sh DISTRIBUTION MEDIA The following files can be used to affect the operation of .Nm when used during initial system installation. .Bl -tag -width ".Pa packages/INDEX" .It Pa cdrom.inf A text file of properties, listed one per line, that describe the contents of the media in use. The syntax for each line is simply .Dq Ar property No = Ar value . Currently, only the following properties are recognized. .Bl -tag -width ".Va CD_MACHINE_ARCH" .It Va CD_VERSION This property should be set to the .Fx version on the current media volume. For example, .Dq Li "CD_VERSION = 5.3" . .It Va CD_MACHINE_ARCH This property should be set to the architecture of the contents on this volume. This property is normally only used with .Fx products that contain CDs for different architectures, to provide better error messages if users try to install Alpha packages on an i386 machine. For example, .Dq Li "CD_MACHINE_ARCH = alpha" . .It Va CD_VOLUME In a multi-volume collection (such as the .Fx 4-CD set), the .Pa ports/INDEX file on each disc should contain the full package index for the set. The last field of the .Pa INDEX file denotes which volume the package appears on, and the .Va CD_VOLUME property here defines the volume ID of the current disc. .El .It Pa packages/INDEX The package index file. Each package is listed on a separate line with additional meta-data such as the required dependencies. This index is generated by .Dq Li "make index" from the .Xr ports 7 collection. When multi-volume support is enabled, an additional field should be added to each line indicating which media volume contains the given package. .El .Pp For information about building a full release of .Fx , please see .Xr release 7 . .Sh FILES This utility may edit the contents of .Pa /etc/rc.conf , .Pa /etc/hosts , and .Pa /etc/resolv.conf as necessary to reflect changes in the network configuration. .Sh SEE ALSO If you have a reasonably complete source tree online, take a look at .Pa /usr/src/usr.sbin/sysinstall/install.cfg for a sample installation script. .Sh HISTORY This version of .Nm first appeared in .Fx 2.0 . .Sh AUTHORS .An Jordan K. Hubbard Aq jkh@FreeBSD.org .Sh BUGS Editing slice and partition tables on disks which are currently mounted by the system is not allowed. This is generally only a problem when .Nm is run on a system that is already installed. Use .Xr fdisk 8 and .Xr bsdlabel 8 for these tasks. .Pp This utility is a prototype which lasted several years past its expiration date and is greatly in need of death. Index: stable/7/usr.sbin/sysinstall =================================================================== --- stable/7/usr.sbin/sysinstall (revision 190356) +++ stable/7/usr.sbin/sysinstall (revision 190357) Property changes on: stable/7/usr.sbin/sysinstall ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head/usr.sbin/sysinstall:r186581