[BACK]Return to optr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / dump

Annotation of src/sbin/dump/optr.c, Revision 1.30

1.30    ! fvdl        1: /*     $NetBSD: optr.c,v 1.29 2003/03/27 13:56:47 lukem Exp $  */
1.3       cgd         2:
1.1       cgd         3: /*-
1.2       mycroft     4:  * Copyright (c) 1980, 1988, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
1.12      lukem      36: #include <sys/cdefs.h>
1.1       cgd        37: #ifndef lint
1.3       cgd        38: #if 0
                     39: static char sccsid[] = "@(#)optr.c     8.2 (Berkeley) 1/6/94";
                     40: #else
1.30    ! fvdl       41: __RCSID("$NetBSD: optr.c,v 1.29 2003/03/27 13:56:47 lukem Exp $");
1.3       cgd        42: #endif
1.1       cgd        43: #endif /* not lint */
                     44:
                     45: #include <sys/param.h>
1.25      lukem      46: #include <sys/queue.h>
1.1       cgd        47: #include <sys/wait.h>
                     48: #include <sys/time.h>
1.17      lukem      49: #include <sys/ucred.h>
                     50: #include <sys/mount.h>
1.2       mycroft    51:
                     52: #include <errno.h>
1.1       cgd        53: #include <fstab.h>
                     54: #include <grp.h>
1.2       mycroft    55: #include <signal.h>
                     56: #include <stdio.h>
1.1       cgd        57: #include <stdlib.h>
                     58: #include <string.h>
                     59: #include <stdarg.h>
1.13      kleink     60: #include <time.h>
1.2       mycroft    61: #include <tzfile.h>
                     62: #include <unistd.h>
1.30    ! fvdl       63:
        !            64: #include <ufs/ufs/dinode.h>
1.2       mycroft    65:
1.1       cgd        66: #include "dump.h"
                     67: #include "pathnames.h"
                     68:
1.15      lukem      69: void   alarmcatch(int);
                     70: struct fstab *allocfsent(struct fstab *);
                     71: int    datesort(const void *, const void *);
1.19      blymn      72: extern  char *time_string;
                     73: extern  char default_time_string[];
                     74:
1.21      lukem      75: static void do_timestamp(time_t, char *);
1.1       cgd        76:
                     77: /*
                     78:  *     Query the operator; This previously-fascist piece of code
                     79:  *     no longer requires an exact response.
                     80:  *     It is intended to protect dump aborting by inquisitive
                     81:  *     people banging on the console terminal to see what is
                     82:  *     happening which might cause dump to croak, destroying
                     83:  *     a large number of hours of work.
                     84:  *
                     85:  *     Every 2 minutes we reprint the message, alerting others
                     86:  *     that dump needs attention.
                     87:  */
1.2       mycroft    88: static int timeout;
                     89: static char *attnmessage;              /* attention message */
1.1       cgd        90:
                     91: int
1.15      lukem      92: query(char *question)
1.1       cgd        93: {
                     94:        char    replybuffer[64];
                     95:        int     back, errcount;
                     96:        FILE    *mytty;
1.4       jtk        97:        time_t  firstprompt, when_answered;
                     98:
                     99:        firstprompt = time((time_t *)0);
1.1       cgd       100:
                    101:        if ((mytty = fopen(_PATH_TTY, "r")) == NULL)
                    102:                quit("fopen on %s fails: %s\n", _PATH_TTY, strerror(errno));
                    103:        attnmessage = question;
                    104:        timeout = 0;
1.12      lukem     105:        alarmcatch(0);
1.1       cgd       106:        back = -1;
                    107:        errcount = 0;
                    108:        do {
                    109:                if (fgets(replybuffer, 63, mytty) == NULL) {
                    110:                        clearerr(mytty);
                    111:                        if (++errcount > 30)    /* XXX  ugly */
                    112:                                quit("excessive operator query failures\n");
                    113:                } else if (replybuffer[0] == 'y' || replybuffer[0] == 'Y') {
                    114:                        back = 1;
                    115:                } else if (replybuffer[0] == 'n' || replybuffer[0] == 'N') {
                    116:                        back = 0;
                    117:                } else {
                    118:                        (void) fprintf(stderr,
                    119:                            "  DUMP: \"Yes\" or \"No\"?\n");
                    120:                        (void) fprintf(stderr,
                    121:                            "  DUMP: %s: (\"yes\" or \"no\") ", question);
                    122:                }
                    123:        } while (back < 0);
                    124:
                    125:        /*
                    126:         *      Turn off the alarm, and reset the signal to trap out..
                    127:         */
                    128:        (void) alarm(0);
                    129:        if (signal(SIGALRM, sig) == SIG_IGN)
                    130:                signal(SIGALRM, SIG_IGN);
                    131:        (void) fclose(mytty);
1.4       jtk       132:        when_answered = time((time_t *)0);
                    133:        /*
                    134:         * Adjust the base for time estimates to ignore time we spent waiting
                    135:         * for operator input.
                    136:         */
                    137:        if (tstart_writing != 0)
                    138:            tstart_writing += (when_answered - firstprompt);
1.1       cgd       139:        return(back);
                    140: }
                    141:
