~ubuntu-branches/debian/jessie/ufsutils/jessie

« back to all changes in this revision

Viewing changes to .pc/02_fsck.ufs.patch/sbin/fsck_ffs/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Guillem Jover, Robert Millan, Guillem Jover, Peter Pentchev
  • Date: 2011-05-31 03:50:05 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20110531035005-wyiyk25p99ivd0k0
Tags: 8.2-1
[ Robert Millan ]
* Set ufsutils-udeb to kfreebsd-any.

[ Guillem Jover ]
* New upstream version (based on FreeBSD 8.2)
* Now using Standards-Version 3.9.2 (no changes needed).
* Switch to source format “3.0 (quilt)”.
  - Remove quilt from Build-Depends.
  - Remove patch target in debian/rules.
  - Remove now unneeded README.source.
  - Refresh all patches.
* Reorganize source code:
  - Switch from debian/upstream.sh to debian/rules get-orig-source target.
  - Switch from CVS to Subversion to retrieve the source code.
  - Use the same source layout as upstream (no more relocations),
    i.e. lib/, sbin/, sys/sys, sys/ufs.
  - Move libport/ to port/.
  - Merge libdisklabel/ into port/.
* Remove unneeded linking against libtermcap, thus removing the need for
  ncurses.
* Add an empty debian/watch file explaining that there's no packaged
  upstream releases. Suggested by Peter Pentchev.
* Update CVS to Subversion reference to upstream source code in
  debian/copyright.
* Remove unused lib variable from debian/rules.
* Use dpkg-buildflags to set CPPFLAGS, CFLAGS and LDFLAGS.
  Based on a patch by Peter Pentchev.
* Remove bogus reference to BSD license in /usr/share/common-licenses.
* Always set -I../../sys, even on GNU/kFreeBSD systems.

[ Peter Pentchev ]
* Remove duplicate section “utils” from ufsutils binary package.
* Remove XC- prefix from Package-Type.
* Honour CPPFLAGS and LDFLAGS and do not link with CFLAGS.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1980, 1986, 1993
 
3
 *      The Regents of the University of California.  All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer.
 
10
 * 2. Redistributions in binary form must reproduce the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer in the
 
12
 *    documentation and/or other materials provided with the distribution.
 
13
 * 4. Neither the name of the University nor the names of its contributors
 
14
 *    may be used to endorse or promote products derived from this software
 
15
 *    without specific prior written permission.
 
16
 *
 
17
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
27
 * SUCH DAMAGE.
 
28
 */
 
29
 
 
30
#if 0
 
31
#ifndef lint
 
32
static const char copyright[] =
 
33
"@(#) Copyright (c) 1980, 1986, 1993\n\
 
34
        The Regents of the University of California.  All rights reserved.\n";
 
35
#endif /* not lint */
 
36
 
 
37
#ifndef lint
 
38
static char sccsid[] = "@(#)main.c      8.6 (Berkeley) 5/14/95";
 
39
#endif /* not lint */
 
40
#endif
 
41
#include <sys/cdefs.h>
 
42
__FBSDID("$FreeBSD$");
 
43
 
 
44
#include <sys/param.h>
 
45
#include <sys/stat.h>
 
46
#include <sys/file.h>
 
47
#include <sys/time.h>
 
48
#include <sys/mount.h>
 
49
#include <sys/resource.h>
 
50
#include <sys/sysctl.h>
 
51
#include <sys/uio.h>
 
52
#include <sys/disklabel.h>
 
53
 
 
54
#include <ufs/ufs/dinode.h>
 
55
#include <ufs/ffs/fs.h>
 
56
 
 
57
#include <err.h>
 
58
#include <errno.h>
 
59
#include <fstab.h>
 
60
#include <grp.h>
 
61
#include <mntopts.h>
 
62
#include <paths.h>
 
63
#include <stdint.h>
 
64
#include <string.h>
 
65
 
 
66
#include "fsck.h"
 
67
 
 
68
static void usage(void) __dead2;
 
