[BACK]Return to target.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / distrib / utils / sysinst

Annotation of src/distrib/utils/sysinst/target.c, Revision 1.22.10.1

1.22.10.1! hubertf     1: /*     $NetBSD: target.c,v 1.23 2000/09/08 02:50:44 hubertf Exp $      */
1.1       jonathan    2:
                      3: /*
1.2       jonathan    4:  * Copyright 1997 Jonathan Stone
1.1       jonathan    5:  * All rights reserved.
                      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:
1.22      cgd        17:  *      This product includes software developed for the NetBSD Project by
1.2       jonathan   18:  *      Jonathan Stone.
                     19:  * 4. The name of Jonathan Stone may not be used to endorse
1.1       jonathan   20:  *    or promote products derived from this software without specific prior
                     21:  *    written permission.
                     22:  *
1.2       jonathan   23:  * THIS SOFTWARE IS PROVIDED BY JONATHAN STONE ``AS IS''
1.1       jonathan   24:  * AND 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 PIERMONT INFORMATION SYSTEMS INC. BE
                     27:  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     28:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     29:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     30:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     31:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     32:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     33:  * THE POSSIBILITY OF SUCH DAMAGE.
                     34:  *
                     35:  */
                     36:
1.5       jonathan   37: #include <sys/cdefs.h>
                     38: #if defined(LIBC_SCCS) && !defined(lint)
1.22.10.1! hubertf    39: __RCSID("$NetBSD: target.c,v 1.23 2000/09/08 02:50:44 hubertf Exp $");
1.5       jonathan   40: #endif
                     41:
                     42: /*
                     43:  * target.c -- path-prefixing routines to access the target installation
                     44:  *  filesystems. Makes  the install tools more ndependent of whether
                     45:  *  we're installing into a separate filesystem hierarchy mounted under /mnt,
                     46:  *  or into the currently active root mounted on /.
                     47:  */
                     48:
                     49: #include <sys/param.h>                 /* XXX vm_param.h always defines TRUE*/
1.8       jonathan   50: #include <sys/types.h>
1.5       jonathan   51: #include <sys/sysctl.h>
1.8       jonathan   52: #include <sys/stat.h>                  /* stat() */
                     53: #include <sys/mount.h>                 /* statfs() */
1.1       jonathan   54:
                     55: #include <stdio.h>
                     56: #include <stdarg.h>
                     57: #include <unistd.h>
1.5       jonathan   58: #include <curses.h>                    /* defines TRUE, but checks  */
1.7       jonathan   59: #include <errno.h>
1.5       jonathan   60:
                     61:
1.1       jonathan   62: #include "defs.h"
                     63: #include "md.h"
                     64: #include "msg_defs.h"
                     65: #include "menu_defs.h"
                     66:
                     67: /*
                     68:  * local  prototypes
                     69:  */
1.8       jonathan   70: static const char*     get_rootdev __P((void));
                     71: static const char* mounted_rootpart __P((void));
                     72: int target_on_current_disk __P((void));
                     73: int must_mount_root __P((void));
                     74:
1.1       jonathan   75: static void make_prefixed_dir __P((const char *prefix, const char *path));
                     76: static int do_target_chdir __P((const char *dir, int flag));
1.4       jonathan   77: static const char* concat_paths __P((const char *prefix, const char *suffix));
1.14      jonathan   78: int    target_test(const char *test, const char *path);
                     79: int    target_test_dir __P((const char *path));        /* deprecated */
                     80: int    target_test_file __P((const char *path));       /* deprecated */
1.22.10.1! hubertf    81: int    target_test_symlink __P((const char *path));    /* deprecated */
1.1       jonathan   82:
1.8       jonathan   83: void backtowin(void);
                     84:
1.13      jonathan   85: void unwind_mounts __P((void));
                     86: int mount_with_unwind(const char *fstype, const char *from, const char *on);
                     87:
                     88: /* Record a mount for later unwinding of target mounts. */
                     89: struct unwind_mount {
                     90:        struct unwind_mount *um_prev;
                     91:        char um_mountpoint[STRSIZE];
                     92: };
                     93:
                     94: /* Unwind-mount stack */
