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>