69
static int argtoi(int flag, const char *req, const char *str, int base);
 
70
static int checkfilesys(char *filesys);
 
71
static int chkdoreload(struct statfs *mntp);
 
72
static struct statfs *getmntpt(const char *);
 
73
 
 
74
int
 
75
main(int argc, char *argv[])
 
76
{
 
77
        int ch;
 
78
        struct rlimit rlimit;
 
79
        struct itimerval itimerval;
 
80
        int ret = 0;
 
81
 
 
82
        sync();
 
83
        skipclean = 1;
 
84
        inoopt = 0;
 
85
        while ((ch = getopt(argc, argv, "b:Bc:CdfFm:npry")) != -1) {
 
86
                switch (ch) {
 
87
                case 'b':
 
88
                        skipclean = 0;
 
89
                        bflag = argtoi('b', "number", optarg, 10);
 
90
                        printf("Alternate super block location: %d\n", bflag);
 
91
                        break;
 
92
 
 
93
                case 'B':
 
94
                        bkgrdflag = 1;
 
95
                        break;
 
96
 
 
97
                case 'c':
 
98
                        skipclean = 0;
 
99
                        cvtlevel = argtoi('c', "conversion level", optarg, 10);
 
100
                        if (cvtlevel < 3)
 
101
                                errx(EEXIT, "cannot do level %d conversion",
 
102
                                    cvtlevel);
 
103
                        break;
 
104
 
 
105
                case 'd':
 
106
                        debug++;
 
107
                        break;
 
108
 
 
109
                case 'f':
 
110
                        skipclean = 0;
 
111
                        break;
 
112
 
 
113
                case 'F':
 
114
                        bkgrdcheck = 1;
 
115
                        break;
 
116
 
 
117
                case 'm':
 
118
                        lfmode = argtoi('m', "mode", optarg, 8);
 
119
                        if (lfmode &~ 07777)
 
120
                                errx(EEXIT, "bad mode to -m: %o", lfmode);
 
121
                        printf("** lost+found creation mode %o\n", lfmode);
 
122
                        break;
 
123
 
 
124
                case 'n':
 
125
                        nflag++;
 
126
                        yflag = 0;
 
127
                        break;
 
128
 
 
129
                case 'p':
 
130
                        preen++;
 
131
                        /*FALLTHROUGH*/
 
132
 
 
133
                case 'C':
 
134
                        ckclean++;
 
135
                        break;
 
136
 
 
137
                case 'r':
 
138
                        inoopt++;
 
139
                        break;
 
140
 
 
141
                case 'y':
 
142
                        yflag++;
 
143
                        nflag = 0;
 
144
                        break;
 
145
 
 
146
                default:
 
147
                        usage();
 
148
                }
 
149
        }
 
150
        argc -= optind;
 
151
        argv += optind;
 
152
 
 
153
        if (!argc)
 
154
                usage();
 
155
 
 
156
        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 
157
                (void)signal(SIGINT, catch);
 
158
        if (ckclean)
 
159
                (void)signal(SIGQUIT, catchquit);
 
160
        signal(SIGINFO, infohandler);
 
161
        if (bkgrdflag) {
 
162
                signal(SIGALRM, alarmhandler);
 
163
                itimerval.it_interval.tv_sec = 5;
 
164
                itimerval.it_interval.tv_usec = 0;
 
165
                itimerval.it_value.tv_sec = 5;
 
166
                itimerval.it_value.tv_usec = 0;
 
167
                setitimer(ITIMER_REAL, &itimerval, NULL);
 
168
        }
 
169
        /*
 
170
         * Push up our allowed memory limit so we can cope
 
171
         * with huge file systems.
 
172
         */
 
173
        if (getrlimit(RLIMIT_DATA, &rlimit) == 0) {
 
174
                rlimit.rlim_cur = rlimit.rlim_max;
 
175
                (void)setrlimit(RLIMIT_DATA, &rlimit);
 
176
        }
 
177
        while (argc-- > 0)
 
178
                (void)checkfilesys(*argv++);
 
179
 
 
180
        if (returntosingle)
 
181
                ret = 2;
 
182
        exit(ret);
 
183
}
 