1.16      mrg        95: struct unwind_mount *unwind_mountlist = NULL;
1.13      jonathan   96:
                     97: /*
                     98:  * Debugging options
                     99:  */
                    100: /*#define DEBUG_ROOT*/         /* turn on what-is-root? debugging. */
                    101: /*#define DEBUG_UNWIND*/       /* turn on unwind-target-mount debugging. */
                    102:
1.8       jonathan  103: /*
                    104:  * debugging helper. curses...
                    105:  */
1.16      mrg       106: void
                    107: backtowin()
1.8       jonathan  108: {
                    109:
                    110:        fflush(stdout); /* curses does not leave stdout linebuffered. */
                    111:        getchar();      /* wait for user to press return */
                    112:        wrefresh(stdscr);
                    113: }
                    114:
                    115: /*
                    116:  * Get name of current root device  from kernel via sysctl.
                    117:  * On NetBSD-1.3_ALPHA, this just returns the name of a
                    118:  * device (e.g., "sd0"), not a specific partition -- like "sd0a",
                    119:  * or "sd0b" for root-in-swap.
1.16      mrg       120:  */
                    121: static const char *
1.8       jonathan  122: get_rootdev()
1.5       jonathan  123: {
                    124:        int mib[2];
1.8       jonathan  125:        static char rootdev[STRSIZE];
1.5       jonathan  126:        size_t varlen;
                    127:
                    128:        mib[0] = CTL_KERN;
                    129:        mib[1] = KERN_ROOT_DEVICE;
1.8       jonathan  130:        varlen = sizeof(rootdev);
                    131:        if (sysctl(mib, 2, rootdev, &varlen, NULL, 0) < 0)
1.5       jonathan  132:                return (NULL);
                    133:
                    134: #ifdef DEBUG
1.8       jonathan  135:        printf("get_rootdev(): sysctl returns %s\n", rootdev);
1.5       jonathan  136: #endif
1.8       jonathan  137:        return (rootdev);
1.5       jonathan  138: }
                    139:
1.8       jonathan  140:
1.5       jonathan  141: /*
1.8       jonathan  142:  * Check if current root and target are on the same
                    143:  * device (e.g., both on "sd0") or on different devices
                    144:  * e.g., target is "sd0" and root is "le0" (nfs).
                    145:  */
                    146: int
1.16      mrg       147: target_on_current_disk()
1.8       jonathan  148: {
                    149:        int same;
1.16      mrg       150:
1.8       jonathan  151:        same = (strcmp(diskdev, get_rootdev()) == 0);
                    152:        return (same);
                    153: }
                    154:
                    155: /*
                    156:  * must_mount_root  -- check to see if the current root
                    157:  * partition  and the target root partition are on the same
                    158:  * device.  If they are, we need to have the root mounted read/write
                    159:  * in order to find out whether they're the same partition.
                    160:  * (this is arguably a bug in the kernel API.)
                    161:  *
                    162:  * check to see if they're
                    163:  */
1.16      mrg       164: int
                    165: must_mount_root()
