1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright (c) 1998,2001 by Sun Microsystems, Inc. 24*0Sstevel@tonic-gate * All rights reserved. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include "dump.h" 30*0Sstevel@tonic-gate #include <ftw.h> 31*0Sstevel@tonic-gate #include <ulimit.h> 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate static int partial; 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #ifdef __STDC__ 36*0Sstevel@tonic-gate static dev_t devfromopts(struct mntent *); 37*0Sstevel@tonic-gate static int lf_mark_root(dev_t, char *); 38*0Sstevel@tonic-gate static int lf_ftw_mark(const char *, const struct stat64 *, int); 39*0Sstevel@tonic-gate static void markino(ino_t); 40*0Sstevel@tonic-gate #else 41*0Sstevel@tonic-gate static dev_t devfromopts(); 42*0Sstevel@tonic-gate static int lf_mark_root(); 43*0Sstevel@tonic-gate static int lf_ftw_mark(); 44*0Sstevel@tonic-gate static void markino(); 45*0Sstevel@tonic-gate #endif 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate void 48*0Sstevel@tonic-gate #ifdef __STDC__ 49*0Sstevel@tonic-gate partial_check(void) 50*0Sstevel@tonic-gate #else 51*0Sstevel@tonic-gate partial_check() 52*0Sstevel@tonic-gate #endif 53*0Sstevel@tonic-gate { 54*0Sstevel@tonic-gate struct mntent *mnt; 55*0Sstevel@tonic-gate struct stat64 st; 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate if (stat64(disk, &st) < 0 || 58*0Sstevel@tonic-gate (st.st_mode & S_IFMT) == S_IFCHR || 59*0Sstevel@tonic-gate (st.st_mode & S_IFMT) == S_IFBLK) 60*0Sstevel@tonic-gate return; 61*0Sstevel@tonic-gate 62*0Sstevel@tonic-gate partial_dev = st.st_dev; 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate setmnttab(); 65*0Sstevel@tonic-gate while (mnt = getmnttab()) { 66*0Sstevel@tonic-gate st.st_dev = devfromopts(mnt); 67*0Sstevel@tonic-gate if (st.st_dev == NODEV && 68*0Sstevel@tonic-gate stat64(mnt->mnt_dir, &st) < 0) 69*0Sstevel@tonic-gate continue; 70*0Sstevel@tonic-gate if (partial_dev == st.st_dev) { 71*0Sstevel@tonic-gate if (disk_dynamic) { 72*0Sstevel@tonic-gate /* LINTED: disk is not NULL */ 73*0Sstevel@tonic-gate free(disk); 74*0Sstevel@tonic-gate } 75*0Sstevel@tonic-gate disk = rawname(mnt->mnt_fsname); 76*0Sstevel@tonic-gate disk_dynamic = (disk != mnt->mnt_fsname); 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate partial = 1; 79*0Sstevel@tonic-gate incno = '0'; 80*0Sstevel@tonic-gate uflag = 0; 81*0Sstevel@tonic-gate return; 82*0Sstevel@tonic-gate } 83*0Sstevel@tonic-gate } 84*0Sstevel@tonic-gate msg(gettext("`%s' is not on a locally mounted filesystem\n"), disk); 85*0Sstevel@tonic-gate dumpabort(); 86*0Sstevel@tonic-gate /*NOTREACHED*/ 87*0Sstevel@tonic-gate } 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate /* 90*0Sstevel@tonic-gate * The device id for the mount should be available in 91*0Sstevel@tonic-gate * the mount option string as "dev=%04x". If it's there 92*0Sstevel@tonic-gate * extract the device id and avoid having to stat. 93*0Sstevel@tonic-gate */ 94*0Sstevel@tonic-gate static dev_t 95*0Sstevel@tonic-gate devfromopts(mnt) 96*0Sstevel@tonic-gate struct mntent *mnt; 97*0Sstevel@tonic-gate { 98*0Sstevel@tonic-gate char *str; 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate str = hasmntopt(mnt, MNTINFO_DEV); 101*0Sstevel@tonic-gate if (str != NULL && (str = strchr(str, '='))) 102*0Sstevel@tonic-gate return ((dev_t)strtol(str + 1, (char **)NULL, 16)); 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate return (NODEV); 105*0Sstevel@tonic-gate } 106*0Sstevel@tonic-gate 107*0Sstevel@tonic-gate int 108*0Sstevel@tonic-gate partial_mark(argc, argv) 109*0Sstevel@tonic-gate int argc; 110*0Sstevel@tonic-gate char **argv; 111*0Sstevel@tonic-gate { 112*0Sstevel@tonic-gate char *path; 113*0Sstevel@tonic-gate struct stat64 st; 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate if (partial == 0) 116*0Sstevel@tonic-gate return (1); 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate while (--argc >= 0) { 119*0Sstevel@tonic-gate path = *argv++; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate if (stat64(path, &st) < 0 || 122*0Sstevel@tonic-gate st.st_dev != partial_dev) { 123*0Sstevel@tonic-gate msg(gettext("`%s' is not on dump device `%s'\n"), 124*0Sstevel@tonic-gate path, disk); 125*0Sstevel@tonic-gate dumpabort(); 126*0Sstevel@tonic-gate /*NOTREACHED*/ 127*0Sstevel@tonic-gate } 128*0Sstevel@tonic-gate 129*0Sstevel@tonic-gate if (lf_mark_root(partial_dev, path)) { 130*0Sstevel@tonic-gate msg(gettext( 131*0Sstevel@tonic-gate "Cannot find filesystem mount point for `%s'\n"), 132*0Sstevel@tonic-gate path); 133*0Sstevel@tonic-gate dumpabort(); 134*0Sstevel@tonic-gate /*NOTREACHED*/ 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate /* LINTED this ulimit will always be < INT_MAX */ 138*0Sstevel@tonic-gate if (lf_lftw(path, lf_ftw_mark, (int)ulimit(UL_GDESLIM, 0) / 2) 139*0Sstevel@tonic-gate < 0) { 140*0Sstevel@tonic-gate int saverr = errno; 141*0Sstevel@tonic-gate msg(gettext("Error in %s (%s)\n"), 142*0Sstevel@tonic-gate "ftw", strerror(saverr)); 143*0Sstevel@tonic-gate dumpabort(); 144*0Sstevel@tonic-gate /*NOTREACHED*/ 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate } 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate return (0); 149*0Sstevel@tonic-gate } 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate /* mark directories between target and root */ 152*0Sstevel@tonic-gate static int 153*0Sstevel@tonic-gate lf_mark_root(dev, path) 154*0Sstevel@tonic-gate dev_t dev; 155*0Sstevel@tonic-gate char *path; 156*0Sstevel@tonic-gate { 157*0Sstevel@tonic-gate struct stat64 st; 158*0Sstevel@tonic-gate char dotdot[MAXPATHLEN + 16]; 159*0Sstevel@tonic-gate char *slash; 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate if (strlen(path) > sizeof (dotdot)) 162*0Sstevel@tonic-gate return (1); 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate (void) strcpy(dotdot, path); 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate if (stat64(dotdot, &st) < 0) 167*0Sstevel@tonic-gate return (1); 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate /* if target is a regular file, find directory */ 170*0Sstevel@tonic-gate if ((st.st_mode & S_IFMT) != S_IFDIR) 171*0Sstevel@tonic-gate if (slash = strrchr(dotdot, '/')) 172*0Sstevel@tonic-gate /* "/file" -> "/" */ 173*0Sstevel@tonic-gate if (slash == dotdot) 174*0Sstevel@tonic-gate slash[1] = 0; 175*0Sstevel@tonic-gate /* "dir/file" -> "dir" */ 176*0Sstevel@tonic-gate else 177*0Sstevel@tonic-gate slash[0] = 0; 178*0Sstevel@tonic-gate else 179*0Sstevel@tonic-gate /* "file" -> "." */ 180*0Sstevel@tonic-gate (void) strcpy(dotdot, "."); 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate /* keep marking parent until we hit mount point */ 183*0Sstevel@tonic-gate do { 184*0Sstevel@tonic-gate if (stat64(dotdot, &st) < 0 || 185*0Sstevel@tonic-gate (st.st_mode & S_IFMT) != S_IFDIR || 186*0Sstevel@tonic-gate st.st_dev != dev) 187*0Sstevel@tonic-gate return (1); 188*0Sstevel@tonic-gate markino(st.st_ino); 189*0Sstevel@tonic-gate if (strlen(dotdot) > (sizeof (dotdot) - 4)) 190*0Sstevel@tonic-gate return (1); 191*0Sstevel@tonic-gate (void) strcat(dotdot, "/.."); 192*0Sstevel@tonic-gate } while (st.st_ino != 2); 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate return (0); 195*0Sstevel@tonic-gate } 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate /*ARGSUSED*/ 198*0Sstevel@tonic-gate static int 199*0Sstevel@tonic-gate lf_ftw_mark(name, st, flag) 200*0Sstevel@tonic-gate #ifdef __STDC__ 201*0Sstevel@tonic-gate const char *name; 202*0Sstevel@tonic-gate const struct stat64 *st; 203*0Sstevel@tonic-gate #else 204*0Sstevel@tonic-gate char *name; 205*0Sstevel@tonic-gate struct stat64 *st; 206*0Sstevel@tonic-gate #endif 207*0Sstevel@tonic-gate int flag; 208*0Sstevel@tonic-gate { 209*0Sstevel@tonic-gate if (flag != FTW_NS) { 210*0Sstevel@tonic-gate /* LINTED ufs only uses the lower 32 bits */ 211*0Sstevel@tonic-gate markino((ino_t)st->st_ino); 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate return (0); 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate static void 217*0Sstevel@tonic-gate markino(i) 218*0Sstevel@tonic-gate ino_t i; 219*0Sstevel@tonic-gate { 220*0Sstevel@tonic-gate struct dinode *dp; 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate dp = getino(ino = i); 223*0Sstevel@tonic-gate mark(dp); 224*0Sstevel@tonic-gate } 225