184
 
 
185
static int
 
186
argtoi(int flag, const char *req, const char *str, int base)
 
187
{
 
188
        char *cp;
 
189
        int ret;
 
190
 
 
191
        ret = (int)strtol(str, &cp, base);
 
192
        if (cp == str || *cp)
 
193
                errx(EEXIT, "-%c flag requires a %s", flag, req);
 
194
        return (ret);
 
195
}
 
196
 
 
197
/*
 
198
 * Check the specified file system.
 
199
 */
 
200
/* ARGSUSED */
 
201
static int
 
202
checkfilesys(char *filesys)
 
203
{
 
204
        ufs2_daddr_t n_ffree, n_bfree;
 
205
        struct dups *dp;
 
206
        struct statfs *mntp;
 
207
        struct stat snapdir;
 
208
        struct group *grp;
 
209
        ufs2_daddr_t blks;
 
210
        struct iovec *iov;
 
211
        char errmsg[255];
 
212
        int iovlen;
 
213
        int cylno;
 
214
        ino_t files;
 
215
        size_t size;
 
216
 
 
217
        iov = NULL;
 
218
        iovlen = 0;
 
219
        errmsg[0] = '\0';
 
220
 
 
221
        cdevname = filesys;
 
222
        if (debug && ckclean)
 
223
                pwarn("starting\n");
 
224
        /*
 
225
         * Make best effort to get the disk name. Check first to see
 
226
         * if it is listed among the mounted file systems. Failing that
 
227
         * check to see if it is listed in /etc/fstab.
 
228
         */
 
229
        mntp = getmntpt(filesys);
 
230
        if (mntp != NULL)
 
231
                filesys = mntp->f_mntfromname;
 
232
        else
 
233
                filesys = blockcheck(filesys);
 
234
        /*
 
235
         * If -F flag specified, check to see whether a background check
 
236
         * is possible and needed. If possible and needed, exit with
 
237
         * status zero. Otherwise exit with status non-zero. A non-zero
 
238
         * exit status will cause a foreground check to be run.
 
239
         */
 
240
        sblock_init();
 
241
        if (bkgrdcheck) {
 
242
                if ((fsreadfd = open(filesys, O_RDONLY)) < 0 || readsb(0) == 0)
 
243
                        exit(3);        /* Cannot read superblock */
 
244
                close(fsreadfd);
 
245
                if (sblock.fs_flags & FS_NEEDSFSCK)
 
246
                        exit(4);        /* Earlier background failed */
 
247
                if ((sblock.fs_flags & FS_DOSOFTDEP) == 0)
 
248
                        exit(5);        /* Not running soft updates */
 
249
                size = MIBSIZE;
 
250
                if (sysctlnametomib("vfs.ffs.adjrefcnt", adjrefcnt, &size) < 0)
 
251
                        exit(6);        /* Lacks kernel support */
 
252
                if ((mntp == NULL && sblock.fs_clean == 1) ||
 
253
                    (mntp != NULL && (sblock.fs_flags & FS_UNCLEAN) == 0))
 
254
                        exit(7);        /* Filesystem clean, report it now */
 
255
                exit(0);
 
256
        }
 
257
        if (ckclean && skipclean) {
 
258
                /*
 
259
                 * If file system is gjournaled, check it here.
 
260
                 */
 
261
                if ((fsreadfd = open(filesys, O_RDONLY)) < 0 || readsb(0) == 0)
 
262
                        exit(3);        /* Cannot read superblock */
 
263
                close(fsreadfd);
 
264
                if ((sblock.fs_flags & FS_GJOURNAL) != 0) {
 
265
                        //printf("GJournaled file system detected on %s.\n",
 
266
                        //    filesys);
 
267
                        if (sblock.fs_clean == 1) {
 
268
                                pwarn("FILE SYSTEM CLEAN; SKIPPING CHECKS\n");
 
269
                                exit(0);
 
270
                        }
 
271
                        if ((sblock.fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) == 0) {
 
272
                                gjournal_check(filesys);
 
273
                                if (chkdoreload(mntp) == 0)
 
274
                                        exit(0);
 
275
                                exit(4);
 
276
                        } else {
 
277
                                pfatal("UNEXPECTED INCONSISTENCY, %s\n",
 
278
                                    "CANNOT RUN FAST FSCK\n");
 
279
                        }
 
280
                }
 
281
        }
 
282
        /*
 
283
         * If we are to do a background check:
 
284
         *      Get the mount point information of the file system
 
285
         *      create snapshot file
 
286
         *      return created snapshot file
 
287
         *      if not found, clear bkgrdflag and proceed with normal fsck
 
288
         */
 
289
        if (bkgrdflag) {
 
290
                if (mntp == NULL) {
 
291
                        bkgrdflag = 0;
 
292
                        pfatal("NOT MOUNTED, CANNOT RUN IN BACKGROUND\n");
 
293
                } else if ((mntp->f_flags & MNT_SOFTDEP) == 0) {
 
294
                        bkgrdflag = 0;
 
295
                        pfatal("NOT USING SOFT UPDATES, %s\n",
 
296
                            "CANNOT RUN IN BACKGROUND");
 
297
                } else if ((mntp->f_flags & MNT_RDONLY) != 0) {
 
298
                        bkgrdflag = 0;
 
299
                        pfatal("MOUNTED READ-ONLY, CANNOT RUN IN BACKGROUND\n");
 
300
                } else if ((fsreadfd = open(filesys, O_RDONLY)) >= 0) {
 
301
                        if (readsb(0) != 0) {
 
302
                                if (sblock.fs_flags & FS_NEEDSFSCK) {
 
303
                                        bkgrdflag = 0;
 
304
                                        pfatal("UNEXPECTED INCONSISTENCY, %s\n",
 
305
                                            "CANNOT RUN IN BACKGROUND\n");
 
306
                                }
 
307
                                if ((sblock.fs_flags & FS_UNCLEAN) == 0 &&
 
308
                                    skipclean && ckclean) {
 
309
                                        /*
 
310
                                         * file system is clean;
 
311
                                         * skip snapshot and report it clean
 
312
                                         */
 
313
                                        pwarn("FILE SYSTEM CLEAN; %s\n",
 
314
                                            "SKIPPING CHECKS");
 
315
                                        goto clean;
 
316
                                }
 
317
                        }
 
318
                        close(fsreadfd);
 
319
                }
 
320
                if (bkgrdflag) {
 
321
                        snprintf(snapname, sizeof snapname, "%s/.snap",
 
322
                            mntp->f_mntonname);
 
323
                        if (stat(snapname, &snapdir) < 0) {
 
324
                                if (errno != ENOENT) {
 
325
                                        bkgrdflag = 0;
 
326
                                        pfatal("CANNOT FIND %s %s: %s, %s\n",
 
327
                                            "SNAPSHOT DIRECTORY",
 
328
                                            snapname, strerror(errno),
 
329
                                            "CANNOT RUN IN BACKGROUND");
 
330
                                } else if ((grp = getgrnam("operator")) == 0 ||
 
331
                                    mkdir(snapname, 0770) < 0 ||
 
332
                                    chown(snapname, -1, grp->gr_gid) < 0 ||
 
333
                                    chmod(snapname, 0770) < 0) {
 
334
                                        bkgrdflag = 0;
 
335
                                        pfatal("CANNOT CREATE %s %s: %s, %s\n",
 
336
                                            "SNAPSHOT DIRECTORY",
 
337
                                            snapname, strerror(errno),
 
338
                                            "CANNOT RUN IN BACKGROUND");
 
339
                                }
 
340
                        } else if (!S_ISDIR(snapdir.st_mode)) {
 
341
                                bkgrdflag = 0;
 
342
                                pfatal("%s IS NOT A DIRECTORY, %s\n", snapname,
 
343
                                    "CANNOT RUN IN BACKGROUND");
 
344
                        }
 
345
                }
 
346
                if (bkgrdflag) {
 
347
                        snprintf(snapname, sizeof snapname,
 
348
                            "%s/.snap/fsck_snapshot", mntp->f_mntonname);
 
349
                        build_iovec(&iov, &iovlen, "fstype", "ffs", 4);
 
350
                        build_iovec(&iov, &iovlen, "from", snapname,
 
351
                            (size_t)-1);
 
352
                        build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname,
 
353
                            (size_t)-1);
 
354
                        build_iovec(&iov, &iovlen, "errmsg", errmsg,
 
355
                            sizeof(errmsg));
 
356
                        build_iovec(&iov, &iovlen, "update", NULL, 0);
 
357
                        build_iovec(&iov, &iovlen, "snapshot", NULL, 0);
 
358
 
 
359
                        while (nmount(iov, iovlen, mntp->f_flags) < 0) {
 
360
                                if (errno == EEXIST && unlink(snapname) == 0)
 
361
                                        continue;
 
362
                                bkgrdflag = 0;
 
363
                                pfatal("CANNOT CREATE SNAPSHOT %s: %s %s\n",
 
364
                                    snapname, strerror(errno), errmsg);
 
365
                                break;
 
366
                        }
 
367
                        if (bkgrdflag != 0)
 
368
                                filesys = snapname;
 
369
                }
 
370
        }
 