1.8       jonathan  166: {
                    167:        int result;
                    168:
                    169: #if defined(DEBUG)  || defined(DEBUG_ROOT)
1.16      mrg       170:        endwin();
                    171:        printf("must_mount_root\n");
                    172:        backtowin();
1.8       jonathan  173: #endif
                    174:
                    175:        /* if they're  on different devices, we're OK. */
                    176:        if (target_on_current_disk() == 0) {
                    177: #if defined(DEBUG)  || defined(DEBUG_ROOT)
                    178:                endwin();
                    179:                printf("must_mount_root: %s and %s, no?\n",
1.16      mrg       180:                    diskdev, get_rootdev());
1.8       jonathan  181:                fflush(stdout);
                    182:                backtowin();
                    183: #endif
                    184:                return (0);
                    185:        }
                    186:
                    187:        /* If they're on the same device, and root not mounted, yell. */
                    188:        result = (strcmp(mounted_rootpart(), "root_device") == 0);
                    189:
                    190: #if defined(DEBUG)  || defined(DEBUG_ROOT)
                    191:                endwin();
                    192:                printf("must_mount_root %s and root_device gives %d\n",
1.16      mrg       193:                    mounted_rootpart(), result);
1.8       jonathan  194:                fflush(stdout);
                    195:                backtowin();
                    196: #endif
                    197:
                    198:        return (result);
                    199: }
                    200:
                    201: /*
                    202:  * Is the root pattion we're running from the same as the root
                    203:  * which the  user has selected to install/upgrade?
                    204:  * Uses global variable "diskdev" to find the selected device for
                    205:  * install/upgrade.
                    206:  * FIXME -- disklabel-editing code assumes that partition 'a' is always root.
1.5       jonathan  207:  */
1.16      mrg       208: int
                    209: target_already_root()
1.5       jonathan  210: {
                    211:        register int result;
1.8       jonathan  212:        char diskdevroot[STRSIZE];
                    213:
                    214:        /* if they're  on different devices, we're OK. */
                    215:        if (target_on_current_disk() == 0)
                    216:                return (0);
                    217:
                    218:        /*
                    219:         * otherwise, install() or upgrade() should already did
                    220:         * have forced the user to explicitly mount the root,
                    221:         * so we can find out via statfs().  Abort if not.
                    222:         */
                    223:
                    224:        /* append 'a' to the partitionless target disk device name. */
                    225:        snprintf(diskdevroot, STRSIZE, "%s%c", diskdev, 'a');
                    226:        result = is_active_rootpart(diskdevroot);
1.16      mrg       227:        return (result);
1.5       jonathan  228: }
                    229:
                    230:
1.8       jonathan  231:
                    232: /*
                    233:  * ask the kernel what the current root is.
                    234:  * If it's "root_device", we should jsut give up now.
                    235:  * (Why won't the kernel tell us? If we booted with "n",
                    236:  * or an explicit bootpath,  the operator told *it* ....)
                    237:  *
                    238:  * Don't cache the answer in case the user suspnnds and remounts.
                    239:  */
1.16      mrg       240: static const char *
                    241: mounted_rootpart()
1.8       jonathan  242: {
                    243:        struct statfs statfsbuf;
                    244:        int result;
                    245:
                    246:        static char statrootstr[STRSIZE];
1.17      perry     247:        memset(&statfsbuf, 0, sizeof(statfsbuf));
1.8       jonathan  248:        result = statfs("/", &statfsbuf);
                    249:        if (result < 0) {
                    250:                fprintf(stderr, "Help! statfs() can't find root: %s\n",
1.16      mrg       251:                    strerror(errno));
1.8       jonathan  252:                fflush(stderr);
1.18      garbled   253:                if (logging)
                    254:                        fprintf(log, "Help! statfs() can't find root: %s\n",
                    255:                            strerror(errno));
1.8       jonathan  256:                exit(errno);
                    257:                return(0);
                    258:        }
                    259: #if defined(DEBUG)
                    260:        endwin();
                    261:        printf("mounted_rootpart: got %s on %s\n",
1.16      mrg       262:            statfsbuf.f_mntonname, statfsbuf.f_mntfromname);
1.8       jonathan  263:        fflush(stdout);
                    264:        backtowin();
                    265: #endif
                    266:
                    267:        /*
                    268:         * Check for unmounted root. We can't tell which partition
                    269:         */
                    270:        strncpy(statrootstr, statfsbuf.f_mntfromname, STRSIZE);
1.16      mrg       271:        return (statrootstr);
1.8       jonathan  272: }
                    273:
                    274: /*
                    275:  * Is this device partition (e.g., "sd0a") mounted as root?
                    276:  * Note difference from target_on_current_disk()!
                    277:  */
                    278: int
