/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1998,2001 by Sun Microsystems, Inc. * All rights reserved. */ #include "dump.h" #include #include dev_t partial_dev; static int partial; static dev_t devfromopts(struct mntent *); static int lf_mark_root(dev_t, char *); static int lf_ftw_mark(const char *, const struct stat64 *, int); static void markino(ino_t); void partial_check(void) { struct mntent *mnt; struct stat64 st; if (stat64(disk, &st) < 0 || (st.st_mode & S_IFMT) == S_IFCHR || (st.st_mode & S_IFMT) == S_IFBLK) return; partial_dev = st.st_dev; setmnttab(); while (mnt = getmnttab()) { st.st_dev = devfromopts(mnt); if (st.st_dev == NODEV && stat64(mnt->mnt_dir, &st) < 0) continue; if (partial_dev == st.st_dev) { if (disk_dynamic) { /* LINTED: disk is not NULL */ free(disk); } disk = rawname(mnt->mnt_fsname); disk_dynamic = (disk != mnt->mnt_fsname); partial = 1; incno = '0'; uflag = 0; return; } } msg(gettext("`%s' is not on a locally mounted filesystem\n"), disk); dumpabort(); /*NOTREACHED*/ } /* * The device id for the mount should be available in * the mount option string as "dev=%04x". If it's there * extract the device id and avoid having to stat. */ static dev_t devfromopts(struct mntent *mnt) { char *str; str = hasmntopt(mnt, MNTINFO_DEV); if (str != NULL && (str = strchr(str, '='))) return ((dev_t)strtol(str + 1, (char **)NULL, 16)); return (NODEV); } int partial_mark(int argc, char **argv) { char *path; struct stat64 st; if (partial == 0) return (1); while (--argc >= 0) { path = *argv++; if (stat64(path, &st) < 0 || st.st_dev != partial_dev) { msg(gettext("`%s' is not on dump device `%s'\n"), path, disk); dumpabort(); /*NOTREACHED*/ } if (lf_mark_root(partial_dev, path)) { msg(gettext( "Cannot find filesystem mount point for `%s'\n"), path); dumpabort(); /*NOTREACHED*/ } /* LINTED this ulimit will always be < INT_MAX */ if (lf_lftw(path, lf_ftw_mark, (int)ulimit(UL_GDESLIM, 0) / 2) < 0) { int saverr = errno; msg(gettext("Error in %s (%s)\n"), "ftw", strerror(saverr)); dumpabort(); /*NOTREACHED*/ } } return (0); } /* mark directories between target and root */ static int lf_mark_root(dev_t dev, char *path) { struct stat64 st; char dotdot[MAXPATHLEN + 16]; char *slash; if (strlen(path) > sizeof (dotdot)) return (1); (void) strcpy(dotdot, path); if (stat64(dotdot, &st) < 0) return (1); /* if target is a regular file, find directory */ if ((st.st_mode & S_IFMT) != S_IFDIR) if (slash = strrchr(dotdot, '/')) /* "/file" -> "/" */ if (slash == dotdot) slash[1] = 0; /* "dir/file" -> "dir" */ else slash[0] = 0; else /* "file" -> "." */ (void) strcpy(dotdot, "."); /* keep marking parent until we hit mount point */ do { if (stat64(dotdot, &st) < 0 || (st.st_mode & S_IFMT) != S_IFDIR || st.st_dev != dev) return (1); markino(st.st_ino); if (strlen(dotdot) > (sizeof (dotdot) - 4)) return (1); (void) strcat(dotdot, "/.."); } while (st.st_ino != 2); return (0); } /*ARGSUSED*/ static int lf_ftw_mark(const char *name, const struct stat64 *st, int flag) { if (flag != FTW_NS) { /* LINTED ufs only uses the lower 32 bits */ markino((ino_t)st->st_ino); } return (0); } static void markino(ino_t i) { struct dinode *dp; dp = getino(ino = i); mark(dp); }