371
 
 
372
        switch (setup(filesys)) {
 
373
        case 0:
 
374
                if (preen)
 
375
                        pfatal("CAN'T CHECK FILE SYSTEM.");
 
376
                return (0);
 
377
        case -1:
 
378
        clean:
 
379
                pwarn("clean, %ld free ", (long)(sblock.fs_cstotal.cs_nffree +
 
380
                    sblock.fs_frag * sblock.fs_cstotal.cs_nbfree));
 
381
                printf("(%lld frags, %lld blocks, %.1f%% fragmentation)\n",
 
382
                    (long long)sblock.fs_cstotal.cs_nffree,
 
383
                    (long long)sblock.fs_cstotal.cs_nbfree,
 
384
                    sblock.fs_cstotal.cs_nffree * 100.0 / sblock.fs_dsize);
 
385
                return (0);
 
386
        }
 
387
        
 
388
        /*
 
389
         * Cleared if any questions answered no. Used to decide if
 
390
         * the superblock should be marked clean.
 
391
         */
 
392
        resolved = 1;
 
393
        /*
 
394
         * 1: scan inodes tallying blocks used
 
395
         */
 
396
        if (preen == 0) {
 
397
                printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
 
398
                if (mntp != NULL && mntp->f_flags & MNT_ROOTFS)
 
399
                        printf("** Root file system\n");
 
400
                printf("** Phase 1 - Check Blocks and Sizes\n");
 
401
        }
 