1.16      mrg       279: is_active_rootpart(devpart)
                    280:        const char *devpart;
1.5       jonathan  281: {
1.8       jonathan  282:        const char *root = 0;
1.5       jonathan  283:        int result;
1.12      jonathan  284:        static char devdirdevpart[STRSIZE];
1.5       jonathan  285:
1.8       jonathan  286:        /* check to see if the devices match? */
                    287:
                    288:        /* this changes on mounts, so don't cache it. */
                    289:        root = mounted_rootpart();
                    290:
1.12      jonathan  291:        /* prepend /dev. */
                    292:        /* XXX post-1.3, use strstr to strip "/dev" from input. */
                    293:        snprintf(devdirdevpart, STRSIZE, "/dev/%s", devpart);
                    294:
                    295:        result = (strcmp(devdirdevpart, root) == 0);
                    296:
1.8       jonathan  297: #if defined(DEBUG) || defined(DEBUG_ROOT)
                    298:        endwin();
1.12      jonathan  299:        printf("is_active_rootpart: activeroot = %s, query=%s, mung=%s, answer=%d\n",
1.16      mrg       300:            root, devpart, devdirdevpart, result);
1.8       jonathan  301:        fflush(stdout);
                    302:        backtowin();
1.5       jonathan  303: #endif
1.8       jonathan  304:
1.16      mrg       305:        return (result);
1.5       jonathan  306: }
1.8       jonathan  307:
1.1       jonathan  308: /*
                    309:  * Pathname  prefixing glue to support installation either
                    310:  * from in-ramdisk miniroots or on-disk diskimages.
                    311:  * If our root is on the target disk, the install target is mounted
                    312:  * on /mnt and we need to prefix installed pathnames with /mnt.
                    313:  * otherwise we are installing to the currently-active root and
                    314:  * no prefix is needed.
                    315:  */
1.16      mrg       316: const char *
                    317: target_prefix()
1.1       jonathan  318: {
                    319:        /*
                    320:         * XXX fetch sysctl variable for current root, and compare
1.16      mrg       321:         * to the devicename of the install target disk.
1.1       jonathan  322:         */
1.5       jonathan  323:        return(target_already_root() ? "" : "/mnt");
1.1       jonathan  324: }
                    325:
1.4       jonathan  326: /*
                    327:  * concatenate two pathnames.
                    328:  * XXX returns either input args or result in a static buffer.
                    329:  * The caller must copy if it wants to use the pathname past the
                    330:  * next call to a target-prefixing  function, or to modify the inputs..
                    331:  * Used only  internally so this is probably safe.
                    332:  */
1.16      mrg       333: static const char*
                    334: concat_paths(prefix, suffix)
                    335:        const char* prefix;
                    336:        const char *suffix;
1.4       jonathan  337: {
                    338:        static char realpath[STRSIZE];
                    339:
                    340:        /* absolute prefix and null suffix? */
                    341:        if (prefix[0] == '/' && suffix[0] == 0)
                    342:                return prefix;
                    343:
                    344:        /* null prefix and absolute suffix? */
                    345:        if (prefix[0] == 0 && suffix[0] == '/')
                    346:                return suffix;
                    347:
                    348:        /* avoid "//" */
                    349:        if (suffix[0] == '/' || suffix[0] == 0)
                    350:                snprintf(realpath, STRSIZE, "%s%s", prefix, suffix);
                    351:        else
                    352:                snprintf(realpath, STRSIZE, "%s/%s", prefix, suffix);
1.16      mrg       353:        return (realpath);
1.4       jonathan  354: }
                    355:
                    356: /*
                    357:  * Do target prefix expansion on a pathname.
                    358:  * XXX uses concat_paths and so returns result in a static buffer.
                    359:  * The caller must copy if it wants to use the pathname past the
                    360:  * next call to a target-prefixing  function, or to modify the inputs..
                    361:  * Used only  internally so this is probably safe.
1.6       phil      362:  *
                    363:  * Not static so other functions can generate target related file names.
1.4       jonathan  364:  */
1.16      mrg       365: const char *
                    366: target_expand(tgtpath)
                    367:        const char *tgtpath;