1.20      lukem     142: char lastmsg[200];
1.1       cgd       143:
                    144: /*
                    145:  *     Alert the console operator, and enable the alarm clock to
                    146:  *     sleep for 2 minutes in case nobody comes to satisfy dump
                    147:  */
1.2       mycroft   148: void
1.15      lukem     149: alarmcatch(int dummy)
1.1       cgd       150: {
1.15      lukem     151:
1.1       cgd       152:        if (notify == 0) {
                    153:                if (timeout == 0)
                    154:                        (void) fprintf(stderr,
                    155:                            "  DUMP: %s: (\"yes\" or \"no\") ",
                    156:                            attnmessage);
                    157:                else
1.25      lukem     158:                        msgtail("\a\a");
1.1       cgd       159:        } else {
                    160:                if (timeout) {
                    161:                        msgtail("\n");
                    162:                        broadcast("");          /* just print last msg */
                    163:                }
                    164:                (void) fprintf(stderr,"  DUMP: %s: (\"yes\" or \"no\") ",
                    165:                    attnmessage);
                    166:        }
                    167:        signal(SIGALRM, alarmcatch);
                    168:        (void) alarm(120);
                    169:        timeout = 1;
                    170: }
                    171:
                    172: /*
                    173:  *     Here if an inquisitive operator interrupts the dump program
                    174:  */
                    175: void
1.15      lukem     176: interrupt(int signo)
1.1       cgd       177: {
1.28      yamt      178:        int errno_save;
1.15      lukem     179:
1.28      yamt      180:        errno_save = errno;
1.1       cgd       181:        msg("Interrupt received.\n");
                    182:        if (query("Do you want to abort dump?"))
                    183:                dumpabort(0);
1.28      yamt      184:        errno = errno_save;
1.1       cgd       185: }
                    186:
                    187: /*
1.29      lukem     188:  *     Use wall(1) "-g operator" to do the actual broadcasting.
1.1       cgd       189:  */
                    190: void
1.15      lukem     191: broadcast(char *message)
1.1       cgd       192: {
1.29      lukem     193:        FILE    *fp;
                    194:        char    buf[sizeof(_PATH_WALL) + sizeof(OPGRENT) + 3];
1.1       cgd       195:
1.29      lukem     196:        if (!notify)
1.1       cgd       197:                return;
                    198:
1.29      lukem     199:        (void)snprintf(buf, sizeof(buf), "%s -g %s", _PATH_WALL, OPGRENT);
                    200:        if ((fp = popen(buf, "w")) == NULL)
1.1       cgd       201:                return;
                    202:
1.29      lukem     203:        (void) fputs("\a\a\aMessage from the dump program to all operators\n\nDUMP: NEEDS ATTENTION: ", fp);
                    204:        if (lastmsg[0])
                    205:                (void) fputs(lastmsg, fp);
                    206:        if (message[0])
                    207:                (void) fputs(message, fp);
1.1       cgd       208:
1.29      lukem     209:        (void) pclose(fp);
1.1       cgd       210: }
                    211:
                    212: /*
1.22      lukem     213:  *     print out the timestamp string to stderr.
1.19      blymn     214:  */
                    215: #define STAMP_LENGTH 80
                    216:
                    217: static void