402
        pass1();
 
403
 
 
404
        /*
 
405
         * 1b: locate first references to duplicates, if any
 
406
         */
 
407
        if (duplist) {
 
408
                if (preen || usedsoftdep)
 
409
                        pfatal("INTERNAL ERROR: dups with -p");
 
410
                printf("** Phase 1b - Rescan For More DUPS\n");
 
411
                pass1b();
 
412
        }
 
413
 
 
414
        /*
 
415
         * 2: traverse directories from root to mark all connected directories
 
416
         */
 
417
        if (preen == 0)
 
418
                printf("** Phase 2 - Check Pathnames\n");
 
419
        pass2();
 
420
 
 
421
        /*
 
422
         * 3: scan inodes looking for disconnected directories
 
423
         */
 
424
        if (preen == 0)
 
425
                printf("** Phase 3 - Check Connectivity\n");
 
426
        pass3();
 
427
 
 
428
        /*
 
429
         * 4: scan inodes looking for disconnected files; check reference counts
 
430
         */
 
431
        if (preen == 0)
 
432
                printf("** Phase 4 - Check Reference Counts\n");
 
433
        pass4();
 
434
 
 
435
        /*
 
436
         * 5: check and repair resource counts in cylinder groups
 
437
         */
 
438
        if (preen == 0)
 