1.4       jonathan  368: {
1.16      mrg       369:
1.4       jonathan  370:        return concat_paths(target_prefix(), tgtpath);
                    371: }
                    372:
1.1       jonathan  373: /* Make a directory, with a prefix like "/mnt" or possibly just "". */
                    374: static void
1.16      mrg       375: make_prefixed_dir(prefix, path)
                    376:        const char *prefix;
                    377:        const char *path;
1.1       jonathan  378: {
1.16      mrg       379:
1.20      bouyer    380:        run_prog(0, 0, NULL, "/bin/mkdir -p %s", concat_paths(prefix, path));
1.1       jonathan  381: }
                    382:
                    383: /* Make a directory with a pathname relative to the insatllation target. */
                    384: void
1.16      mrg       385: make_target_dir(path)
                    386:        const char *path;
1.1       jonathan  387: {
1.16      mrg       388:
1.1       jonathan  389:        make_prefixed_dir(target_prefix(), path);
                    390: }
                    391:
1.16      mrg       392: /* Make a directory with a pathname in the currently-mounted root. */
1.1       jonathan  393: void
1.16      mrg       394: make_ramdisk_dir(path)
                    395:        const char *path;
1.1       jonathan  396: {
1.16      mrg       397:
1.1       jonathan  398:        make_prefixed_dir(path, "");
                    399: }
                    400:
1.19      garbled   401: #if 0
                    402: /* unused, will not work with new run.c */
1.1       jonathan  403: /*
                    404:  *
                    405:  * Append |string| to the  filename |path|, where |path| is
                    406:  * relative to the root of the install target.
                    407:  * for example,
                    408:  *    echo_to_target_file( "Newbie.NetBSD.ORG", "/etc/myname");
                    409:  * would set the default hostname at the next reboot of the installed-on disk.
                    410:  */
                    411: void
1.16      mrg       412: append_to_target_file(path, string)
                    413:        const char *path;
                    414:        const char *string;
1.1       jonathan  415: {
1.16      mrg       416:
1.20      bouyer    417:        run_prog(1, 0, NULL, "echo %s >> %s", string, target_expand(path));
1.1       jonathan  418: }
                    419:
                    420: /*
                    421:  * As append_to_target_file, but with ftrunc semantics.
                    422:  */
                    423: void
1.16      mrg       424: echo_to_target_file(path, string)
                    425:        const char *path;
                    426:        const char *string;
1.1       jonathan  427: {
                    428:        trunc_target_file(path);
                    429:        append_to_target_file(path, string);
                    430: }
                    431:
                    432: void
                    433: sprintf_to_target_file(const char *path, const char *format, ...)
                    434: {
                    435:        char lines[STRSIZE];
                    436:        va_list ap;
                    437:
                    438:        trunc_target_file(path);
                    439:
1.10      phil      440:        va_start(ap, format);
1.1       jonathan  441:        vsnprintf(lines, STRSIZE, format, ap);
                    442:        va_end(ap);
                    443:
                    444:        append_to_target_file(path, lines);
                    445: }
                    446:
                    447:
                    448: void
1.16      mrg       449: trunc_target_file(path)
                    450:        const char *path;
1.1       jonathan  451: {
1.16      mrg       452:
1.20      bouyer    453:        run_prog(1, 0, NULL, "cat < /dev/null > %s",  target_expand(path));
1.1       jonathan  454: }
1.19      garbled   455: #endif /* if 0 */
1.1       jonathan  456:
1.16      mrg       457: static int
                    458: do_target_chdir(dir, must_succeed)
                    459:        const char *dir;
                    460:        int must_succeed;