1.21      lukem     218: do_timestamp(time_t thistime, char *message)
1.19      blymn     219: {
                    220:        struct tm tm_time;
                    221:        char then[STAMP_LENGTH + 1];
1.23      lukem     222:
1.21      lukem     223:        (void) localtime_r(&thistime, &tm_time);
1.19      blymn     224:        if (strftime(then, STAMP_LENGTH, time_string, &tm_time) == 0) {
                    225:                time_string = default_time_string;
                    226:                strftime(then, STAMP_LENGTH, time_string, &tm_time);
                    227:                fprintf(stderr,
                    228:                   "DUMP: ERROR: TIMEFORMAT too long, reverting to default\n");
                    229:        }
1.23      lukem     230:
1.21      lukem     231:        fprintf(stderr, message, then);
1.19      blymn     232: }
                    233:
1.23      lukem     234:
1.19      blymn     235: /*
1.1       cgd       236:  *     print out an estimate of the amount of time left to do the dump
                    237:  */
                    238:
                    239: time_t tschedule = 0;
                    240:
                    241: void
1.15      lukem     242: timeest(void)
1.1       cgd       243: {
                    244:        time_t  tnow, deltat;
                    245:
                    246:        (void) time((time_t *) &tnow);
                    247:        if (tnow >= tschedule) {
                    248:                tschedule = tnow + 300;
                    249:                if (blockswritten < 500)
1.23      lukem     250:                        return;
1.1       cgd       251:                deltat = tstart_writing - tnow +
                    252:                        (1.0 * (tnow - tstart_writing))
                    253:                        / blockswritten * tapesize;
1.19      blymn     254:
                    255:                msg("%3.2f%% done, finished in %ld:%02ld",
1.14      is        256:                    (blockswritten * 100.0) / tapesize,
                    257:                    (long)(deltat / 3600), (long)((deltat % 3600) / 60));
1.23      lukem     258:
1.19      blymn     259:                if (timestamp == 1)
                    260:                        do_timestamp(tnow + deltat, " (at %s)");
                    261:
                    262:                fprintf(stderr, "\n");
1.1       cgd       263:        }
                    264: }
                    265:
                    266: void
                    267: msg(const char *fmt, ...)
                    268: {
1.22      lukem     269:        time_t  tnow;
1.1       cgd       270:        va_list ap;
                    271:
1.19      blymn     272:        fprintf(stderr, "  ");
1.22      lukem     273:        if (timestamp == 1) {
                    274:                (void) time((time_t *) &tnow);
1.19      blymn     275:                do_timestamp(tnow, "[%s] ");
1.22      lukem     276:        }
1.19      blymn     277:
                    278:        (void) fprintf(stderr,"DUMP: ");
1.1       cgd       279: #ifdef TDEBUG
                    280:        (void) fprintf(stderr, "pid=%d ", getpid());
                    281: #endif
                    282:        va_start(ap, fmt);
1.20      lukem     283:        (void) vsnprintf(lastmsg, sizeof lastmsg, fmt, ap);
                    284:        fputs(lastmsg, stderr);
1.1       cgd       285:        (void) fflush(stdout);
                    286:        (void) fflush(stderr);
                    287:        va_end(ap);
                    288: }
                    289:
                    290: void
                    291: msgtail(const char *fmt, ...)
                    292: {
                    293:        va_list ap;
1.15      lukem     294:
1.1       cgd       295:        va_start(ap, fmt);
                    296:        (void) vfprintf(stderr, fmt, ap);
                    297:        va_end(ap);
                    298: }
                    299:
                    300: void
                    301: quit(const char *fmt, ...)
                    302: {
                    303:        va_list ap;
                    304:
                    305:        (void) fprintf(stderr,"  DUMP: ");
                    306: #ifdef TDEBUG
                    307:        (void) fprintf(stderr, "pid=%d ", getpid());
                    308: #endif
                    309:        va_start(ap, fmt);
                    310:        (void) vfprintf(stderr, fmt, ap);
                    311:        va_end(ap);
                    312:        (void) fflush(stdout);
                    313:        (void) fflush(stderr);
                    314:        dumpabort(0);
                    315: }
                    316:
                    317: /*
                    318:  *     Tell the operator what has to be done;
                    319:  *     we don't actually do it
                    320:  */
                    321:
                    322: struct fstab *
