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