1.1       jonathan  461: {
1.4       jonathan  462:        const char *tgt_dir;
1.9       phil      463:        int error;
1.1       jonathan  464:
1.9       phil      465:        error = 0;
1.4       jonathan  466:        tgt_dir = target_expand(dir);
1.1       jonathan  467:
                    468: #ifndef DEBUG
1.7       jonathan  469:        /* chdir returns -1 on error and sets errno. */
1.16      mrg       470:        if (chdir(tgt_dir) < 0)
1.7       jonathan  471:                error = errno;
1.18      garbled   472:        if (logging) {
                    473:                fprintf(log, "cd to %s\n", tgt_dir);
                    474:                fflush(log);
                    475:        }
                    476:        if (scripting) {
                    477:                fprintf(script, "cd %s\n", tgt_dir);
                    478:                fflush(script);
                    479:        }
1.16      mrg       480:
1.1       jonathan  481:        if (error && must_succeed) {
1.7       jonathan  482:                fprintf(stderr, msg_string(MSG_realdir),
                    483:                       target_prefix(), strerror(error));
1.18      garbled   484:                if (logging)
                    485:                        fprintf(log, msg_string(MSG_realdir),
                    486:                               target_prefix(), strerror(error));
1.1       jonathan  487:                exit(1);
                    488:        }
                    489:        return (error);
                    490: #else
                    491:        printf("target_chdir (%s)\n", tgt_dir);
                    492:        return (0);
                    493: #endif
                    494: }
                    495:
1.16      mrg       496: void
                    497: target_chdir_or_die(dir)
                    498:        const char *dir;
1.1       jonathan  499: {
1.16      mrg       500:
1.1       jonathan  501:        (void) do_target_chdir(dir, 1);
                    502: }
                    503:
1.16      mrg       504: int
                    505: target_chdir(dir)
                    506:        const char *dir;
1.1       jonathan  507: {
1.16      mrg       508:
1.1       jonathan  509:        return(do_target_chdir(dir, 0));
1.3       jonathan  510: }
                    511:
                    512: /*
1.15      jonathan  513:  * Copy a file from the current root into the target system,
                    514:  * where the  destination pathname is relative to the target root.
                    515:  * Does not check for copy-to-self when target is  current root.
                    516:  */
1.20      bouyer    517: int
1.16      mrg       518: cp_to_target(srcpath, tgt_path)
                    519:        const char *srcpath;
                    520:        const char *tgt_path;
1.15      jonathan  521: {
                    522:        const char *realpath = target_expand(tgt_path);
1.16      mrg       523:
1.20      bouyer    524:        return run_prog(0, 0, NULL, "/bin/cp %s %s", srcpath, realpath);
1.15      jonathan  525: }
                    526:
                    527: /*
1.3       jonathan  528:  * Duplicate a file from the current root to the same pathname
1.15      jonathan  529:  * in the target system.  Pathname must be an absolute pathname.
1.3       jonathan  530:  * If we're running in the target, do nothing.
                    531:  */
1.16      mrg       532: void
                    533: dup_file_into_target(filename)
                    534:        const char *filename;
1.3       jonathan  535: {
1.16      mrg       536:
                    537:        if (!target_already_root())
1.15      jonathan  538:                cp_to_target(filename, filename);
1.3       jonathan  539: }
                    540:
                    541:
1.16      mrg       542: /*
                    543:  * Do a mv where both pathnames are  within the target filesystem.
                    544:  */
1.22.10.1! hubertf   545: void
        !           546: mv_within_target_or_die(frompath, topath)
1.16      mrg       547:        const char *frompath;
                    548:        const char *topath;
1.4       jonathan  549: {
                    550:        char realfrom[STRSIZE];
                    551:        char realto[STRSIZE];
                    552:
                    553:        strncpy(realfrom, target_expand(frompath), STRSIZE);
                    554:        strncpy(realto, target_expand(topath), STRSIZE);
                    555:
1.20      bouyer    556:        run_prog(1, 0, NULL, "mv %s %s", realfrom, realto);
1.4       jonathan  557: }
                    558:
