1*d24f36faSmartin /* $NetBSD: target.c,v 1.18 2022/02/10 16:11:41 martin Exp $ */
250dbef1aSdholland
350dbef1aSdholland /*
450dbef1aSdholland * Copyright 1997 Jonathan Stone
550dbef1aSdholland * All rights reserved.
650dbef1aSdholland *
750dbef1aSdholland * Redistribution and use in source and binary forms, with or without
850dbef1aSdholland * modification, are permitted provided that the following conditions
950dbef1aSdholland * are met:
1050dbef1aSdholland * 1. Redistributions of source code must retain the above copyright
1150dbef1aSdholland * notice, this list of conditions and the following disclaimer.
1250dbef1aSdholland * 2. Redistributions in binary form must reproduce the above copyright
1350dbef1aSdholland * notice, this list of conditions and the following disclaimer in the
1450dbef1aSdholland * documentation and/or other materials provided with the distribution.
1550dbef1aSdholland * 3. All advertising materials mentioning features or use of this software
1650dbef1aSdholland * must display the following acknowledgement:
1750dbef1aSdholland * This product includes software developed for the NetBSD Project by
1850dbef1aSdholland * Jonathan Stone.
1950dbef1aSdholland * 4. The name of Jonathan Stone may not be used to endorse
2050dbef1aSdholland * or promote products derived from this software without specific prior
2150dbef1aSdholland * written permission.
2250dbef1aSdholland *
2350dbef1aSdholland * THIS SOFTWARE IS PROVIDED BY JONATHAN STONE ``AS IS''
2450dbef1aSdholland * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2550dbef1aSdholland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2650dbef1aSdholland * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
2750dbef1aSdholland * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2850dbef1aSdholland * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2950dbef1aSdholland * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3050dbef1aSdholland * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3150dbef1aSdholland * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3250dbef1aSdholland * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3350dbef1aSdholland * THE POSSIBILITY OF SUCH DAMAGE.
3450dbef1aSdholland *
3550dbef1aSdholland */
3650dbef1aSdholland
3750dbef1aSdholland /* Copyright below applies to the realpath() code */
3850dbef1aSdholland
3950dbef1aSdholland /*
4050dbef1aSdholland * Copyright (c) 1989, 1991, 1993, 1995
4150dbef1aSdholland * The Regents of the University of California. All rights reserved.
4250dbef1aSdholland *
4350dbef1aSdholland * This code is derived from software contributed to Berkeley by
4450dbef1aSdholland * Jan-Simon Pendry.
4550dbef1aSdholland *
4650dbef1aSdholland * Redistribution and use in source and binary forms, with or without
4750dbef1aSdholland * modification, are permitted provided that the following conditions
4850dbef1aSdholland * are met:
4950dbef1aSdholland * 1. Redistributions of source code must retain the above copyright
5050dbef1aSdholland * notice, this list of conditions and the following disclaimer.
5150dbef1aSdholland * 2. Redistributions in binary form must reproduce the above copyright
5250dbef1aSdholland * notice, this list of conditions and the following disclaimer in the
5350dbef1aSdholland * documentation and/or other materials provided with the distribution.
5450dbef1aSdholland * 3. Neither the name of the University nor the names of its contributors
5550dbef1aSdholland * may be used to endorse or promote products derived from this software
5650dbef1aSdholland * without specific prior written permission.
5750dbef1aSdholland *
5850dbef1aSdholland * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5950dbef1aSdholland * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6050dbef1aSdholland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6150dbef1aSdholland * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
6250dbef1aSdholland * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6350dbef1aSdholland * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6450dbef1aSdholland * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6550dbef1aSdholland * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6650dbef1aSdholland * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6750dbef1aSdholland * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6850dbef1aSdholland * SUCH DAMAGE.
6950dbef1aSdholland */
7050dbef1aSdholland
7150dbef1aSdholland
7250dbef1aSdholland #include <sys/cdefs.h>
7350dbef1aSdholland #if defined(LIBC_SCCS) && !defined(lint)
74*d24f36faSmartin __RCSID("$NetBSD: target.c,v 1.18 2022/02/10 16:11:41 martin Exp $");
7550dbef1aSdholland #endif
7650dbef1aSdholland
7750dbef1aSdholland /*
7850dbef1aSdholland * target.c -- path-prefixing routines to access the target installation
7950dbef1aSdholland * filesystems. Makes the install tools more independent of whether
8050dbef1aSdholland * we're installing into a separate filesystem hierarchy mounted under
8150dbef1aSdholland * /targetroot, or into the currently active root mounted on /.
8250dbef1aSdholland */
8350dbef1aSdholland
8450dbef1aSdholland #include <sys/param.h> /* XXX vm_param.h always defines TRUE*/
8550dbef1aSdholland #include <sys/types.h>
868bb96d39Smartin #include <sys/ioctl.h>
8750dbef1aSdholland #include <sys/sysctl.h>
8850dbef1aSdholland #include <sys/stat.h> /* stat() */
8950dbef1aSdholland #include <sys/mount.h> /* statfs() */
9050dbef1aSdholland
9150dbef1aSdholland #include <fcntl.h>
9250dbef1aSdholland #include <stdio.h>
9350dbef1aSdholland #include <stdarg.h>
9450dbef1aSdholland #include <unistd.h>
9550dbef1aSdholland #include <curses.h> /* defines TRUE, but checks */
9650dbef1aSdholland #include <errno.h>
978bb96d39Smartin #include <util.h>
9850dbef1aSdholland
9950dbef1aSdholland #include "defs.h"
10050dbef1aSdholland #include "md.h"
10150dbef1aSdholland #include "msg_defs.h"
10250dbef1aSdholland #include "menu_defs.h"
10350dbef1aSdholland
10450dbef1aSdholland /*
10550dbef1aSdholland * local prototypes
10650dbef1aSdholland */
10750dbef1aSdholland
10850dbef1aSdholland static void make_prefixed_dir (const char *prefix, const char *path);
10950dbef1aSdholland static int do_target_chdir (const char *dir, int flag);
11050dbef1aSdholland int target_test(unsigned int mode, const char *path);
11150dbef1aSdholland int target_test_dir (const char *path); /* deprecated */
11250dbef1aSdholland int target_test_file (const char *path); /* deprecated */
11350dbef1aSdholland int target_test_symlink (const char *path); /* deprecated */
11450dbef1aSdholland
11550dbef1aSdholland void unwind_mounts(void);
11650dbef1aSdholland
11750dbef1aSdholland /* Record a mount for later unwinding of target mounts. */
11850dbef1aSdholland struct unwind_mount {
11950dbef1aSdholland struct unwind_mount *um_prev;
12050dbef1aSdholland char um_mountpoint[4]; /* Allocated longer... */
12150dbef1aSdholland };
12250dbef1aSdholland
1238bb96d39Smartin /* Record a wedge for later deletion after all file systems have been unmounted */
1248bb96d39Smartin struct umount_delwedge {
1258bb96d39Smartin struct umount_delwedge *next;
126fade124bSmartin char disk[DISKNAMESIZE], wedge[DISKNAMESIZE];
1278bb96d39Smartin };
1288bb96d39Smartin struct umount_delwedge *post_umount_dwlist = NULL;
1298bb96d39Smartin
13050dbef1aSdholland /* Unwind-mount stack */
13150dbef1aSdholland struct unwind_mount *unwind_mountlist = NULL;
13250dbef1aSdholland
13350dbef1aSdholland /*
13450dbef1aSdholland * Debugging options
13550dbef1aSdholland */
13650dbef1aSdholland /*#define DEBUG_ROOT*/ /* turn on what-is-root? debugging. */
13750dbef1aSdholland /*#define DEBUG_UNWIND*/ /* turn on unwind-target-mount debugging. */
13850dbef1aSdholland
13950dbef1aSdholland /*
14050dbef1aSdholland * debugging helper. curses...
14150dbef1aSdholland */
14250dbef1aSdholland #if defined(DEBUG) || defined(DEBUG_ROOT)
14350dbef1aSdholland void
backtowin(void)14450dbef1aSdholland backtowin(void)
14550dbef1aSdholland {
14650dbef1aSdholland
14750dbef1aSdholland fflush(stdout); /* curses does not leave stdout linebuffered. */
14850dbef1aSdholland getchar(); /* wait for user to press return */
14950dbef1aSdholland wrefresh(stdscr);
15050dbef1aSdholland }
15150dbef1aSdholland #endif
15250dbef1aSdholland
15350dbef1aSdholland
15450dbef1aSdholland /*
15550dbef1aSdholland * Is the root partition we're running from the same as the root
15650dbef1aSdholland * which the user has selected to install/upgrade?
1574b2364d9Smartin * Uses global variable "pm->diskdev" to find the selected device for
15850dbef1aSdholland * install/upgrade.
15950dbef1aSdholland */
16050dbef1aSdholland int
target_already_root(void)16150dbef1aSdholland target_already_root(void)
16250dbef1aSdholland {
1634103857bSmartin char dev[PATH_MAX];
1644103857bSmartin int rootpart = -1;
1654103857bSmartin static struct pm_devs *last_pm;
1664103857bSmartin static int last_res;
1674103857bSmartin part_id ptn;
168bc25142eSmartin struct disk_partitions *parts, *inner;
1694103857bSmartin struct disk_part_info info;
17050dbef1aSdholland
171dd0cd772Smartin if (pm == NULL)
172dd0cd772Smartin return 1;
173dd0cd772Smartin
1744103857bSmartin if (pm == last_pm)
1754103857bSmartin return last_res;
176e0822524Smartin
177b1fa9754Smartin if (pm->cur_system)
178b1fa9754Smartin return 1;
179b1fa9754Smartin
1804103857bSmartin last_pm = pm;
181c2ed2005Smartin last_res = 0;
1824103857bSmartin
1834103857bSmartin parts = pm->parts;
184c2ed2005Smartin if (parts == NULL) {
1854103857bSmartin last_res = 0;
1864103857bSmartin return 0;
1874103857bSmartin }
188c2ed2005Smartin
189c2ed2005Smartin if (pm->no_part) {
190c2ed2005Smartin last_res = is_active_rootpart(pm->diskdev, -1);
191c2ed2005Smartin return last_res;
192c2ed2005Smartin }
193c2ed2005Smartin
194bc25142eSmartin if (pm->parts->pscheme->secondary_partitions != NULL) {
195bc25142eSmartin inner = pm->parts->pscheme->secondary_partitions(parts,
19683478358Smartin pm->ptstart, false);
197bc25142eSmartin if (inner != NULL)
198bc25142eSmartin parts = inner;
199bc25142eSmartin }
2004103857bSmartin
2014103857bSmartin for (ptn = 0; ptn < parts->num_part; ptn++) {
2024103857bSmartin if (!parts->pscheme->get_part_info(parts, ptn, &info))
2034103857bSmartin continue;
2044103857bSmartin if (info.nat_type->generic_ptype != PT_root)
2054103857bSmartin continue;
206c2ed2005Smartin if (!is_root_part_mount(info.last_mounted))
2074103857bSmartin continue;
2084103857bSmartin if (!parts->pscheme->get_part_device(parts, ptn,
209abce8cb3Smartin dev, sizeof dev, &rootpart, plain_name, false, true))
2104103857bSmartin continue;
2114103857bSmartin
2124103857bSmartin last_res = is_active_rootpart(dev, rootpart);
213c2ed2005Smartin break;
214c2ed2005Smartin }
215c2ed2005Smartin
2164103857bSmartin return last_res;
2174103857bSmartin }
2184103857bSmartin
219c2ed2005Smartin /*
220c2ed2005Smartin * Could something with this "last mounted on" information be a potential
221c2ed2005Smartin * root partition?
222c2ed2005Smartin */
223c2ed2005Smartin bool
is_root_part_mount(const char * last_mounted)224c2ed2005Smartin is_root_part_mount(const char *last_mounted)
225c2ed2005Smartin {
2266de47033Smartin if (last_mounted == NULL)
2276de47033Smartin return false;
2286de47033Smartin
229c2ed2005Smartin return strcmp(last_mounted, "/") == 0 ||
230c2ed2005Smartin strcmp(last_mounted, "/targetroot") == 0 ||
231c2ed2005Smartin strcmp(last_mounted, "/altroot") == 0;
23250dbef1aSdholland }
23350dbef1aSdholland
23450dbef1aSdholland /*
23550dbef1aSdholland * Is this device partition (e.g., "sd0a") mounted as root?
23650dbef1aSdholland */
23750dbef1aSdholland int
is_active_rootpart(const char * dev,int ptn)23850dbef1aSdholland is_active_rootpart(const char *dev, int ptn)
23950dbef1aSdholland {
24050dbef1aSdholland int mib[2];
24150dbef1aSdholland char rootdev[SSTRSIZE];
24250dbef1aSdholland int rootptn;
24350dbef1aSdholland size_t varlen;
24450dbef1aSdholland
24550dbef1aSdholland mib[0] = CTL_KERN;
24650dbef1aSdholland mib[1] = KERN_ROOT_DEVICE;
24750dbef1aSdholland varlen = sizeof(rootdev);
24850dbef1aSdholland if (sysctl(mib, 2, rootdev, &varlen, NULL, 0) < 0)
24950dbef1aSdholland return 1;
25050dbef1aSdholland
25150dbef1aSdholland if (strcmp(dev, rootdev) != 0)
25250dbef1aSdholland return 0;
25350dbef1aSdholland
2545864e121Smartin if (ptn < 0)
2555864e121Smartin return 1; /* device only check, or wedge */
2565864e121Smartin
25750dbef1aSdholland mib[1] = KERN_ROOT_PARTITION;
25850dbef1aSdholland varlen = sizeof rootptn;
2595864e121Smartin rootptn = -1;
26050dbef1aSdholland if (sysctl(mib, 2, &rootptn, &varlen, NULL, 0) < 0)
26150dbef1aSdholland return 1;
26250dbef1aSdholland
26350dbef1aSdholland return ptn == rootptn;
26450dbef1aSdholland }
26550dbef1aSdholland
26650dbef1aSdholland /*
26750dbef1aSdholland * Pathname prefixing glue to support installation either
26850dbef1aSdholland * from in-ramdisk miniroots or on-disk diskimages.
26950dbef1aSdholland * If our root is on the target disk, the install target is mounted
27050dbef1aSdholland * on /targetroot and we need to prefix installed pathnames with /targetroot.
27150dbef1aSdholland * otherwise we are installing to the currently-active root and
27250dbef1aSdholland * no prefix is needed.
27350dbef1aSdholland */
27450dbef1aSdholland const char *
target_prefix(void)27550dbef1aSdholland target_prefix(void)
27650dbef1aSdholland {
27750dbef1aSdholland /*
27850dbef1aSdholland * XXX fetch sysctl variable for current root, and compare
27950dbef1aSdholland * to the devicename of the install target disk.
28050dbef1aSdholland */
28150dbef1aSdholland return(target_already_root() ? "" : targetroot_mnt);
28250dbef1aSdholland }
28350dbef1aSdholland
28450dbef1aSdholland /*
28550dbef1aSdholland * concatenate two pathnames.
28650dbef1aSdholland * XXX returns either input args or result in a static buffer.
28750dbef1aSdholland * The caller must copy if it wants to use the pathname past the
2886dccb7a0Srillig * next call to a target-prefixing function, or to modify the inputs.
28950dbef1aSdholland * Used only internally so this is probably safe.
29050dbef1aSdholland */
29150dbef1aSdholland const char *
concat_paths(const char * prefix,const char * suffix)29250dbef1aSdholland concat_paths(const char *prefix, const char *suffix)
29350dbef1aSdholland {
29450dbef1aSdholland static char real_path[MAXPATHLEN];
29550dbef1aSdholland
29650dbef1aSdholland /* absolute prefix and null suffix? */
29750dbef1aSdholland if (prefix[0] == '/' && suffix[0] == 0)
29850dbef1aSdholland return prefix;
29950dbef1aSdholland
30050dbef1aSdholland /* null prefix and absolute suffix? */
30150dbef1aSdholland if (prefix[0] == 0 && suffix[0] == '/')
30250dbef1aSdholland return suffix;
30350dbef1aSdholland
30450dbef1aSdholland /* avoid "//" */
30550dbef1aSdholland if (suffix[0] == '/' || suffix[0] == 0)
30650dbef1aSdholland snprintf(real_path, sizeof(real_path), "%s%s", prefix, suffix);
30750dbef1aSdholland else
30850dbef1aSdholland snprintf(real_path, sizeof(real_path), "%s/%s",
30950dbef1aSdholland prefix, suffix);
31050dbef1aSdholland return (real_path);
31150dbef1aSdholland }
31250dbef1aSdholland
31350dbef1aSdholland /*
31450dbef1aSdholland * Do target prefix expansion on a pathname.
31550dbef1aSdholland * XXX uses concat_paths and so returns result in a static buffer.
31650dbef1aSdholland * The caller must copy if it wants to use the pathname past the
3176dccb7a0Srillig * next call to a target-prefixing function, or to modify the inputs.
31850dbef1aSdholland * Used only internally so this is probably safe.
31950dbef1aSdholland *
32050dbef1aSdholland * Not static so other functions can generate target related file names.
32150dbef1aSdholland */
32250dbef1aSdholland const char *
target_expand(const char * tgtpath)32350dbef1aSdholland target_expand(const char *tgtpath)
32450dbef1aSdholland {
32550dbef1aSdholland
32650dbef1aSdholland return concat_paths(target_prefix(), tgtpath);
32750dbef1aSdholland }
32850dbef1aSdholland
32950dbef1aSdholland /* Make a directory, with a prefix like "/targetroot" or possibly just "". */
33050dbef1aSdholland static void
make_prefixed_dir(const char * prefix,const char * path)33150dbef1aSdholland make_prefixed_dir(const char *prefix, const char *path)
33250dbef1aSdholland {
33350dbef1aSdholland
33450dbef1aSdholland run_program(0, "/bin/mkdir -p %s", concat_paths(prefix, path));
33550dbef1aSdholland }
33650dbef1aSdholland
33750dbef1aSdholland /* Make a directory with a pathname relative to the installation target. */
33850dbef1aSdholland void
make_target_dir(const char * path)33950dbef1aSdholland make_target_dir(const char *path)
34050dbef1aSdholland {
34150dbef1aSdholland
34250dbef1aSdholland make_prefixed_dir(target_prefix(), path);
34350dbef1aSdholland }
34450dbef1aSdholland
34550dbef1aSdholland
34650dbef1aSdholland static int
do_target_chdir(const char * dir,int must_succeed)34750dbef1aSdholland do_target_chdir(const char *dir, int must_succeed)
34850dbef1aSdholland {
34950dbef1aSdholland const char *tgt_dir;
35050dbef1aSdholland int error;
35150dbef1aSdholland
35250dbef1aSdholland error = 0;
35350dbef1aSdholland tgt_dir = target_expand(dir);
35450dbef1aSdholland
3554b2364d9Smartin #ifdef DEBUG
3564b2364d9Smartin printf("target_chdir (%s)\n", tgt_dir);
3574b2364d9Smartin //return (0);
3584b2364d9Smartin #endif
35950dbef1aSdholland /* chdir returns -1 on error and sets errno. */
36050dbef1aSdholland if (chdir(tgt_dir) < 0)
36150dbef1aSdholland error = errno;
36250dbef1aSdholland if (logfp) {
36350dbef1aSdholland fprintf(logfp, "cd to %s\n", tgt_dir);
36450dbef1aSdholland fflush(logfp);
36550dbef1aSdholland }
36650dbef1aSdholland if (script) {
36750dbef1aSdholland scripting_fprintf(NULL, "cd %s\n", tgt_dir);
36850dbef1aSdholland fflush(script);
36950dbef1aSdholland }
37050dbef1aSdholland
37150dbef1aSdholland if (error && must_succeed) {
3724103857bSmartin const char *args[] = { target_prefix(), strerror(error) };
3734103857bSmartin char *err = str_arg_subst(msg_string(MSG_realdir),
3744103857bSmartin __arraycount(args), args);
3754103857bSmartin fprintf(stderr, "%s\n", err);
37650dbef1aSdholland if (logfp)
3774103857bSmartin fprintf(logfp, "%s\n", err);
3784103857bSmartin free(err);
37950dbef1aSdholland exit(1);
38050dbef1aSdholland }
38150dbef1aSdholland errno = error;
38250dbef1aSdholland return (error);
38350dbef1aSdholland }
38450dbef1aSdholland
38550dbef1aSdholland void
target_chdir_or_die(const char * dir)38650dbef1aSdholland target_chdir_or_die(const char *dir)
38750dbef1aSdholland {
38850dbef1aSdholland
38950dbef1aSdholland (void)do_target_chdir(dir, 1);
39050dbef1aSdholland }
39150dbef1aSdholland
39250dbef1aSdholland #ifdef notdef
39350dbef1aSdholland int
target_chdir(const char * dir)39450dbef1aSdholland target_chdir(const char *dir)
39550dbef1aSdholland {
39650dbef1aSdholland
39750dbef1aSdholland return do_target_chdir(dir, 0);
39850dbef1aSdholland }
39950dbef1aSdholland #endif
40050dbef1aSdholland
40150dbef1aSdholland /*
40250dbef1aSdholland * Copy a file from the current root into the target system,
40350dbef1aSdholland * where the destination pathname is relative to the target root.
40450dbef1aSdholland * Does not check for copy-to-self when target is current root.
40550dbef1aSdholland */
40650dbef1aSdholland int
cp_to_target(const char * srcpath,const char * tgt_path)40750dbef1aSdholland cp_to_target(const char *srcpath, const char *tgt_path)
40850dbef1aSdholland {
40950dbef1aSdholland const char *real_path = target_expand(tgt_path);
41050dbef1aSdholland
41150dbef1aSdholland return run_program(0, "/bin/cp %s %s", srcpath, real_path);
41250dbef1aSdholland }
41350dbef1aSdholland
41450dbef1aSdholland /*
41550dbef1aSdholland * Duplicate a file from the current root to the same pathname
41650dbef1aSdholland * in the target system. Pathname must be an absolute pathname.
41750dbef1aSdholland * If we're running in the target, do nothing.
41850dbef1aSdholland */
41950dbef1aSdholland void
dup_file_into_target(const char * filename)42050dbef1aSdholland dup_file_into_target(const char *filename)
42150dbef1aSdholland {
42250dbef1aSdholland
42350dbef1aSdholland if (!target_already_root())
42450dbef1aSdholland cp_to_target(filename, filename);
42550dbef1aSdholland }
42650dbef1aSdholland
42750dbef1aSdholland
42850dbef1aSdholland /*
42950dbef1aSdholland * Do a mv where both pathnames are within the target filesystem.
43050dbef1aSdholland */
43150dbef1aSdholland void
mv_within_target_or_die(const char * frompath,const char * topath)43250dbef1aSdholland mv_within_target_or_die(const char *frompath, const char *topath)
43350dbef1aSdholland {
43450dbef1aSdholland char realfrom[STRSIZE];
43550dbef1aSdholland char realto[STRSIZE];
43650dbef1aSdholland
43750dbef1aSdholland strlcpy(realfrom, target_expand(frompath), sizeof realfrom);
43850dbef1aSdholland strlcpy(realto, target_expand(topath), sizeof realto);
43950dbef1aSdholland
44050dbef1aSdholland run_program(RUN_FATAL, "mv %s %s", realfrom, realto);
44150dbef1aSdholland }
44250dbef1aSdholland
44350dbef1aSdholland /* Do a cp where both pathnames are within the target filesystem. */
44450dbef1aSdholland int
cp_within_target(const char * frompath,const char * topath,int optional)44550dbef1aSdholland cp_within_target(const char *frompath, const char *topath, int optional)
44650dbef1aSdholland {
44750dbef1aSdholland char realfrom[STRSIZE];
44850dbef1aSdholland char realto[STRSIZE];
44950dbef1aSdholland
450f16eda65Smartin strlcpy(realfrom, target_expand(frompath), sizeof realfrom);
451f16eda65Smartin strlcpy(realto, target_expand(topath), sizeof realto);
45250dbef1aSdholland
45350dbef1aSdholland if (access(realfrom, R_OK) == -1 && optional)
45450dbef1aSdholland return 0;
45550dbef1aSdholland return (run_program(0, "cp -p %s %s", realfrom, realto));
45650dbef1aSdholland }
45750dbef1aSdholland
45850dbef1aSdholland /* fopen a pathname in the target. */
45950dbef1aSdholland FILE *
target_fopen(const char * filename,const char * type)46050dbef1aSdholland target_fopen(const char *filename, const char *type)
46150dbef1aSdholland {
46250dbef1aSdholland
46350dbef1aSdholland return fopen(target_expand(filename), type);
46450dbef1aSdholland }
46550dbef1aSdholland
46650dbef1aSdholland /*
46750dbef1aSdholland * Do a mount onto a mountpoint in the install target.
46850dbef1aSdholland * Record mountpoint so we can unmount when finished.
46950dbef1aSdholland * NB: does not prefix mount-from, which probably breaks nullfs mounts.
47050dbef1aSdholland */
47150dbef1aSdholland int
target_mount_do(const char * opts,const char * from,const char * on)4724b2364d9Smartin target_mount_do(const char *opts, const char *from, const char *on)
47350dbef1aSdholland {
47450dbef1aSdholland struct unwind_mount *m;
47550dbef1aSdholland int error;
47650dbef1aSdholland int len;
47750dbef1aSdholland
47850dbef1aSdholland len = strlen(on);
47950dbef1aSdholland m = malloc(sizeof *m + len);
48050dbef1aSdholland if (m == 0)
48150dbef1aSdholland return (ENOMEM); /* XXX */
48250dbef1aSdholland
48350dbef1aSdholland memcpy(m->um_mountpoint, on, len + 1);
48450dbef1aSdholland
48550dbef1aSdholland #ifdef DEBUG_UNWIND
48650dbef1aSdholland endwin();
48750dbef1aSdholland fprintf(stderr, "mounting %s with unwind\n", on);
48850dbef1aSdholland backtowin();
48950dbef1aSdholland #endif
49050dbef1aSdholland
4914b2364d9Smartin error = run_program(0, "/sbin/mount %s %s %s%s",
4924b2364d9Smartin opts, from, target_prefix(), on);
49350dbef1aSdholland if (error) {
49450dbef1aSdholland free(m);
49550dbef1aSdholland return error;
49650dbef1aSdholland }
49750dbef1aSdholland m->um_prev = unwind_mountlist;
49850dbef1aSdholland unwind_mountlist = m;
49950dbef1aSdholland return 0;
50050dbef1aSdholland }
50150dbef1aSdholland
502a7267d53Smartin /*
503a7267d53Smartin * Special case - we have mounted the target / readonly
504a7267d53Smartin * to peek at etc/fstab, and now want it undone.
505a7267d53Smartin */
506a7267d53Smartin void
umount_root(void)507a7267d53Smartin umount_root(void)
508a7267d53Smartin {
509a7267d53Smartin
510a7267d53Smartin /* verify this is the only mount */
511a7267d53Smartin if (unwind_mountlist == NULL)
512a7267d53Smartin return;
513a7267d53Smartin if (unwind_mountlist->um_prev != NULL)
514a7267d53Smartin return;
515a7267d53Smartin
516a7267d53Smartin if (run_program(0, "/sbin/umount %s", target_prefix()) != 0)
517a7267d53Smartin return;
518a7267d53Smartin
519a7267d53Smartin free(unwind_mountlist);
520a7267d53Smartin unwind_mountlist = NULL;
521a7267d53Smartin }
522a7267d53Smartin
523a7267d53Smartin
5244b2364d9Smartin int
target_mount(const char * opts,const char * from,const char * on)5254103857bSmartin target_mount(const char *opts, const char *from, const char *on)
5264b2364d9Smartin {
5274103857bSmartin return target_mount_do(opts, from, on);
5284b2364d9Smartin }
5294b2364d9Smartin
530*d24f36faSmartin int
target_unmount(const char * mount_point)531*d24f36faSmartin target_unmount(const char *mount_point)
532*d24f36faSmartin {
533*d24f36faSmartin struct unwind_mount *m, *prev = NULL;
534*d24f36faSmartin int error;
535*d24f36faSmartin
536*d24f36faSmartin for (m = unwind_mountlist; m != NULL; prev = m, m = m->um_prev)
537*d24f36faSmartin if (strcmp(m->um_mountpoint, mount_point) == 0)
538*d24f36faSmartin break;
539*d24f36faSmartin
540*d24f36faSmartin if (m == NULL)
541*d24f36faSmartin return ENOTDIR;
542*d24f36faSmartin
543*d24f36faSmartin error = run_program(0, "/sbin/umount %s%s",
544*d24f36faSmartin target_prefix(), m->um_mountpoint);
545*d24f36faSmartin if (error)
546*d24f36faSmartin return error;
547*d24f36faSmartin
548*d24f36faSmartin if (m == unwind_mountlist)
549*d24f36faSmartin unwind_mountlist = m->um_prev;
550*d24f36faSmartin else
551*d24f36faSmartin prev->um_prev = m->um_prev;
552*d24f36faSmartin free(m);
553*d24f36faSmartin
554*d24f36faSmartin return 0;
555*d24f36faSmartin }
556*d24f36faSmartin
5578bb96d39Smartin static bool
delete_wedge(const char * disk,const char * wedge)5588bb96d39Smartin delete_wedge(const char *disk, const char *wedge)
5598bb96d39Smartin {
5608bb96d39Smartin struct dkwedge_info dkw;
5618bb96d39Smartin char diskpath[MAXPATHLEN];
5628bb96d39Smartin int fd, error;
5638bb96d39Smartin
5648bb96d39Smartin fd = opendisk(disk, O_RDWR, diskpath, sizeof(diskpath), 0);
5658bb96d39Smartin if (fd < 0)
5668bb96d39Smartin return false;
5678bb96d39Smartin memset(&dkw, 0, sizeof(dkw));
5688bb96d39Smartin strlcpy(dkw.dkw_devname, wedge, sizeof(dkw.dkw_devname));
5698bb96d39Smartin error = ioctl(fd, DIOCDWEDGE, &dkw);
5708bb96d39Smartin close(fd);
5718bb96d39Smartin return error == 0;
5728bb96d39Smartin }
5738bb96d39Smartin
5748bb96d39Smartin void
register_post_umount_delwedge(const char * disk,const char * wedge)5758bb96d39Smartin register_post_umount_delwedge(const char *disk, const char *wedge)
5768bb96d39Smartin {
5778bb96d39Smartin struct umount_delwedge *dw;
5788bb96d39Smartin
579fade124bSmartin if (unwind_mountlist == NULL) {
580fade124bSmartin /* we have nothing mounted, can delete it right now */
581fade124bSmartin delete_wedge(disk, wedge);
582fade124bSmartin return;
583fade124bSmartin }
584fade124bSmartin
5858bb96d39Smartin dw = calloc(1, sizeof(*dw));
5868bb96d39Smartin dw->next = post_umount_dwlist;
5878bb96d39Smartin strlcpy(dw->disk, disk, sizeof(dw->disk));
5888bb96d39Smartin strlcpy(dw->wedge, wedge, sizeof(dw->wedge));
5898bb96d39Smartin post_umount_dwlist = dw;
5908bb96d39Smartin }
5918bb96d39Smartin
59250dbef1aSdholland /*
59350dbef1aSdholland * unwind the mount stack, unmounting mounted filesystems.
59450dbef1aSdholland * For now, ignore any errors in unmount.
59550dbef1aSdholland * (Why would we be unable to unmount? The user has suspended
59650dbef1aSdholland * us and forked shell sitting somewhere in the target root?)
59750dbef1aSdholland */
59850dbef1aSdholland void
unwind_mounts(void)59950dbef1aSdholland unwind_mounts(void)
60050dbef1aSdholland {
60150dbef1aSdholland struct unwind_mount *m;
6028bb96d39Smartin struct umount_delwedge *dw;
60350dbef1aSdholland static volatile int unwind_in_progress = 0;
60450dbef1aSdholland
60550dbef1aSdholland /* signal safety */
60650dbef1aSdholland if (unwind_in_progress)
60750dbef1aSdholland return;
60850dbef1aSdholland unwind_in_progress = 1;
60950dbef1aSdholland
61050dbef1aSdholland while ((m = unwind_mountlist) != NULL) {
61150dbef1aSdholland unwind_mountlist = m->um_prev;
61250dbef1aSdholland #ifdef DEBUG_UNWIND
61350dbef1aSdholland endwin();
61450dbef1aSdholland fprintf(stderr, "unmounting %s\n", m->um_mountpoint);
61550dbef1aSdholland backtowin();
61650dbef1aSdholland #endif
61750dbef1aSdholland run_program(0, "/sbin/umount %s%s",
61850dbef1aSdholland target_prefix(), m->um_mountpoint);
61950dbef1aSdholland free(m);
62050dbef1aSdholland }
6218bb96d39Smartin while ((dw = post_umount_dwlist) != NULL) {
6228bb96d39Smartin post_umount_dwlist = dw->next;
6238bb96d39Smartin delete_wedge(dw->disk, dw->wedge);
6248bb96d39Smartin free(dw);
6258bb96d39Smartin }
62650dbef1aSdholland unwind_in_progress = 0;
62750dbef1aSdholland }
62850dbef1aSdholland
62950dbef1aSdholland int
target_collect_file(int kind,char ** buffer,const char * name)63050dbef1aSdholland target_collect_file(int kind, char **buffer, const char *name)
63150dbef1aSdholland {
63250dbef1aSdholland const char *realname = target_expand(name);
63350dbef1aSdholland
63450dbef1aSdholland #ifdef DEBUG
63550dbef1aSdholland printf("collect real name %s\n", realname);
63650dbef1aSdholland #endif
63750dbef1aSdholland return collect(kind, buffer, "%s", realname);
63850dbef1aSdholland }
63950dbef1aSdholland
64050dbef1aSdholland /*
64150dbef1aSdholland * Verify a pathname already exists in the target root filesystem,
64250dbef1aSdholland * by running test "testflag" on the expanded target pathname.
64350dbef1aSdholland */
64450dbef1aSdholland int
target_test(unsigned int mode,const char * path)64550dbef1aSdholland target_test(unsigned int mode, const char *path)
64650dbef1aSdholland {
64750dbef1aSdholland const char *real_path = target_expand(path);
64850dbef1aSdholland register int result;
64950dbef1aSdholland
65050dbef1aSdholland result = !file_mode_match(real_path, mode);
65150dbef1aSdholland scripting_fprintf(NULL, "if [ $? != 0 ]; then echo \"%s does not exist!\"; fi\n", real_path);
65250dbef1aSdholland
65350dbef1aSdholland #if defined(DEBUG)
65450dbef1aSdholland printf("target_test(%o, %s) returning %d\n", mode, real_path, result);
65550dbef1aSdholland #endif
65650dbef1aSdholland return (result);
65750dbef1aSdholland }
65850dbef1aSdholland
65950dbef1aSdholland /*
66050dbef1aSdholland * Verify a directory already exists in the target root
66150dbef1aSdholland * filesystem. Do not create the directory if it doesn't exist.
66250dbef1aSdholland * Assumes that sysinst has already mounted the target root.
66350dbef1aSdholland */
66450dbef1aSdholland int
target_test_dir(const char * path)66550dbef1aSdholland target_test_dir(const char *path)
66650dbef1aSdholland {
66750dbef1aSdholland
66850dbef1aSdholland return target_test(S_IFDIR, path);
66950dbef1aSdholland }
67050dbef1aSdholland
67150dbef1aSdholland /*
67250dbef1aSdholland * Verify an ordinary file already exists in the target root
67350dbef1aSdholland * filesystem. Do not create the directory if it doesn't exist.
67450dbef1aSdholland * Assumes that sysinst has already mounted the target root.
67550dbef1aSdholland */
67650dbef1aSdholland int
target_test_file(const char * path)67750dbef1aSdholland target_test_file(const char *path)
67850dbef1aSdholland {
67950dbef1aSdholland
68050dbef1aSdholland return target_test(S_IFREG, path);
68150dbef1aSdholland }
68250dbef1aSdholland
68350dbef1aSdholland int
target_test_symlink(const char * path)68450dbef1aSdholland target_test_symlink(const char *path)
68550dbef1aSdholland {
68650dbef1aSdholland
68750dbef1aSdholland return target_test(S_IFLNK, path);
68850dbef1aSdholland }
68950dbef1aSdholland
69050dbef1aSdholland int
target_file_exists_p(const char * path)69150dbef1aSdholland target_file_exists_p(const char *path)
69250dbef1aSdholland {
69350dbef1aSdholland
69450dbef1aSdholland return (target_test_file(path) == 0);
69550dbef1aSdholland }
69650dbef1aSdholland
69750dbef1aSdholland int
target_dir_exists_p(const char * path)69850dbef1aSdholland target_dir_exists_p(const char *path)
69950dbef1aSdholland {
70050dbef1aSdholland
70150dbef1aSdholland return (target_test_dir(path) == 0);
70250dbef1aSdholland }
70350dbef1aSdholland
70450dbef1aSdholland int
target_symlink_exists_p(const char * path)70550dbef1aSdholland target_symlink_exists_p(const char *path)
70650dbef1aSdholland {
70750dbef1aSdholland
70850dbef1aSdholland return (target_test_symlink(path) == 0);
70950dbef1aSdholland }
71050dbef1aSdholland
71150dbef1aSdholland int
target_mounted(void)71250dbef1aSdholland target_mounted(void)
71350dbef1aSdholland {
71450dbef1aSdholland return (unwind_mountlist != NULL);
71550dbef1aSdholland }
716