439
                printf("** Phase 5 - Check Cyl groups\n");
 
440
        pass5();
 
441
 
 
442
        /*
 
443
         * print out summary statistics
 
444
         */
 
445
        n_ffree = sblock.fs_cstotal.cs_nffree;
 
446
        n_bfree = sblock.fs_cstotal.cs_nbfree;
 
447
        files = maxino - ROOTINO - sblock.fs_cstotal.cs_nifree - n_files;
 
448
        blks = n_blks +
 
449
            sblock.fs_ncg * (cgdmin(&sblock, 0) - cgsblock(&sblock, 0));
 
450
        blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0);
 
451
        blks += howmany(sblock.fs_cssize, sblock.fs_fsize);
 
452
        blks = maxfsblock - (n_ffree + sblock.fs_frag * n_bfree) - blks;
 
453
        if (bkgrdflag && (files > 0 || blks > 0)) {
 
454
                countdirs = sblock.fs_cstotal.cs_ndir - countdirs;
 
455
                pwarn("Reclaimed: %ld directories, %ld files, %lld fragments\n",
 
456
                    countdirs, (long)files - countdirs, (long long)blks);
 
457
        }
 
458
        pwarn("%ld files, %jd used, %ju free ",
 
459
            (long)n_files, (intmax_t)n_blks,
 
460
            (uintmax_t)n_ffree + sblock.fs_frag * n_bfree);
 
461
        printf("(%ju frags, %ju blocks, %.1f%% fragmentation)\n",
 
462
            (uintmax_t)n_ffree, (uintmax_t)n_bfree,
 
463
            n_ffree * 100.0 / sblock.fs_dsize);
 
464
        if (debug) {
 
465
                if (files < 0)
 
466
                        printf("%d inodes missing\n", -files);
 
467
                if (blks < 0)
 
468
                        printf("%lld blocks missing\n", -(long long)blks);
 
469
                if (duplist != NULL) {
 
470
                        printf("The following duplicate blocks remain:");
 
471
                        for (dp = duplist; dp; dp = dp->next)
 
472
                                printf(" %lld,", (long long)dp->dup);
 
473
                        printf("\n");
 
474
                }
 
475
        }
 
476
        duplist = (struct dups *)0;
 
477
        muldup = (struct dups *)0;
 
478
        inocleanup();
 
479
        if (fsmodified) {
 
480
                sblock.fs_time = time(NULL);
 
481
                sbdirty();
 
482
        }
 
483
        if (cvtlevel && sblk.b_dirty) {
 
484
                /*
 
485
                 * Write out the duplicate super blocks
 
486
                 */
 
487
                for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
 
488
                        blwrite(fswritefd, (char *)&sblock,
 
489
                            fsbtodb(&sblock, cgsblock(&sblock, cylno)),
 
490
                            SBLOCKSIZE);
 
491
        }
 
492
        if (rerun)
 
493
                resolved = 0;
 
494
 
 
495
        /*
 
496
         * Check to see if the file system is mounted read-write.
 
497
         */
 
498
        if (bkgrdflag == 0 && mntp != NULL && (mntp->f_flags & MNT_RDONLY) == 0)
 
499
                resolved = 0;
 
500
        ckfini(resolved);
 
501
 
 
502
        for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
 
503
                if (inostathead[cylno].il_stat != NULL)
 
504
                        free((char *)inostathead[cylno].il_stat);
 
505
        free((char *)inostathead);
 
506
        inostathead = NULL;
 
507
        if (fsmodified && !preen)
 
508
                printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
 
509
        if (rerun)
 
510
                printf("\n***** PLEASE RERUN FSCK *****\n");
 