1.7       jonathan  559: /* Do a cp where both pathnames are  within the target filesystem. */
1.16      mrg       560: int cp_within_target(frompath, topath)
                    561:        const char *frompath;
                    562:        const char *topath;
1.7       jonathan  563: {
                    564:        char realfrom[STRSIZE];
                    565:        char realto[STRSIZE];
                    566:
                    567:        strncpy(realfrom, target_expand(frompath), STRSIZE);
                    568:        strncpy(realto, target_expand(topath), STRSIZE);
                    569:
1.20      bouyer    570:        return (run_prog(0, 0, NULL, "cp -p %s %s", realfrom, realto));
1.7       jonathan  571: }
                    572:
1.4       jonathan  573: /* fopen a pathname in the target. */
1.16      mrg       574: FILE *
                    575: target_fopen(filename, type)
                    576:        const char *filename;
                    577:        const char *type;
1.4       jonathan  578: {
1.16      mrg       579:
1.4       jonathan  580:        return fopen(target_expand(filename), type);
                    581: }
                    582:
                    583: /*
1.13      jonathan  584:  * Do a mount and record the mountpoint in a list of mounts to
                    585:  * unwind after completing or aborting a mount.
                    586:  */
                    587: int
1.16      mrg       588: mount_with_unwind(fstype, from, on)
                    589:        const char *fstype;
                    590:        const char *from;
                    591:        const char *on;
1.13      jonathan  592: {
                    593:        int error;
                    594:        struct unwind_mount * m;
                    595:
                    596:        m = malloc(sizeof(*m));
                    597:        if (m == 0)
                    598:                return (ENOMEM);        /* XXX */
                    599:
                    600:        strncpy(m->um_mountpoint, on, STRSIZE);
                    601:        m->um_prev = unwind_mountlist;
                    602:         unwind_mountlist = m;
                    603:
                    604: #ifdef DEBUG_UNWIND
                    605:        endwin();
                    606:        fprintf(stderr, "mounting %s with unwind\n", on);
                    607:        backtowin();
                    608: #endif
                    609:
1.20      bouyer    610:        error = run_prog(0, 0, NULL, "/sbin/mount %s %s %s", fstype, from, on);
1.13      jonathan  611:        return (error);
                    612: }
                    613:
                    614: /*
                    615:  * unwind the mount stack, umounting mounted filesystems.
                    616:  * For now, ignore any errors in unmount.
                    617:  * (Why would we be unable to unmount?  The user has suspended
                    618:  *  us and forked shell sitting somewhere in the target root?)
                    619:  */
                    620: void
                    621: unwind_mounts()
                    622: {
                    623:        struct unwind_mount *m, *prev;
1.14      jonathan  624:        volatile static int unwind_in_progress = 0;
                    625:
                    626:        /* signal safety */
                    627:        if (unwind_in_progress)
                    628:                return;
                    629:        unwind_in_progress = 1;
1.13      jonathan  630:
                    631:        prev = NULL;
                    632:        for (m = unwind_mountlist; m;  ) {
                    633:                struct unwind_mount *prev;
                    634: #ifdef DEBUG_UNWIND
                    635:                endwin();
                    636:                fprintf(stderr, "unmounting %s\n", m->um_mountpoint);
                    637:                backtowin();
                    638: #endif
1.20      bouyer    639:                run_prog(0, 0, NULL, "/sbin/umount %s", m->um_mountpoint);
1.13      jonathan  640:                prev = m->um_prev;
                    641:                free(m);
                    642:                m = prev;
                    643:        }
                    644:        unwind_mountlist = NULL;
1.14      jonathan  645:        unwind_in_progress = 0;
1.13      jonathan  646: }
                    647:
                    648: /*
1.4       jonathan  649:  * Do a mount onto a moutpoint in the install target.
                    650:  * NB: does not prefix mount-from, which probably breaks  nullfs mounts.
                    651:  */
