1 7c478bd9Sstevel@tonic-gate /* 2 7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3 7c478bd9Sstevel@tonic-gate * 4 7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5 c40f76e3Sjc144527 * Common Development and Distribution License (the "License"). 6 c40f76e3Sjc144527 * You may not use this file except in compliance with the License. 7 7c478bd9Sstevel@tonic-gate * 8 7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 10 7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 11 7c478bd9Sstevel@tonic-gate * and limitations under the License. 12 7c478bd9Sstevel@tonic-gate * 13 7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 14 7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 16 7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 17 7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 18 7c478bd9Sstevel@tonic-gate * 19 7c478bd9Sstevel@tonic-gate * CDDL HEADER END 20 7c478bd9Sstevel@tonic-gate */ 21 7c478bd9Sstevel@tonic-gate /* 22 c690e840SJohn.Zolnowsky@Sun.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 23 7c478bd9Sstevel@tonic-gate */ 24 7c478bd9Sstevel@tonic-gate 25 7c478bd9Sstevel@tonic-gate #include <signal.h> 26 7c478bd9Sstevel@tonic-gate #include <unistd.h> 27 7c478bd9Sstevel@tonic-gate #include <sys/acl.h> 28 7c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 29 7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 30 7c478bd9Sstevel@tonic-gate #include "bart.h" 31 fa9e4066Sahrens #include <aclutils.h> 32 7c478bd9Sstevel@tonic-gate 33 7c478bd9Sstevel@tonic-gate static int sanitize_reloc_root(char *root, size_t bufsize); 34 7c478bd9Sstevel@tonic-gate static int create_manifest_filelist(char **argv, char *reloc_root); 35 7c478bd9Sstevel@tonic-gate static int create_manifest_rule(char *reloc_root, FILE *rule_fp); 36 7c478bd9Sstevel@tonic-gate static void output_manifest(void); 37 *99389cdeSJan Parcel static int eval_file(const char *fname, const struct stat64 *statb, 38 *99389cdeSJan Parcel struct FTW *ftwx); 39 7c478bd9Sstevel@tonic-gate static char *sanitized_fname(const char *, boolean_t); 40 7c478bd9Sstevel@tonic-gate static char *get_acl_string(const char *fname, const struct stat64 *statb, 41 7c478bd9Sstevel@tonic-gate int *err_code); 42 7c478bd9Sstevel@tonic-gate static int generate_hash(int fdin, char *hash_str); 43 7c478bd9Sstevel@tonic-gate static int read_filelist(char *reloc_root, char **argv, char *buf, 44 7c478bd9Sstevel@tonic-gate size_t bufsize); 45 7c478bd9Sstevel@tonic-gate static int walker(const char *name, const struct stat64 *sp, 46 7c478bd9Sstevel@tonic-gate int type, struct FTW *ftwx); 47 7c478bd9Sstevel@tonic-gate 48 7c478bd9Sstevel@tonic-gate /* 49 7c478bd9Sstevel@tonic-gate * The following globals are necessary due to the "walker" function 50 7c478bd9Sstevel@tonic-gate * provided by nftw(). Since there is no way to pass them through to the 51 7c478bd9Sstevel@tonic-gate * walker function, they must be global. 52 7c478bd9Sstevel@tonic-gate */ 53 7c478bd9Sstevel@tonic-gate static int compute_chksum = 1, eval_err = 0; 54 7c478bd9Sstevel@tonic-gate static struct rule *subtree_root; 55 7c478bd9Sstevel@tonic-gate static char reloc_root[PATH_MAX]; 56 a2721256SWilliam Young static struct statvfs64 parent_vfs; 57 7c478bd9Sstevel@tonic-gate 58 7c478bd9Sstevel@tonic-gate int 59 7c478bd9Sstevel@tonic-gate bart_create(int argc, char **argv) 60 7c478bd9Sstevel@tonic-gate { 61 7c478bd9Sstevel@tonic-gate boolean_t filelist_input; 62 7c478bd9Sstevel@tonic-gate int ret, c, output_pipe[2]; 63 7c478bd9Sstevel@tonic-gate FILE *rules_fd = NULL; 64 7c478bd9Sstevel@tonic-gate pid_t pid; 65 7c478bd9Sstevel@tonic-gate 66 7c478bd9Sstevel@tonic-gate filelist_input = B_FALSE; 67 7c478bd9Sstevel@tonic-gate reloc_root[0] = '\0'; 68 7c478bd9Sstevel@tonic-gate 69 7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "Inr:R:")) != EOF) { 70 7c478bd9Sstevel@tonic-gate switch (c) { 71 7c478bd9Sstevel@tonic-gate case 'I': 72 7c478bd9Sstevel@tonic-gate if (rules_fd != NULL) { 73 7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s", INPUT_ERR); 74 7c478bd9Sstevel@tonic-gate usage(); 75 7c478bd9Sstevel@tonic-gate } 76 7c478bd9Sstevel@tonic-gate filelist_input = B_TRUE; 77 7c478bd9Sstevel@tonic-gate break; 78 7c478bd9Sstevel@tonic-gate 79 7c478bd9Sstevel@tonic-gate case 'n': 80 7c478bd9Sstevel@tonic-gate compute_chksum = 0; 81 7c478bd9Sstevel@tonic-gate break; 82 7c478bd9Sstevel@tonic-gate 83 7c478bd9Sstevel@tonic-gate case 'r': 84 7c478bd9Sstevel@tonic-gate if (strcmp(optarg, "-") == 0) 85 7c478bd9Sstevel@tonic-gate rules_fd = stdin; 86 7c478bd9Sstevel@tonic-gate else 87 7c478bd9Sstevel@tonic-gate rules_fd = fopen(optarg, "r"); 88 7c478bd9Sstevel@tonic-gate if (rules_fd == NULL) { 89 7c478bd9Sstevel@tonic-gate perror(optarg); 90 7c478bd9Sstevel@tonic-gate usage(); 91 7c478bd9Sstevel@tonic-gate } 92 7c478bd9Sstevel@tonic-gate break; 93 7c478bd9Sstevel@tonic-gate 94 7c478bd9Sstevel@tonic-gate case 'R': 95 7c478bd9Sstevel@tonic-gate (void) strlcpy(reloc_root, optarg, sizeof (reloc_root)); 96 7c478bd9Sstevel@tonic-gate ret = sanitize_reloc_root(reloc_root, 97 7c478bd9Sstevel@tonic-gate sizeof (reloc_root)); 98 7c478bd9Sstevel@tonic-gate if (ret == 0) 99 7c478bd9Sstevel@tonic-gate usage(); 100 7c478bd9Sstevel@tonic-gate break; 101 7c478bd9Sstevel@tonic-gate 102 7c478bd9Sstevel@tonic-gate case '?': 103 7c478bd9Sstevel@tonic-gate default : 104 7c478bd9Sstevel@tonic-gate usage(); 105 7c478bd9Sstevel@tonic-gate } 106 7c478bd9Sstevel@tonic-gate } 107 7c478bd9Sstevel@tonic-gate argv += optind; 108 7c478bd9Sstevel@tonic-gate 109 7c478bd9Sstevel@tonic-gate if (pipe(output_pipe) < 0) { 110 7c478bd9Sstevel@tonic-gate perror(""); 111 7c478bd9Sstevel@tonic-gate exit(FATAL_EXIT); 112 7c478bd9Sstevel@tonic-gate } 113 7c478bd9Sstevel@tonic-gate 114 7c478bd9Sstevel@tonic-gate pid = fork(); 115 7c478bd9Sstevel@tonic-gate if (pid < 0) { 116 7c478bd9Sstevel@tonic-gate perror(NULL); 117 7c478bd9Sstevel@tonic-gate exit(FATAL_EXIT); 118 7c478bd9Sstevel@tonic-gate } 119 7c478bd9Sstevel@tonic-gate 120 7c478bd9Sstevel@tonic-gate /* 121 7c478bd9Sstevel@tonic-gate * Break the creation of a manifest into two parts: the parent process 122 7c478bd9Sstevel@tonic-gate * generated the data whereas the child process sorts the data. 123 7c478bd9Sstevel@tonic-gate * 124 7c478bd9Sstevel@tonic-gate * The processes communicate through the pipe. 125 7c478bd9Sstevel@tonic-gate */ 126 7c478bd9Sstevel@tonic-gate if (pid > 0) { 127 7c478bd9Sstevel@tonic-gate /* 128 7c478bd9Sstevel@tonic-gate * Redirect the stdout of this process so it goes into 129 7c478bd9Sstevel@tonic-gate * output_pipe[0]. The output of this process will be read 130 7c478bd9Sstevel@tonic-gate * by the child, which will sort the output. 131 7c478bd9Sstevel@tonic-gate */ 132 7c478bd9Sstevel@tonic-gate if (dup2(output_pipe[0], STDOUT_FILENO) != STDOUT_FILENO) { 133 7c478bd9Sstevel@tonic-gate perror(NULL); 134 7c478bd9Sstevel@tonic-gate exit(FATAL_EXIT); 135 7c478bd9Sstevel@tonic-gate } 136 7c478bd9Sstevel@tonic-gate (void) close(output_pipe[0]); 137 7c478bd9Sstevel@tonic-gate (void) close(output_pipe[1]); 138 7c478bd9Sstevel@tonic-gate 139 7c478bd9Sstevel@tonic-gate if (filelist_input == B_TRUE) { 140 7c478bd9Sstevel@tonic-gate ret = create_manifest_filelist(argv, reloc_root); 141 7c478bd9Sstevel@tonic-gate } else { 142 7c478bd9Sstevel@tonic-gate ret = create_manifest_rule(reloc_root, rules_fd); 143 7c478bd9Sstevel@tonic-gate } 144 7c478bd9Sstevel@tonic-gate 145 7c478bd9Sstevel@tonic-gate /* Close stdout so the sort in the child proc will complete */ 146 7c478bd9Sstevel@tonic-gate (void) fclose(stdout); 147 7c478bd9Sstevel@tonic-gate } else { 148 7c478bd9Sstevel@tonic-gate /* 149 7c478bd9Sstevel@tonic-gate * Redirect the stdin of this process so its read in from 150 7c478bd9Sstevel@tonic-gate * the pipe, which is the parent process in this case. 151 7c478bd9Sstevel@tonic-gate */ 152 7c478bd9Sstevel@tonic-gate if (dup2(output_pipe[1], STDIN_FILENO) != STDIN_FILENO) { 153 7c478bd9Sstevel@tonic-gate perror(NULL); 154 7c478bd9Sstevel@tonic-gate exit(FATAL_EXIT); 155 7c478bd9Sstevel@tonic-gate } 156 7c478bd9Sstevel@tonic-gate (void) close(output_pipe[0]); 157 7c478bd9Sstevel@tonic-gate 158 7c478bd9Sstevel@tonic-gate output_manifest(); 159 7c478bd9Sstevel@tonic-gate } 160 7c478bd9Sstevel@tonic-gate 161 7c478bd9Sstevel@tonic-gate /* Wait for the child proc (the sort) to complete */ 162 7c478bd9Sstevel@tonic-gate (void) wait(0); 163 7c478bd9Sstevel@tonic-gate 164 7c478bd9Sstevel@tonic-gate return (ret); 165 7c478bd9Sstevel@tonic-gate } 166 7c478bd9Sstevel@tonic-gate 167 7c478bd9Sstevel@tonic-gate /* 168 7c478bd9Sstevel@tonic-gate * Handle the -R option and sets 'root' to be the absolute path of the 169 7c478bd9Sstevel@tonic-gate * relocatable root. This is useful when the user specifies '-R ../../foo'. 170 7c478bd9Sstevel@tonic-gate * 171 7c478bd9Sstevel@tonic-gate * Return code is whether or not the location spec'd by the -R flag is a 172 7c478bd9Sstevel@tonic-gate * directory or not. 173 7c478bd9Sstevel@tonic-gate */ 174 7c478bd9Sstevel@tonic-gate static int 175 7c478bd9Sstevel@tonic-gate sanitize_reloc_root(char *root, size_t bufsize) 176 7c478bd9Sstevel@tonic-gate { 177 7c478bd9Sstevel@tonic-gate char pwd[PATH_MAX]; 178 7c478bd9Sstevel@tonic-gate 179 7c478bd9Sstevel@tonic-gate /* 180 7c478bd9Sstevel@tonic-gate * First, save the current directory and go to the location 181 7c478bd9Sstevel@tonic-gate * specified with the -R option. 182 7c478bd9Sstevel@tonic-gate */ 183 7c478bd9Sstevel@tonic-gate (void) getcwd(pwd, sizeof (pwd)); 184 7c478bd9Sstevel@tonic-gate if (chdir(root) < 0) { 185 7c478bd9Sstevel@tonic-gate /* Failed to change directory, something is wrong.... */ 186 7c478bd9Sstevel@tonic-gate perror(root); 187 7c478bd9Sstevel@tonic-gate return (0); 188 7c478bd9Sstevel@tonic-gate } 189 7c478bd9Sstevel@tonic-gate 190 7c478bd9Sstevel@tonic-gate /* 191 7c478bd9Sstevel@tonic-gate * Save the absolute path of the relocatable root directory. 192 7c478bd9Sstevel@tonic-gate */ 193 7c478bd9Sstevel@tonic-gate (void) getcwd(root, bufsize); 194 7c478bd9Sstevel@tonic-gate 195 7c478bd9Sstevel@tonic-gate /* 196 7c478bd9Sstevel@tonic-gate * Now, go back to where we started, necessary for picking up a rules 197 7c478bd9Sstevel@tonic-gate * file. 198 7c478bd9Sstevel@tonic-gate */ 199 7c478bd9Sstevel@tonic-gate if (chdir(pwd) < 0) { 200 7c478bd9Sstevel@tonic-gate /* Failed to change directory, something is wrong.... */ 201 7c478bd9Sstevel@tonic-gate perror(root); 202 7c478bd9Sstevel@tonic-gate return (0); 203 7c478bd9Sstevel@tonic-gate } 204 7c478bd9Sstevel@tonic-gate 205 7c478bd9Sstevel@tonic-gate /* 206 7c478bd9Sstevel@tonic-gate * Make sure the path returned does not have a trailing /. This 207 7c478bd9Sstevel@tonic-gate * can only happen when the entire pathname is "/". 208 7c478bd9Sstevel@tonic-gate */ 209 7c478bd9Sstevel@tonic-gate if (strcmp(root, "/") == 0) 210 7c478bd9Sstevel@tonic-gate root[0] = '\0'; 211 7c478bd9Sstevel@tonic-gate 212 7c478bd9Sstevel@tonic-gate /* 213 7c478bd9Sstevel@tonic-gate * Since the earlier chdir() succeeded, return success. 214 7c478bd9Sstevel@tonic-gate */ 215 7c478bd9Sstevel@tonic-gate return (1); 216 7c478bd9Sstevel@tonic-gate } 217 7c478bd9Sstevel@tonic-gate 218 7c478bd9Sstevel@tonic-gate /* 219 7c478bd9Sstevel@tonic-gate * This is the worker bee which creates the manifest based upon the command 220 7c478bd9Sstevel@tonic-gate * line options supplied by the user. 221 7c478bd9Sstevel@tonic-gate * 222 7c478bd9Sstevel@tonic-gate * NOTE: create_manifest() eventually outputs data to a pipe, which is read in 223 7c478bd9Sstevel@tonic-gate * by the child process. The child process is running output_manifest(), which 224 7c478bd9Sstevel@tonic-gate * is responsible for generating sorted output. 225 7c478bd9Sstevel@tonic-gate */ 226 7c478bd9Sstevel@tonic-gate static int 227 7c478bd9Sstevel@tonic-gate create_manifest_rule(char *reloc_root, FILE *rule_fp) 228 7c478bd9Sstevel@tonic-gate { 229 7c478bd9Sstevel@tonic-gate struct rule *root; 230 7c478bd9Sstevel@tonic-gate int ret_status = EXIT; 231 7c478bd9Sstevel@tonic-gate uint_t flags; 232 7c478bd9Sstevel@tonic-gate 233 7c478bd9Sstevel@tonic-gate if (compute_chksum) 234 7c478bd9Sstevel@tonic-gate flags = ATTR_CONTENTS; 235 7c478bd9Sstevel@tonic-gate else 236 7c478bd9Sstevel@tonic-gate flags = 0; 237 7c478bd9Sstevel@tonic-gate ret_status = read_rules(rule_fp, reloc_root, flags, 1); 238 7c478bd9Sstevel@tonic-gate 239 7c478bd9Sstevel@tonic-gate /* Loop through every single subtree */ 240 7c478bd9Sstevel@tonic-gate for (root = get_first_subtree(); root != NULL; 241 7c478bd9Sstevel@tonic-gate root = get_next_subtree(root)) { 242 7c478bd9Sstevel@tonic-gate 243 7c478bd9Sstevel@tonic-gate /* 244 7c478bd9Sstevel@tonic-gate * Check to see if this subtree should have contents 245 7c478bd9Sstevel@tonic-gate * checking turned on or off. 246 7c478bd9Sstevel@tonic-gate * 247 7c478bd9Sstevel@tonic-gate * NOTE: The 'compute_chksum' and 'parent_vfs' 248 7c478bd9Sstevel@tonic-gate * are a necessary hack: the variables are used in 249 7c478bd9Sstevel@tonic-gate * walker(), both directly and indirectly. Since 250 7c478bd9Sstevel@tonic-gate * the parameters to walker() are defined by nftw(), 251 7c478bd9Sstevel@tonic-gate * the globals are really a backdoor mechanism. 252 7c478bd9Sstevel@tonic-gate */ 253 a2721256SWilliam Young ret_status = statvfs64(root->subtree, &parent_vfs); 254 7c478bd9Sstevel@tonic-gate if (ret_status < 0) { 255 7c478bd9Sstevel@tonic-gate perror(root->subtree); 256 7c478bd9Sstevel@tonic-gate continue; 257 7c478bd9Sstevel@tonic-gate } 258 7c478bd9Sstevel@tonic-gate 259 7c478bd9Sstevel@tonic-gate /* 260 c690e840SJohn.Zolnowsky@Sun.COM * Walk the subtree and invoke the callback function walker() 261 c690e840SJohn.Zolnowsky@Sun.COM * Use FTW_ANYERR to get FTW_NS and FTW_DNR entries *and* 262 c690e840SJohn.Zolnowsky@Sun.COM * to continue past those errors. 263 7c478bd9Sstevel@tonic-gate */ 264 7c478bd9Sstevel@tonic-gate subtree_root = root; 265 c690e840SJohn.Zolnowsky@Sun.COM (void) nftw64(root->subtree, &walker, 20, FTW_PHYS|FTW_ANYERR); 266 7c478bd9Sstevel@tonic-gate 267 7c478bd9Sstevel@tonic-gate /* 268 7c478bd9Sstevel@tonic-gate * Ugly but necessary: 269 7c478bd9Sstevel@tonic-gate * 270 7c478bd9Sstevel@tonic-gate * walker() must return 0, or the tree walk will stop, 271 7c478bd9Sstevel@tonic-gate * so warning flags must be set through a global. 272 7c478bd9Sstevel@tonic-gate */ 273 7c478bd9Sstevel@tonic-gate if (eval_err == WARNING_EXIT) 274 7c478bd9Sstevel@tonic-gate ret_status = WARNING_EXIT; 275 7c478bd9Sstevel@tonic-gate 276 7c478bd9Sstevel@tonic-gate } 277 7c478bd9Sstevel@tonic-gate return (ret_status); 278 7c478bd9Sstevel@tonic-gate } 279 7c478bd9Sstevel@tonic-gate 280 7c478bd9Sstevel@tonic-gate static int 281 7c478bd9Sstevel@tonic-gate create_manifest_filelist(char **argv, char *reloc_root) 282 7c478bd9Sstevel@tonic-gate { 283 7c478bd9Sstevel@tonic-gate int ret_status = EXIT; 284 7c478bd9Sstevel@tonic-gate char input_fname[PATH_MAX]; 285 7c478bd9Sstevel@tonic-gate 286 7c478bd9Sstevel@tonic-gate while (read_filelist(reloc_root, argv, 287 7c478bd9Sstevel@tonic-gate input_fname, sizeof (input_fname)) != -1) { 288 7c478bd9Sstevel@tonic-gate 289 7c478bd9Sstevel@tonic-gate struct stat64 stat_buf; 290 7c478bd9Sstevel@tonic-gate int ret; 291 7c478bd9Sstevel@tonic-gate 292 7c478bd9Sstevel@tonic-gate ret = lstat64(input_fname, &stat_buf); 293 7c478bd9Sstevel@tonic-gate if (ret < 0) { 294 7c478bd9Sstevel@tonic-gate ret_status = WARNING_EXIT; 295 7c478bd9Sstevel@tonic-gate perror(input_fname); 296 7c478bd9Sstevel@tonic-gate } else { 297 *99389cdeSJan Parcel ret = eval_file(input_fname, &stat_buf, NULL); 298 7c478bd9Sstevel@tonic-gate 299 7c478bd9Sstevel@tonic-gate if (ret == WARNING_EXIT) 300 7c478bd9Sstevel@tonic-gate ret_status = WARNING_EXIT; 301 7c478bd9Sstevel@tonic-gate } 302 7c478bd9Sstevel@tonic-gate } 303 7c478bd9Sstevel@tonic-gate 304 7c478bd9Sstevel@tonic-gate return (ret_status); 305 7c478bd9Sstevel@tonic-gate } 306 7c478bd9Sstevel@tonic-gate 307 7c478bd9Sstevel@tonic-gate /* 308 7c478bd9Sstevel@tonic-gate * output_manifest() the child process. It reads in the output from 309 7c478bd9Sstevel@tonic-gate * create_manifest() and sorts it. 310 7c478bd9Sstevel@tonic-gate */ 311 7c478bd9Sstevel@tonic-gate static void 312 7c478bd9Sstevel@tonic-gate output_manifest(void) 313 7c478bd9Sstevel@tonic-gate { 314 7c478bd9Sstevel@tonic-gate char *env[] = {"LC_CTYPE=C", "LC_COLLATE=C", "LC_NUMERIC=C", NULL}; 315 7c478bd9Sstevel@tonic-gate time_t time_val; 316 7c478bd9Sstevel@tonic-gate struct tm *tm; 317 7c478bd9Sstevel@tonic-gate char time_buf[1024]; 318 7c478bd9Sstevel@tonic-gate 319 7c478bd9Sstevel@tonic-gate (void) printf("%s", MANIFEST_VER); 320 7c478bd9Sstevel@tonic-gate time_val = time((time_t)0); 321 7c478bd9Sstevel@tonic-gate tm = localtime(&time_val); 322 7c478bd9Sstevel@tonic-gate (void) strftime(time_buf, sizeof (time_buf), "%A, %B %d, %Y (%T)", tm); 323 7c478bd9Sstevel@tonic-gate (void) printf("! %s\n", time_buf); 324 7c478bd9Sstevel@tonic-gate (void) printf("%s", FORMAT_STR); 325 7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 326 7c478bd9Sstevel@tonic-gate /* 327 7c478bd9Sstevel@tonic-gate * Simply run sort and read from the the current stdin, which is really 328 7c478bd9Sstevel@tonic-gate * the output of create_manifest(). 329 7c478bd9Sstevel@tonic-gate * Also, make sure the output is unique, since a given file may be 330 7c478bd9Sstevel@tonic-gate * included by several stanzas. 331 7c478bd9Sstevel@tonic-gate */ 332 9c84d166Srm88369 if (execle("/usr/bin/sort", "sort", "-u", NULL, env) < 0) { 333 7c478bd9Sstevel@tonic-gate perror(""); 334 7c478bd9Sstevel@tonic-gate exit(FATAL_EXIT); 335 7c478bd9Sstevel@tonic-gate } 336 7c478bd9Sstevel@tonic-gate 337 7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 338 7c478bd9Sstevel@tonic-gate } 339 7c478bd9Sstevel@tonic-gate 340 7c478bd9Sstevel@tonic-gate /* 341 7c478bd9Sstevel@tonic-gate * Callback function for nftw() 342 7c478bd9Sstevel@tonic-gate */ 343 7c478bd9Sstevel@tonic-gate static int 344 7c478bd9Sstevel@tonic-gate walker(const char *name, const struct stat64 *sp, int type, struct FTW *ftwx) 345 7c478bd9Sstevel@tonic-gate { 346 7c478bd9Sstevel@tonic-gate int ret; 347 a2721256SWilliam Young struct statvfs64 path_vfs; 348 7c478bd9Sstevel@tonic-gate boolean_t dir_flag = B_FALSE; 349 7c478bd9Sstevel@tonic-gate struct rule *rule; 350 7c478bd9Sstevel@tonic-gate 351 7c478bd9Sstevel@tonic-gate switch (type) { 352 7c478bd9Sstevel@tonic-gate case FTW_F: /* file */ 353 7c478bd9Sstevel@tonic-gate rule = check_rules(name, 'F'); 354 7c478bd9Sstevel@tonic-gate if (rule != NULL) { 355 7c478bd9Sstevel@tonic-gate if (rule->attr_list & ATTR_CONTENTS) 356 7c478bd9Sstevel@tonic-gate compute_chksum = 1; 357 7c478bd9Sstevel@tonic-gate else 358 7c478bd9Sstevel@tonic-gate compute_chksum = 0; 359 7c478bd9Sstevel@tonic-gate } 360 7c478bd9Sstevel@tonic-gate break; 361 c690e840SJohn.Zolnowsky@Sun.COM case FTW_SL: /* symbolic link, FTW_PHYS */ 362 c690e840SJohn.Zolnowsky@Sun.COM case FTW_SLN: /* symbolic link, ~FTW_PHYS */ 363 7c478bd9Sstevel@tonic-gate break; 364 c690e840SJohn.Zolnowsky@Sun.COM case FTW_DP: /* end of directory, FTW_DEPTH */ 365 c690e840SJohn.Zolnowsky@Sun.COM case FTW_D: /* enter directory, ~FTW_DEPTH */ 366 7c478bd9Sstevel@tonic-gate dir_flag = B_TRUE; 367 a2721256SWilliam Young ret = statvfs64(name, &path_vfs); 368 7c478bd9Sstevel@tonic-gate if (ret < 0) 369 7c478bd9Sstevel@tonic-gate eval_err = WARNING_EXIT; 370 7c478bd9Sstevel@tonic-gate break; 371 c690e840SJohn.Zolnowsky@Sun.COM case FTW_NS: /* unstatable file */ 372 c690e840SJohn.Zolnowsky@Sun.COM (void) fprintf(stderr, UNKNOWN_FILE, name); 373 7c478bd9Sstevel@tonic-gate eval_err = WARNING_EXIT; 374 c690e840SJohn.Zolnowsky@Sun.COM return (0); 375 c690e840SJohn.Zolnowsky@Sun.COM case FTW_DNR: /* unreadable directory */ 376 c690e840SJohn.Zolnowsky@Sun.COM (void) fprintf(stderr, CANTLIST_DIR, name); 377 c690e840SJohn.Zolnowsky@Sun.COM eval_err = WARNING_EXIT; 378 c690e840SJohn.Zolnowsky@Sun.COM return (0); 379 c690e840SJohn.Zolnowsky@Sun.COM default: 380 c690e840SJohn.Zolnowsky@Sun.COM (void) fprintf(stderr, INTERNAL_ERR, name); 381 c690e840SJohn.Zolnowsky@Sun.COM eval_err = WARNING_EXIT; 382 c690e840SJohn.Zolnowsky@Sun.COM return (0); 383 7c478bd9Sstevel@tonic-gate } 384 7c478bd9Sstevel@tonic-gate 385 7c478bd9Sstevel@tonic-gate /* This is the function which really processes the file */ 386 *99389cdeSJan Parcel ret = eval_file(name, sp, ftwx); 387 7c478bd9Sstevel@tonic-gate 388 7c478bd9Sstevel@tonic-gate /* 389 7c478bd9Sstevel@tonic-gate * Since the parameters to walker() are constrained by nftw(), 390 7c478bd9Sstevel@tonic-gate * need to use a global to reflect a WARNING. Sigh. 391 7c478bd9Sstevel@tonic-gate */ 392 7c478bd9Sstevel@tonic-gate if (ret == WARNING_EXIT) 393 7c478bd9Sstevel@tonic-gate eval_err = WARNING_EXIT; 394 7c478bd9Sstevel@tonic-gate 395 7c478bd9Sstevel@tonic-gate /* 396 7c478bd9Sstevel@tonic-gate * This is a case of a directory which crosses into a mounted 397 7c478bd9Sstevel@tonic-gate * filesystem of a different type, e.g., UFS -> NFS. 398 7c478bd9Sstevel@tonic-gate * BART should not walk the new filesystem (by specification), so 399 7c478bd9Sstevel@tonic-gate * set this consolidation-private flag so the rest of the subtree 400 7c478bd9Sstevel@tonic-gate * under this directory is not waled. 401 7c478bd9Sstevel@tonic-gate */ 402 7c478bd9Sstevel@tonic-gate if (dir_flag && 403 7c478bd9Sstevel@tonic-gate (strcmp(parent_vfs.f_basetype, path_vfs.f_basetype) != 0)) 404 7c478bd9Sstevel@tonic-gate ftwx->quit = FTW_PRUNE; 405 7c478bd9Sstevel@tonic-gate 406 7c478bd9Sstevel@tonic-gate return (0); 407 7c478bd9Sstevel@tonic-gate } 408 7c478bd9Sstevel@tonic-gate 409 7c478bd9Sstevel@tonic-gate /* 410 7c478bd9Sstevel@tonic-gate * This file does the per-file evaluation and is run to generate every entry 411 7c478bd9Sstevel@tonic-gate * in the manifest. 412 7c478bd9Sstevel@tonic-gate * 413 7c478bd9Sstevel@tonic-gate * All output is written to a pipe which is read by the child process, 414 7c478bd9Sstevel@tonic-gate * which is running output_manifest(). 415 7c478bd9Sstevel@tonic-gate */ 416 7c478bd9Sstevel@tonic-gate static int 417 *99389cdeSJan Parcel eval_file(const char *fname, const struct stat64 *statb, struct FTW *ftwx) 418 7c478bd9Sstevel@tonic-gate { 419 *99389cdeSJan Parcel int fd, ret, err_code, i, result; 420 a2721256SWilliam Young char last_field[PATH_MAX], ftype, *acl_str; 421 a2721256SWilliam Young char *quoted_name; 422 7c478bd9Sstevel@tonic-gate 423 7c478bd9Sstevel@tonic-gate err_code = EXIT; 424 7c478bd9Sstevel@tonic-gate 425 7c478bd9Sstevel@tonic-gate switch (statb->st_mode & S_IFMT) { 426 7c478bd9Sstevel@tonic-gate /* Regular file */ 427 7c478bd9Sstevel@tonic-gate case S_IFREG: ftype = 'F'; break; 428 7c478bd9Sstevel@tonic-gate 429 7c478bd9Sstevel@tonic-gate /* Directory */ 430 7c478bd9Sstevel@tonic-gate case S_IFDIR: ftype = 'D'; break; 431 7c478bd9Sstevel@tonic-gate 432 7c478bd9Sstevel@tonic-gate /* Block Device */ 433 7c478bd9Sstevel@tonic-gate case S_IFBLK: ftype = 'B'; break; 434 7c478bd9Sstevel@tonic-gate 435 7c478bd9Sstevel@tonic-gate /* Character Device */ 436 7c478bd9Sstevel@tonic-gate case S_IFCHR: ftype = 'C'; break; 437 7c478bd9Sstevel@tonic-gate 438 7c478bd9Sstevel@tonic-gate /* Named Pipe */ 439 7c478bd9Sstevel@tonic-gate case S_IFIFO: ftype = 'P'; break; 440 7c478bd9Sstevel@tonic-gate 441 7c478bd9Sstevel@tonic-gate /* Socket */ 442 7c478bd9Sstevel@tonic-gate case S_IFSOCK: ftype = 'S'; break; 443 7c478bd9Sstevel@tonic-gate 444 7c478bd9Sstevel@tonic-gate /* Door */ 445 7c478bd9Sstevel@tonic-gate case S_IFDOOR: ftype = 'O'; break; 446 7c478bd9Sstevel@tonic-gate 447 7c478bd9Sstevel@tonic-gate /* Symbolic link */ 448 7c478bd9Sstevel@tonic-gate case S_IFLNK: ftype = 'L'; break; 449 7c478bd9Sstevel@tonic-gate 450 7c478bd9Sstevel@tonic-gate default: ftype = '-'; break; 451 7c478bd9Sstevel@tonic-gate } 452 7c478bd9Sstevel@tonic-gate 453 7c478bd9Sstevel@tonic-gate /* First, make sure this file should be cataloged */ 454 7c478bd9Sstevel@tonic-gate 455 7c478bd9Sstevel@tonic-gate if ((subtree_root != NULL) && 456 *99389cdeSJan Parcel ((result = exclude_fname(fname, ftype, subtree_root)) != 457 *99389cdeSJan Parcel NO_EXCLUDE)) { 458 *99389cdeSJan Parcel if ((result == EXCLUDE_PRUNE) && (ftwx != (struct FTW *)NULL)) 459 *99389cdeSJan Parcel ftwx->quit = FTW_PRUNE; 460 7c478bd9Sstevel@tonic-gate return (err_code); 461 *99389cdeSJan Parcel } 462 7c478bd9Sstevel@tonic-gate for (i = 0; i < PATH_MAX; i++) 463 7c478bd9Sstevel@tonic-gate last_field[i] = '\0'; 464 7c478bd9Sstevel@tonic-gate 465 7c478bd9Sstevel@tonic-gate /* 466 7c478bd9Sstevel@tonic-gate * Regular files, compute the MD5 checksum and put it into 'last_field' 467 7c478bd9Sstevel@tonic-gate * UNLESS instructed to ignore the checksums. 468 7c478bd9Sstevel@tonic-gate */ 469 7c478bd9Sstevel@tonic-gate if (ftype == 'F') { 470 7c478bd9Sstevel@tonic-gate if (compute_chksum) { 471 7c478bd9Sstevel@tonic-gate fd = open(fname, O_RDONLY|O_LARGEFILE); 472 7c478bd9Sstevel@tonic-gate if (fd < 0) { 473 7c478bd9Sstevel@tonic-gate err_code = WARNING_EXIT; 474 7c478bd9Sstevel@tonic-gate perror(fname); 475 7c478bd9Sstevel@tonic-gate 476 7c478bd9Sstevel@tonic-gate /* default value since the computution failed */ 477 7c478bd9Sstevel@tonic-gate (void) strcpy(last_field, "-"); 478 7c478bd9Sstevel@tonic-gate } else { 479 7c478bd9Sstevel@tonic-gate if (generate_hash(fd, last_field) != 0) { 480 7c478bd9Sstevel@tonic-gate err_code = WARNING_EXIT; 481 7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, CONTENTS_WARN, 482 7c478bd9Sstevel@tonic-gate fname); 483 7c478bd9Sstevel@tonic-gate (void) strcpy(last_field, "-"); 484 7c478bd9Sstevel@tonic-gate } 485 7c478bd9Sstevel@tonic-gate } 486 7c478bd9Sstevel@tonic-gate (void) close(fd); 487 7c478bd9Sstevel@tonic-gate } 488 7c478bd9Sstevel@tonic-gate /* Instructed to ignore checksums, just put in a '-' */ 489 7c478bd9Sstevel@tonic-gate else 490 7c478bd9Sstevel@tonic-gate (void) strcpy(last_field, "-"); 491 7c478bd9Sstevel@tonic-gate } 492 7c478bd9Sstevel@tonic-gate 493 7c478bd9Sstevel@tonic-gate /* 494 7c478bd9Sstevel@tonic-gate * For symbolic links, put the destination of the symbolic link into 495 7c478bd9Sstevel@tonic-gate * 'last_field' 496 7c478bd9Sstevel@tonic-gate */ 497 7c478bd9Sstevel@tonic-gate if (ftype == 'L') { 498 7c478bd9Sstevel@tonic-gate ret = readlink(fname, last_field, sizeof (last_field)); 499 7c478bd9Sstevel@tonic-gate if (ret < 0) { 500 7c478bd9Sstevel@tonic-gate err_code = WARNING_EXIT; 501 7c478bd9Sstevel@tonic-gate perror(fname); 502 7c478bd9Sstevel@tonic-gate 503 7c478bd9Sstevel@tonic-gate /* default value since the computation failed */ 504 7c478bd9Sstevel@tonic-gate (void) strcpy(last_field, "-"); 505 7c478bd9Sstevel@tonic-gate } 506 7c478bd9Sstevel@tonic-gate else 507 7c478bd9Sstevel@tonic-gate (void) strlcpy(last_field, 508 7c478bd9Sstevel@tonic-gate sanitized_fname(last_field, B_FALSE), 509 7c478bd9Sstevel@tonic-gate sizeof (last_field)); 510 7c478bd9Sstevel@tonic-gate 511 7c478bd9Sstevel@tonic-gate /* 512 7c478bd9Sstevel@tonic-gate * Boundary condition: possible for a symlink to point to 513 7c478bd9Sstevel@tonic-gate * nothing [ ln -s '' link_name ]. For this case, set the 514 7c478bd9Sstevel@tonic-gate * destination to "\000". 515 7c478bd9Sstevel@tonic-gate */ 516 7c478bd9Sstevel@tonic-gate if (strlen(last_field) == 0) 517 7c478bd9Sstevel@tonic-gate (void) strcpy(last_field, "\\000"); 518 7c478bd9Sstevel@tonic-gate } 519 7c478bd9Sstevel@tonic-gate 520 7c478bd9Sstevel@tonic-gate acl_str = get_acl_string(fname, statb, &err_code); 521 7c478bd9Sstevel@tonic-gate 522 7c478bd9Sstevel@tonic-gate /* Sanitize 'fname', so its in the proper format for the manifest */ 523 7c478bd9Sstevel@tonic-gate quoted_name = sanitized_fname(fname, B_TRUE); 524 7c478bd9Sstevel@tonic-gate 525 7c478bd9Sstevel@tonic-gate /* Start to build the entry.... */ 526 7c478bd9Sstevel@tonic-gate (void) printf("%s %c %d %o %s %x %d %d", quoted_name, ftype, 527 7c478bd9Sstevel@tonic-gate (int)statb->st_size, (int)statb->st_mode, acl_str, 528 7c478bd9Sstevel@tonic-gate (int)statb->st_mtime, (int)statb->st_uid, (int)statb->st_gid); 529 7c478bd9Sstevel@tonic-gate 530 7c478bd9Sstevel@tonic-gate /* Finish it off based upon whether or not it's a device node */ 531 c40f76e3Sjc144527 if ((ftype == 'B') || (ftype == 'C')) 532 7c478bd9Sstevel@tonic-gate (void) printf(" %x\n", (int)statb->st_rdev); 533 7c478bd9Sstevel@tonic-gate else if (strlen(last_field) > 0) 534 7c478bd9Sstevel@tonic-gate (void) printf(" %s\n", last_field); 535 7c478bd9Sstevel@tonic-gate else 536 7c478bd9Sstevel@tonic-gate (void) printf("\n"); 537 7c478bd9Sstevel@tonic-gate 538 7c478bd9Sstevel@tonic-gate /* free the memory consumed */ 539 7c478bd9Sstevel@tonic-gate free(acl_str); 540 7c478bd9Sstevel@tonic-gate free(quoted_name); 541 7c478bd9Sstevel@tonic-gate 542 7c478bd9Sstevel@tonic-gate return (err_code); 543 7c478bd9Sstevel@tonic-gate } 544 7c478bd9Sstevel@tonic-gate 545 7c478bd9Sstevel@tonic-gate /* 546 7c478bd9Sstevel@tonic-gate * When creating a manifest, make sure all '?', tabs, space, newline, '/' 547 7c478bd9Sstevel@tonic-gate * and '[' are all properly quoted. Convert them to a "\ooo" where the 'ooo' 548 7c478bd9Sstevel@tonic-gate * represents their octal value. For filesystem objects, as opposed to symlink 549 7c478bd9Sstevel@tonic-gate * targets, also canonicalize the pathname. 550 7c478bd9Sstevel@tonic-gate */ 551 7c478bd9Sstevel@tonic-gate static char * 552 7c478bd9Sstevel@tonic-gate sanitized_fname(const char *fname, boolean_t canon_path) 553 7c478bd9Sstevel@tonic-gate { 554 7c478bd9Sstevel@tonic-gate const char *ip; 555 7c478bd9Sstevel@tonic-gate unsigned char ch; 556 7c478bd9Sstevel@tonic-gate char *op, *quoted_name; 557 7c478bd9Sstevel@tonic-gate 558 7c478bd9Sstevel@tonic-gate /* Initialize everything */ 559 7c478bd9Sstevel@tonic-gate quoted_name = safe_calloc((4 * PATH_MAX) + 1); 560 7c478bd9Sstevel@tonic-gate ip = fname; 561 7c478bd9Sstevel@tonic-gate op = quoted_name; 562 7c478bd9Sstevel@tonic-gate 563 7c478bd9Sstevel@tonic-gate if (canon_path) { 564 7c478bd9Sstevel@tonic-gate /* 565 7c478bd9Sstevel@tonic-gate * In the case when a relocatable root was used, the relocatable 566 7c478bd9Sstevel@tonic-gate * root should *not* be part of the manifest. 567 7c478bd9Sstevel@tonic-gate */ 568 7c478bd9Sstevel@tonic-gate ip += strlen(reloc_root); 569 7c478bd9Sstevel@tonic-gate 570 7c478bd9Sstevel@tonic-gate /* 571 7c478bd9Sstevel@tonic-gate * In the case when the '-I' option was used, make sure 572 7c478bd9Sstevel@tonic-gate * the quoted_name starts with a '/'. 573 7c478bd9Sstevel@tonic-gate */ 574 7c478bd9Sstevel@tonic-gate if (*ip != '/') 575 7c478bd9Sstevel@tonic-gate *op++ = '/'; 576 7c478bd9Sstevel@tonic-gate } 577 7c478bd9Sstevel@tonic-gate 578 7c478bd9Sstevel@tonic-gate /* Now walk through 'fname' and build the quoted string */ 579 7c478bd9Sstevel@tonic-gate while ((ch = *ip++) != 0) { 580 7c478bd9Sstevel@tonic-gate switch (ch) { 581 7c478bd9Sstevel@tonic-gate /* Quote the following characters */ 582 7c478bd9Sstevel@tonic-gate case ' ': 583 7c478bd9Sstevel@tonic-gate case '*': 584 7c478bd9Sstevel@tonic-gate case '\n': 585 7c478bd9Sstevel@tonic-gate case '?': 586 7c478bd9Sstevel@tonic-gate case '[': 587 7c478bd9Sstevel@tonic-gate case '\\': 588 7c478bd9Sstevel@tonic-gate case '\t': 589 7c478bd9Sstevel@tonic-gate op += sprintf(op, "\\%.3o", (unsigned char)ch); 590 7c478bd9Sstevel@tonic-gate break; 591 7c478bd9Sstevel@tonic-gate 592 7c478bd9Sstevel@tonic-gate /* Otherwise, simply append them */ 593 7c478bd9Sstevel@tonic-gate default: 594 7c478bd9Sstevel@tonic-gate *op++ = ch; 595 7c478bd9Sstevel@tonic-gate break; 596 7c478bd9Sstevel@tonic-gate } 597 7c478bd9Sstevel@tonic-gate } 598 7c478bd9Sstevel@tonic-gate 599 7c478bd9Sstevel@tonic-gate *op = 0; 600 7c478bd9Sstevel@tonic-gate 601 7c478bd9Sstevel@tonic-gate return (quoted_name); 602 7c478bd9Sstevel@tonic-gate } 603 7c478bd9Sstevel@tonic-gate 604 7c478bd9Sstevel@tonic-gate /* 605 7c478bd9Sstevel@tonic-gate * Function responsible for generating the ACL information for a given 606 7c478bd9Sstevel@tonic-gate * file. Note, the string is put into buffer malloc'd by this function. 607 a2721256SWilliam Young * It's the responsibility of the caller to free the buffer. This function 608 a2721256SWilliam Young * should never return a NULL pointer. 609 7c478bd9Sstevel@tonic-gate */ 610 7c478bd9Sstevel@tonic-gate static char * 611 7c478bd9Sstevel@tonic-gate get_acl_string(const char *fname, const struct stat64 *statb, int *err_code) 612 7c478bd9Sstevel@tonic-gate { 613 fa9e4066Sahrens acl_t *aclp; 614 fa9e4066Sahrens char *acltext; 615 fa9e4066Sahrens int error; 616 7c478bd9Sstevel@tonic-gate 617 7c478bd9Sstevel@tonic-gate if (S_ISLNK(statb->st_mode)) { 618 7c478bd9Sstevel@tonic-gate return (safe_strdup("-")); 619 7c478bd9Sstevel@tonic-gate } 620 7c478bd9Sstevel@tonic-gate 621 7c478bd9Sstevel@tonic-gate /* 622 fa9e4066Sahrens * Include trivial acl's 623 7c478bd9Sstevel@tonic-gate */ 624 fa9e4066Sahrens error = acl_get(fname, 0, &aclp); 625 fa9e4066Sahrens 626 fa9e4066Sahrens if (error != 0) { 627 7c478bd9Sstevel@tonic-gate *err_code = WARNING_EXIT; 628 fa9e4066Sahrens (void) fprintf(stderr, "%s: %s\n", fname, acl_strerror(error)); 629 7c478bd9Sstevel@tonic-gate return (safe_strdup("-")); 630 fa9e4066Sahrens } else { 631 5a5eeccaSmarks acltext = acl_totext(aclp, 0); 632 fa9e4066Sahrens acl_free(aclp); 633 a2721256SWilliam Young if (acltext == NULL) 634 a2721256SWilliam Young return (safe_strdup("-")); 635 a2721256SWilliam Young else 636 fa9e4066Sahrens return (acltext); 637 7c478bd9Sstevel@tonic-gate } 638 7c478bd9Sstevel@tonic-gate } 639 7c478bd9Sstevel@tonic-gate 640 7c478bd9Sstevel@tonic-gate 641 7c478bd9Sstevel@tonic-gate /* 642 7c478bd9Sstevel@tonic-gate * 643 7c478bd9Sstevel@tonic-gate * description: This routine reads stdin in BUF_SIZE chunks, uses the bits 644 7c478bd9Sstevel@tonic-gate * to update the md5 hash buffer, and outputs the chunks 645 7c478bd9Sstevel@tonic-gate * to stdout. When stdin is exhausted, the hash is computed, 646 7c478bd9Sstevel@tonic-gate * converted to a hexadecimal string, and returned. 647 7c478bd9Sstevel@tonic-gate * 648 7c478bd9Sstevel@tonic-gate * returns: The md5 hash of stdin, or NULL if unsuccessful for any reason. 649 7c478bd9Sstevel@tonic-gate */ 650 7c478bd9Sstevel@tonic-gate static int 651 7c478bd9Sstevel@tonic-gate generate_hash(int fdin, char *hash_str) 652 7c478bd9Sstevel@tonic-gate { 653 7c478bd9Sstevel@tonic-gate unsigned char buf[BUF_SIZE]; 654 7c478bd9Sstevel@tonic-gate unsigned char hash[MD5_DIGEST_LENGTH]; 655 7c478bd9Sstevel@tonic-gate int i, amtread; 656 7c478bd9Sstevel@tonic-gate MD5_CTX ctx; 657 7c478bd9Sstevel@tonic-gate 658 7c478bd9Sstevel@tonic-gate MD5Init(&ctx); 659 7c478bd9Sstevel@tonic-gate 660 7c478bd9Sstevel@tonic-gate for (;;) { 661 7c478bd9Sstevel@tonic-gate amtread = read(fdin, buf, sizeof (buf)); 662 7c478bd9Sstevel@tonic-gate if (amtread == 0) 663 7c478bd9Sstevel@tonic-gate break; 664 7c478bd9Sstevel@tonic-gate if (amtread < 0) 665 7c478bd9Sstevel@tonic-gate return (1); 666 7c478bd9Sstevel@tonic-gate 667 7c478bd9Sstevel@tonic-gate /* got some data. Now update hash */ 668 7c478bd9Sstevel@tonic-gate MD5Update(&ctx, buf, amtread); 669 7c478bd9Sstevel@tonic-gate } 670 7c478bd9Sstevel@tonic-gate 671 7c478bd9Sstevel@tonic-gate /* done passing through data, calculate hash */ 672 7c478bd9Sstevel@tonic-gate MD5Final(hash, &ctx); 673 7c478bd9Sstevel@tonic-gate 674 7c478bd9Sstevel@tonic-gate for (i = 0; i < MD5_DIGEST_LENGTH; i++) 675 7c478bd9Sstevel@tonic-gate (void) sprintf(hash_str + (i*2), "%2.2x", hash[i]); 676 7c478bd9Sstevel@tonic-gate 677 7c478bd9Sstevel@tonic-gate return (0); 678 7c478bd9Sstevel@tonic-gate } 679 7c478bd9Sstevel@tonic-gate 680 7c478bd9Sstevel@tonic-gate /* 681 7c478bd9Sstevel@tonic-gate * Used by 'bart create' with the '-I' option. Return each entry into a 'buf' 682 7c478bd9Sstevel@tonic-gate * with the appropriate exit code: '0' for success and '-1' for failure. 683 7c478bd9Sstevel@tonic-gate */ 684 7c478bd9Sstevel@tonic-gate static int 685 7c478bd9Sstevel@tonic-gate read_filelist(char *reloc_root, char **argv, char *buf, size_t bufsize) 686 7c478bd9Sstevel@tonic-gate { 687 7c478bd9Sstevel@tonic-gate static int argv_index = -1; 688 7c478bd9Sstevel@tonic-gate static boolean_t read_stdinput = B_FALSE; 689 7c478bd9Sstevel@tonic-gate char temp_buf[PATH_MAX]; 690 7c478bd9Sstevel@tonic-gate char *cp; 691 7c478bd9Sstevel@tonic-gate 692 7c478bd9Sstevel@tonic-gate /* 693 7c478bd9Sstevel@tonic-gate * INITIALIZATION: 694 7c478bd9Sstevel@tonic-gate * Setup this code so it knows whether or not to read sdtin. 695 7c478bd9Sstevel@tonic-gate * Also, if reading from argv, setup the index, "argv_index" 696 7c478bd9Sstevel@tonic-gate */ 697 7c478bd9Sstevel@tonic-gate if (argv_index == -1) { 698 7c478bd9Sstevel@tonic-gate argv_index = 0; 699 7c478bd9Sstevel@tonic-gate 700 7c478bd9Sstevel@tonic-gate /* In this case, no args after '-I', so read stdin */ 701 7c478bd9Sstevel@tonic-gate if (argv[0] == NULL) 702 7c478bd9Sstevel@tonic-gate read_stdinput = B_TRUE; 703 7c478bd9Sstevel@tonic-gate } 704 7c478bd9Sstevel@tonic-gate 705 7c478bd9Sstevel@tonic-gate buf[0] = '\0'; 706 7c478bd9Sstevel@tonic-gate 707 7c478bd9Sstevel@tonic-gate if (read_stdinput) { 708 7c478bd9Sstevel@tonic-gate if (fgets(temp_buf, PATH_MAX, stdin) == NULL) 709 7c478bd9Sstevel@tonic-gate return (-1); 710 7c478bd9Sstevel@tonic-gate cp = strtok(temp_buf, "\n"); 711 7c478bd9Sstevel@tonic-gate } else { 712 7c478bd9Sstevel@tonic-gate cp = argv[argv_index++]; 713 7c478bd9Sstevel@tonic-gate } 714 7c478bd9Sstevel@tonic-gate 715 7c478bd9Sstevel@tonic-gate if (cp == NULL) 716 7c478bd9Sstevel@tonic-gate return (-1); 717 7c478bd9Sstevel@tonic-gate 718 7c478bd9Sstevel@tonic-gate /* 719 7c478bd9Sstevel@tonic-gate * Unlike similar code elsewhere, avoid adding a leading 720 7c478bd9Sstevel@tonic-gate * slash for relative pathnames. 721 7c478bd9Sstevel@tonic-gate */ 722 7c478bd9Sstevel@tonic-gate (void) snprintf(buf, bufsize, 723 7c478bd9Sstevel@tonic-gate (reloc_root[0] == '\0' || cp[0] == '/') ? "%s%s" : "%s/%s", 724 7c478bd9Sstevel@tonic-gate reloc_root, cp); 725 7c478bd9Sstevel@tonic-gate 726 7c478bd9Sstevel@tonic-gate return (0); 727 7c478bd9Sstevel@tonic-gate } 728