1.15      lukem     323: allocfsent(struct fstab *fs)
1.1       cgd       324: {
1.7       lukem     325:        struct fstab *new;
1.1       cgd       326:
1.17      lukem     327:        new = (struct fstab *)xmalloc(sizeof (*fs));
                    328:        new->fs_file = xstrdup(fs->fs_file);
                    329:        new->fs_type = xstrdup(fs->fs_type);
                    330:        new->fs_spec = xstrdup(fs->fs_spec);
1.1       cgd       331:        new->fs_passno = fs->fs_passno;
                    332:        new->fs_freq = fs->fs_freq;
                    333:        return (new);
                    334: }
                    335:
                    336: struct pfstab {
1.25      lukem     337:        SLIST_ENTRY(pfstab) pf_list;
1.1       cgd       338:        struct  fstab *pf_fstab;
                    339: };
                    340:
1.25      lukem     341: static SLIST_HEAD(, pfstab) table;
1.1       cgd       342:
                    343: void
1.15      lukem     344: getfstab(void)
1.1       cgd       345: {
1.7       lukem     346:        struct fstab *fs;
                    347:        struct pfstab *pf;
1.1       cgd       348:
                    349:        if (setfsent() == 0) {
                    350:                msg("Can't open %s for dump table information: %s\n",
                    351:                    _PATH_FSTAB, strerror(errno));
                    352:                return;
                    353:        }
1.2       mycroft   354:        while ((fs = getfsent()) != NULL) {
1.1       cgd       355:                if (strcmp(fs->fs_type, FSTAB_RW) &&
                    356:                    strcmp(fs->fs_type, FSTAB_RO) &&
                    357:                    strcmp(fs->fs_type, FSTAB_RQ))
1.5       perry     358:                        continue;
1.24      lukem     359: #ifdef DUMP_LFS
                    360:                if (strcmp(fs->fs_vfstype, "lfs"))
                    361:                        continue;
                    362: #else
1.5       perry     363:                if (strcmp(fs->fs_vfstype, "ufs") &&
                    364:                    strcmp(fs->fs_vfstype, "ffs"))
1.1       cgd       365:                        continue;
1.24      lukem     366: #endif
1.1       cgd       367:                fs = allocfsent(fs);
1.17      lukem     368:                pf = (struct pfstab *)xmalloc(sizeof (*pf));
1.1       cgd       369:                pf->pf_fstab = fs;
1.25      lukem     370:                SLIST_INSERT_HEAD(&table, pf, pf_list);
1.1       cgd       371:        }
                    372:        (void) endfsent();
                    373: }
                    374:
                    375: /*
                    376:  * Search in the fstab for a file name.
                    377:  * This file name can be either the special or the path file name.
                    378:  *
                    379:  * The entries in the fstab are the BLOCK special names, not the
                    380:  * character special names.
                    381:  * The caller of fstabsearch assures that the character device
                    382:  * is dumped (that is much faster)
                    383:  *
                    384:  * The file name can omit the leading '/'.
                    385:  */
                    386: struct fstab *
1.17      lukem     387: fstabsearch(const char *key)
1.1       cgd       388: {
1.7       lukem     389:        struct pfstab *pf;
                    390:        struct fstab *fs;
1.2       mycroft   391:        char *rn;
1.1       cgd       392:
1.25      lukem     393:        SLIST_FOREACH(pf, &table, pf_list) {
1.1       cgd       394:                fs = pf->pf_fstab;
                    395:                if (strcmp(fs->fs_file, key) == 0 ||
                    396:                    strcmp(fs->fs_spec, key) == 0)
                    397:                        return (fs);
                    398:                rn = rawname(fs->fs_spec);
                    399:                if (rn != NULL && strcmp(rn, key) == 0)
                    400:                        return (fs);
                    401:                if (key[0] != '/') {
                    402:                        if (*fs->fs_spec == '/' &&
                    403:                            strcmp(fs->fs_spec + 1, key) == 0)
                    404:                                return (fs);
                    405:                        if (*fs->fs_file == '/' &&
                    406:                            strcmp(fs->fs_file + 1, key) == 0)
                    407:                                return (fs);
                    408:                }
                    409:        }
                    410:        return (NULL);
                    411: }