1.16      mrg       652: int
                    653: target_mount(fstype, from, on)
                    654:        const char *fstype;
                    655:        const char *from;
                    656:        const char *on;
1.4       jonathan  657: {
                    658:        int error;
                    659:        const char *realmount = target_expand(on);
                    660:
1.13      jonathan  661:        /* mount and record for unmonting when done.  */
                    662:        error = mount_with_unwind(fstype, from, realmount);
                    663:
1.4       jonathan  664:        return (error);
                    665: }
                    666:
1.16      mrg       667: int
                    668: target_collect_file(kind, buffer, name)
                    669:        int kind;
                    670:        char **buffer;
                    671:        char *name;
1.3       jonathan  672: {
1.16      mrg       673:        const char *realname =target_expand(name);
1.5       jonathan  674:
                    675: #ifdef DEBUG
                    676:        printf("collect real name %s\n", realname);
                    677: #endif
                    678:        return collect(kind, buffer, realname);
1.7       jonathan  679: }
                    680:
                    681: /*
                    682:  * Verify a pathname already exists in the target root filesystem,
                    683:  * by running  test "testflag" on the expanded target pathname.
                    684:  */
1.16      mrg       685: int
                    686: target_test(test, path)
                    687:        const char *test;
                    688:        const char *path;
1.7       jonathan  689: {
                    690:        const char *realpath = target_expand(path);
                    691:        register int result;
                    692:
1.20      bouyer    693:        result = run_prog(0, 0, NULL, "test %s %s", test, realpath);
1.18      garbled   694:        if (scripting)
                    695:                (void)fprintf(script, "if [ $? != 0 ]; then echo \"%s does not exist!\"; fi\n", realpath);
1.7       jonathan  696:
                    697: #if defined(DEBUG)
1.16      mrg       698:        printf("target_test(%s %s) returning %d\n", test, realpath, result);
1.7       jonathan  699: #endif
1.16      mrg       700:        return (result);
1.7       jonathan  701: }
                    702:
                    703: /*
                    704:  * Verify a directory already exists in the target root
                    705:  * filesystem. Do not create the directory if it doesn't  exist.
                    706:  * Assumes that sysinst has already mounted the target root.
                    707:  */
1.16      mrg       708: int
                    709: target_test_dir(path)
                    710:        const char *path;
1.7       jonathan  711: {
1.16      mrg       712:
1.7       jonathan  713:        return target_test("-d", path);
                    714: }
                    715:
                    716: /*
                    717:  * Verify an ordinary file already exists in the target root
                    718:  * filesystem. Do not create the directory if it doesn't  exist.
                    719:  * Assumes that sysinst has already mounted the target root.
                    720:  */
1.16      mrg       721: int
                    722: target_test_file(path)
                    723:        const char *path;
1.7       jonathan  724: {
1.16      mrg       725:
1.7       jonathan  726:        return target_test("-f", path);
1.1       jonathan  727: }
1.14      jonathan  728:
1.22.10.1! hubertf   729: int
        !           730: target_test_symlink(path)
        !           731:        const char *path;
        !           732: {
        !           733:
        !           734:        return target_test("-h", path);
        !           735: }
        !           736:
1.16      mrg       737: int target_file_exists_p(path)
                    738:        const char *path;
1.14      jonathan  739: {
1.16      mrg       740:
1.14      jonathan  741:        return (target_test_file(path) == 0);
                    742: }
                    743:
1.16      mrg       744: int target_dir_exists_p(path)
                    745:        const char *path;
1.14      jonathan  746: {
1.16      mrg       747:
1.14      jonathan  748:        return (target_test_dir(path) == 0);
1.22.10.1! hubertf   749: }
        !           750:
        !           751: int target_symlink_exists_p(path)
        !           752:        const char *path;
        !           753: {
        !           754:
        !           755:        return (target_test_symlink(path) == 0);
1.14      jonathan  756: }

CVSweb <webmaster@jp.NetBSD.org>