511
        if (chkdoreload(mntp) != 0) {
 
512
                if (!fsmodified)
 
513
                        return (0);
 
514
                if (!preen)
 
515
                        printf("\n***** REBOOT NOW *****\n");
 
516
                sync();
 
517
                return (4);
 
518
        }
 
519
        return (0);
 
520
}
 
521
 
 
522
static int
 
523
chkdoreload(struct statfs *mntp)
 
524
{
 
525
        struct iovec *iov;
 
526
        int iovlen;
 
527
        char errmsg[255];
 
528
 
 
529
        if (mntp == NULL)
 
530
                return (0);
 
531
 
 
532
        iov = NULL;
 
533
        iovlen = 0;
 
534
        errmsg[0] = '\0';
 
535
        /*
 
536
         * We modified a mounted file system.  Do a mount update on
 
537
         * it unless it is read-write, so we can continue using it
 
538
         * as safely as possible.
 
539
         */
 
540
        if (mntp->f_flags & MNT_RDONLY) {
 
541
                build_iovec(&iov, &iovlen, "fstype", "ffs", 4);
 
542
                build_iovec(&iov, &iovlen, "from", mntp->f_mntfromname,
 
543
                    (size_t)-1);
 
544
                build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname,
 
545
                    (size_t)-1);
 
546
                build_iovec(&iov, &iovlen, "errmsg", errmsg,
 
547
                    sizeof(errmsg));
 
548
                build_iovec(&iov, &iovlen, "update", NULL, 0);
 
549
                build_iovec(&iov, &iovlen, "reload", NULL, 0);
 
550
                /*
 
551
                 * XX: We need the following line until we clean up
 
552
                 * nmount parsing of root mounts and NFS root mounts.
 
553
                 */ 
 
554
                build_iovec(&iov, &iovlen, "ro", NULL, 0);
 
555
                if (nmount(iov, iovlen, mntp->f_flags) == 0) {
 
556
                        return (0);
 
557
                }
 
558
                pwarn("mount reload of '%s' failed: %s %s\n\n",
 
559
                    mntp->f_mntonname, strerror(errno), errmsg);
 
560
                return (1);
 
561
        }
 
562
        return (0);
 
563
}
 
564
 
 
565
/*
 
566
 * Get the mount point information for name.
 
567
 */
 
568
static struct statfs *
 
569
getmntpt(const char *name)
 
570
{
 
571
        struct stat devstat, mntdevstat;
 
572
        char device[sizeof(_PATH_DEV) - 1 + MNAMELEN];
 
573
        char *ddevname;
 
574
        struct statfs *mntbuf, *statfsp;
 
575
        int i, mntsize, isdev;
 
576
 
 
577
        if (stat(name, &devstat) != 0)
 
578
                return (NULL);
 
579
        if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode))
 
580
                isdev = 1;
 
581
        else
 
582
                isdev = 0;
 
583
        mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
 
584
        for (i = 0; i < mntsize; i++) {
 
585
                statfsp = &mntbuf[i];
 
586
                ddevname = statfsp->f_mntfromname;
 
587
                if (*ddevname != '/') {
 
588
                        strcpy(device, _PATH_DEV);
 
589
                        strcat(device, ddevname);
 
590
                        strcpy(statfsp->f_mntfromname, device);
 
591
                }
 
592
                if (isdev == 0) {
 
593
                        if (strcmp(name, statfsp->f_mntonname))
 
594
                                continue;
 
595
                        return (statfsp);
 
596
                }
 
597
                if (stat(ddevname, &mntdevstat) == 0 &&
 
598
                    mntdevstat.st_rdev == devstat.st_rdev)
 
599
                        return (statfsp);
 
600
        }
 
601
        statfsp = NULL;
 
602
        return (statfsp);
 
603
}
 
604
 
 
605
static void
 
606
usage(void)
 
607
{
 
608
        (void) fprintf(stderr,
 
609
            "usage: %s [-BFprfny] [-b block] [-c level] [-m mode] "
 
610
                        "filesystem ...\n",
 
611
            getprogname());
 
612
        exit(1);
 
613
}