1.17      lukem     412:
                    413: /*
                    414:  * Search in the mounted file list for a file name.
                    415:  * This file name can be either the special or the path file name.
                    416:  *
                    417:  * The entries in the list are the BLOCK special names, not the
                    418:  * character special names.
                    419:  * The caller of mntinfosearch assures that the character device
                    420:  * is dumped (that is much faster)
                    421:  */
                    422: struct statfs *
                    423: mntinfosearch(const char *key)
                    424: {
                    425:        int i, mntbufc;
                    426:        struct statfs *mntbuf, *fs;
                    427:        char *rn;
                    428:
                    429:        if ((mntbufc = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0)
                    430:                quit("Can't get mount list: %s", strerror(errno));
                    431:        for (fs = mntbuf, i = 0; i < mntbufc; i++, fs++) {
                    432:                if (strcmp(fs->f_fstypename, "ufs") != 0 &&
                    433:                    strcmp(fs->f_fstypename, "ffs") != 0)
                    434:                        continue;
                    435:                if (strcmp(fs->f_mntonname, key) == 0 ||
                    436:                    strcmp(fs->f_mntfromname, key) == 0)
                    437:                        return (fs);
                    438:                rn = rawname(fs->f_mntfromname);
                    439:                if (rn != NULL && strcmp(rn, key) == 0)
                    440:                        return (fs);
                    441:        }
                    442:        return (NULL);
                    443: }
                    444:
1.1       cgd       445:
                    446: /*
1.15      lukem     447:  *     Tell the operator what to do.
                    448:  *     arg:    w ==> just what to do; W ==> most recent dumps
1.1       cgd       449:  */
                    450: void
1.15      lukem     451: lastdump(char arg)
1.1       cgd       452: {
1.7       lukem     453:        int i;
                    454:        struct fstab *dt;
                    455:        struct dumpdates *dtwalk;
1.1       cgd       456:        char *lastname, *date;
1.2       mycroft   457:        int dumpme;
1.1       cgd       458:        time_t tnow;
                    459:
                    460:        (void) time(&tnow);
                    461:        getfstab();             /* /etc/fstab input */
                    462:        initdumptimes();        /* /etc/dumpdates input */
                    463:        qsort((char *) ddatev, nddates, sizeof(struct dumpdates *), datesort);
                    464:
                    465:        if (arg == 'w')
                    466:                (void) printf("Dump these file systems:\n");
                    467:        else
                    468:                (void) printf("Last dump(s) done (Dump '>' file systems):\n");
                    469:        lastname = "??";
                    470:        ITITERATE(i, dtwalk) {
                    471:                if (strncmp(lastname, dtwalk->dd_name,
                    472:                    sizeof(dtwalk->dd_name)) == 0)
                    473:                        continue;
                    474:                date = (char *)ctime(&dtwalk->dd_ddate);
1.6       lukem     475:                date[24] = '\0';
                    476:                strcpy(date + 16, date + 19);   /* blast away seconds */
1.1       cgd       477:                lastname = dtwalk->dd_name;
                    478:                dt = fstabsearch(dtwalk->dd_name);
                    479:                dumpme = (dt != NULL &&
                    480:                    dt->fs_freq != 0 &&
                    481:                    dtwalk->dd_ddate < tnow - (dt->fs_freq * SECSPERDAY));
                    482:                if (arg != 'w' || dumpme)
                    483:                        (void) printf(
                    484:                            "%c %8s\t(%6s) Last dump: Level %c, Date %s\n",
                    485:                            dumpme && (arg != 'w') ? '>' : ' ',
                    486:                            dtwalk->dd_name,
                    487:                            dt ? dt->fs_file : "",
                    488:                            dtwalk->dd_level,
                    489:                            date);
                    490:        }
                    491: }
                    492:
                    493: int
1.15      lukem     494: datesort(const void *a1, const void *a2)
1.1       cgd       495: {
                    496:        struct dumpdates *d1 = *(struct dumpdates **)a1;
                    497:        struct dumpdates *d2 = *(struct dumpdates **)a2;
                    498:        int diff;
                    499:
                    500:        diff = strncmp(d1->dd_name, d2->dd_name, sizeof(d1->dd_name));
                    501:        if (diff == 0)
                    502:                return (d2->dd_ddate - d1->dd_ddate);
                    503:        return (diff);
                    504: }

CVSweb <webmaster@jp.NetBSD.org>