0
|
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 2003 Sun Microsystems, Inc. All rights reserved.
|
|
24 * Use is subject to license terms.
|
|
25 */
|
|
26 #pragma ident "@(#)compare.c 1.3 05/06/08 SMI"
|
|
27
|
|
28 #include <unistd.h>
|
|
29 #include "bart.h"
|
|
30
|
|
31 static int compare_manifests(FILE *rulesfile, char *control, char *test,
|
|
32 boolean_t prog_fmt, uint_t flags);
|
|
33 static void extract_fname_ftype(char *line, char *fname, char *type);
|
|
34 static int report_add(char *fname, char *type);
|
|
35 static int report_delete(char *fname, char *type);
|
|
36 static int evaluate_differences(char *control_line, char *test_line,
|
|
37 boolean_t prog_fmt, int flags);
|
|
38 static void report_error(char *fname, char *type, char *ctrl_val,
|
|
39 char *test_val, boolean_t prog_fmt);
|
|
40 static int read_manifest_line(FILE *fd, char *buf, int buf_size, int start_pos,
|
|
41 char **line, char *fname);
|
|
42 static void parse_line(char *line, char *fname, char *type, char *size,
|
|
43 char *mode, char *acl, char *mtime, char *uid, char *gid, char *contents,
|
|
44 char *devnode, char *dest);
|
|
45 static void init_default_flags(uint_t *flags);
|
|
46 static void get_token(char *line, int *curr_pos, int line_len, char *buf,
|
|
47 int buf_size);
|
|
48
|
|
49 int
|
|
50 bart_compare(int argc, char **argv)
|
|
51 {
|
|
52 char *control_fname, *test_fname;
|
|
53 int c;
|
|
54 FILE *rules_fd = NULL;
|
|
55 uint_t glob_flags;
|
|
56 boolean_t prog_fmt = B_FALSE;
|
|
57
|
|
58 init_default_flags(&glob_flags);
|
|
59
|
|
60 while ((c = getopt(argc, argv, "pr:i:")) != EOF) {
|
|
61 switch (c) {
|
|
62 case 'p':
|
|
63 prog_fmt = B_TRUE;
|
|
64 break;
|
|
65
|
|
66 case 'r':
|
|
67 if (optarg == NULL)
|
|
68 usage();
|
|
69
|
|
70 if (strcmp(optarg, "-") == 0)
|
|
71 rules_fd = stdin;
|
|
72 else
|
|
73 rules_fd = fopen(optarg, "r");
|
|
74 if (rules_fd == NULL) {
|
|
75 perror(optarg);
|
|
76 usage();
|
|
77 }
|
|
78 break;
|
|
79
|
|
80 case 'i':
|
|
81 process_glob_ignores(optarg, &glob_flags);
|
|
82 break;
|
|
83
|
|
84 case '?':
|
|
85 default:
|
|
86 usage();
|
|
87 }
|
|
88 }
|
|
89
|
|
90 /* Make sure we have the right number of args */
|
|
91 if ((optind + 2) != argc)
|
|
92 usage();
|
|
93 argv += optind;
|
|
94 control_fname = argv[0];
|
|
95 test_fname = argv[1];
|
|
96 /* At this point, the filenames are sane, so do the comparison */
|
|
97 return (compare_manifests(rules_fd, control_fname, test_fname,
|
|
98 prog_fmt, glob_flags));
|
|
99 }
|
|
100
|
|
101 static int
|
|
102 compare_manifests(FILE *rulesfile, char *control, char *test,
|
|
103 boolean_t prog_fmt, uint_t flags)
|
|
104 {
|
|
105 FILE *control_fd, *test_fd;
|
|
106 char *control_line, *test_line, control_buf[BUF_SIZE],
|
|
107 test_buf[BUF_SIZE], control_fname[PATH_MAX],
|
|
108 control_type[TYPE_SIZE], test_fname[PATH_MAX],
|
|
109 test_type[TYPE_SIZE];
|
|
110 int control_pos, test_pos, ret, fname_cmp, return_status;
|
|
111
|
|
112 return_status = EXIT;
|
|
113
|
|
114 return_status = read_rules(rulesfile, "", flags, 0);
|
|
115
|
|
116 control_fd = fopen(control, "r");
|
|
117 if (control_fd == NULL) {
|
|
118 perror(control);
|
|
119 return (FATAL_EXIT);
|
|
120 }
|
|
121
|
|
122 test_fd = fopen(test, "r");
|
|
123 if (test_fd == NULL) {
|
|
124 perror(test);
|
|
125 return (FATAL_EXIT);
|
|
126 }
|
|
127
|
|
128 control_pos = read_manifest_line(control_fd, control_buf,
|
|
129 BUF_SIZE, 0, &control_line, control);
|
|
130 test_pos = read_manifest_line(test_fd, test_buf, BUF_SIZE, 0,
|
|
131 &test_line, test);
|
|
132
|
|
133 while ((control_pos != -1) && (test_pos != -1)) {
|
|
134 ret = strcmp(control_line, test_line);
|
|
135 if (ret == 0) {
|
|
136 /* Lines compare OK, just read the next lines.... */
|
|
137 control_pos = read_manifest_line(control_fd,
|
|
138 control_buf, BUF_SIZE, control_pos, &control_line,
|
|
139 control);
|
|
140 test_pos = read_manifest_line(test_fd, test_buf,
|
|
141 BUF_SIZE, test_pos, &test_line, test);
|
|
142 continue;
|
|
143 }
|
|
144
|
|
145 /*
|
|
146 * Something didn't compare properly.
|
|
147 */
|
|
148 extract_fname_ftype(control_line, control_fname, control_type);
|
|
149 extract_fname_ftype(test_line, test_fname, test_type);
|
|
150 fname_cmp = strcmp(control_fname, test_fname);
|
|
151
|
|
152 if (fname_cmp == 0) {
|
|
153 /*
|
|
154 * Filenames were the same, see what was
|
|
155 * different and continue.
|
|
156 */
|
|
157 if (evaluate_differences(control_line, test_line,
|
|
158 prog_fmt, flags) != 0)
|
|
159 return_status = WARNING_EXIT;
|
|
160
|
|
161 control_pos = read_manifest_line(control_fd,
|
|
162 control_buf, BUF_SIZE, control_pos, &control_line,
|
|
163 control);
|
|
164 test_pos = read_manifest_line(test_fd, test_buf,
|
|
165 BUF_SIZE, test_pos, &test_line, test);
|
|
166 } else if (fname_cmp > 0) {
|
|
167 /* Filenames were different, a files was ADDED */
|
|
168 if (report_add(test_fname, test_type)) {
|
|
169 report_error(test_fname, ADD_KEYWORD, NULL,
|
|
170 NULL, prog_fmt);
|
|
171 return_status = WARNING_EXIT;
|
|
172 }
|
|
173 test_pos = read_manifest_line(test_fd, test_buf,
|
|
174 BUF_SIZE, test_pos, &test_line, test);
|
|
175 } else if (fname_cmp < 0) {
|
|
176 /* Filenames were different, a files was DELETED */
|
|
177 if (report_delete(control_fname, control_type)) {
|
|
178 report_error(control_fname, DELETE_KEYWORD,
|
|
179 NULL, NULL, prog_fmt);
|
|
180 return_status = WARNING_EXIT;
|
|
181 }
|
|
182 control_pos = read_manifest_line(control_fd,
|
|
183 control_buf, BUF_SIZE, control_pos, &control_line,
|
|
184 control);
|
|
185 }
|
|
186 }
|
|
187
|
|
188 /*
|
|
189 * Entering this while loop means files were DELETED from the test
|
|
190 * manifest.
|
|
191 */
|
|
192 while (control_pos != -1) {
|
|
193 (void) sscanf(control_line, "%1023s", control_fname);
|
|
194 if (report_delete(control_fname, control_type)) {
|
|
195 report_error(control_fname, DELETE_KEYWORD, NULL,
|
|
196 NULL, prog_fmt);
|
|
197 return_status = WARNING_EXIT;
|
|
198 }
|
|
199 control_pos = read_manifest_line(control_fd, control_buf,
|
|
200 BUF_SIZE, control_pos, &control_line, control);
|
|
201 }
|
|
202
|
|
203 /*
|
|
204 * Entering this while loop means files were ADDED to the test
|
|
205 * manifest.
|
|
206 */
|
|
207 while (test_pos != -1) {
|
|
208 (void) sscanf(test_line, "%1023s", test_fname);
|
|
209 if (report_add(test_fname, test_type)) {
|
|
210 report_error(test_fname, ADD_KEYWORD, NULL,
|
|
211 NULL, prog_fmt);
|
|
212 return_status = WARNING_EXIT;
|
|
213 }
|
|
214 test_pos = read_manifest_line(test_fd, test_buf,
|
|
215 BUF_SIZE, test_pos, &test_line, test);
|
|
216 }
|
|
217
|
|
218 (void) fclose(control_fd);
|
|
219 (void) fclose(test_fd);
|
|
220
|
|
221 /* For programmatic mode, add a newline for cosmetic reasons */
|
|
222 if (prog_fmt && (return_status != 0))
|
|
223 (void) printf("\n");
|
|
224
|
|
225 return (return_status);
|
|
226 }
|
|
227
|
|
228 static void
|
|
229 parse_line(char *line, char *fname, char *type, char *size, char *mode,
|
|
230 char *acl, char *mtime, char *uid, char *gid, char *contents, char *devnode,
|
|
231 char *dest)
|
|
232 {
|
|
233 int pos, line_len;
|
|
234
|
|
235 line_len = strlen(line);
|
|
236 pos = 0;
|
|
237
|
|
238 get_token(line, &pos, line_len, fname, PATH_MAX);
|
|
239 get_token(line, &pos, line_len, type, TYPE_SIZE);
|
|
240 get_token(line, &pos, line_len, size, MISC_SIZE);
|
|
241 get_token(line, &pos, line_len, mode, MISC_SIZE);
|
|
242 get_token(line, &pos, line_len, acl, ACL_SIZE);
|
|
243 get_token(line, &pos, line_len, mtime, MISC_SIZE);
|
|
244 get_token(line, &pos, line_len, uid, MISC_SIZE);
|
|
245 get_token(line, &pos, line_len, gid, MISC_SIZE);
|
|
246
|
|
247 /* Reset these fields... */
|
|
248
|
|
249 *contents = NULL;
|
|
250 *devnode = '\0';
|
|
251 *dest = '\0';
|
|
252
|
|
253 /* Handle filetypes which have a last field..... */
|
|
254 if (type[0] == 'F')
|
|
255 get_token(line, &pos, line_len, contents, PATH_MAX);
|
|
256 else if ((type[0] == 'B') || (type[0] == 'C'))
|
|
257 get_token(line, &pos, line_len, devnode, PATH_MAX);
|
|
258 else if (type[0] == 'L')
|
|
259 get_token(line, &pos, line_len, dest, PATH_MAX);
|
|
260 }
|
|
261
|
|
262 static void
|
|
263 get_token(char *line, int *curr_pos, int line_len, char *buf, int buf_size)
|
|
264 {
|
|
265 int cnt = 0;
|
|
266
|
|
267 while (isspace(line[*curr_pos]) && (*curr_pos < line_len))
|
|
268 (*curr_pos)++;
|
|
269
|
|
270 while (!isspace(line[*curr_pos]) &&
|
|
271 (*curr_pos < line_len) && (cnt < (buf_size-1))) {
|
|
272 buf[cnt] = line[*curr_pos];
|
|
273 (*curr_pos)++;
|
|
274 cnt++;
|
|
275 }
|
|
276 buf[cnt] = '\0';
|
|
277 }
|
|
278
|
|
279 /*
|
|
280 * Utility function: extract fname and type from this line
|
|
281 */
|
|
282 static void
|
|
283 extract_fname_ftype(char *line, char *fname, char *type)
|
|
284 {
|
|
285 int line_len, pos;
|
|
286
|
|
287 pos = 0;
|
|
288 line_len = strlen(line);
|
|
289
|
|
290 get_token(line, &pos, line_len, fname, PATH_MAX);
|
|
291 get_token(line, &pos, line_len, type, TYPE_SIZE);
|
|
292 }
|
|
293
|
|
294 /*
|
|
295 * Utility function: tells us whether or not this addition should be reported
|
|
296 *
|
|
297 * Returns 0 if the discrepancy is ignored, non-zero if the discrepancy is
|
|
298 * reported.
|
|
299 */
|
|
300 static int
|
|
301 report_add(char *fname, char *type)
|
|
302 {
|
|
303 struct rule *rule_ptr;
|
|
304
|
|
305 rule_ptr = check_rules(fname, type[0]);
|
|
306 if ((rule_ptr != NULL) && (rule_ptr->attr_list & ATTR_ADD))
|
|
307 return (1);
|
|
308 else
|
|
309 return (0);
|
|
310 }
|
|
311
|
|
312 /*
|
|
313 * Utility function: tells us whether or not this deletion should be reported
|
|
314 *
|
|
315 * Returns 0 if the discrepancy is ignored, non-zero if the discrepancy is
|
|
316 * reported.
|
|
317 */
|
|
318 static int
|
|
319 report_delete(char *fname, char *type)
|
|
320 {
|
|
321 struct rule *rule_ptr;
|
|
322
|
|
323 rule_ptr = check_rules(fname, type[0]);
|
|
324
|
|
325 if ((rule_ptr != NULL) && (rule_ptr->attr_list & ATTR_DELETE))
|
|
326 return (1);
|
|
327 else
|
|
328 return (0);
|
|
329 }
|
|
330
|
|
331 /*
|
|
332 * This function takes in the two entries, which have been flagged as
|
|
333 * different, breaks them up and reports discrepancies. Note, discrepancies
|
|
334 * are affected by the 'CHECK' and 'IGNORE' stanzas which may apply to
|
|
335 * these entries.
|
|
336 *
|
|
337 * Returns the number of discrepancies reported.
|
|
338 */
|
|
339 static int
|
|
340 evaluate_differences(char *control_line, char *test_line,
|
|
341 boolean_t prog_fmt, int flags)
|
|
342 {
|
|
343 char ctrl_fname[PATH_MAX], test_fname[PATH_MAX],
|
|
344 ctrl_type[TYPE_SIZE], test_type[TYPE_SIZE],
|
|
345 ctrl_size[MISC_SIZE], ctrl_mode[MISC_SIZE],
|
|
346 ctrl_acl[ACL_SIZE], ctrl_mtime[MISC_SIZE],
|
|
347 ctrl_uid[MISC_SIZE], ctrl_gid[MISC_SIZE],
|
|
348 ctrl_dest[PATH_MAX], ctrl_contents[PATH_MAX],
|
|
349 ctrl_devnode[PATH_MAX], test_size[MISC_SIZE],
|
|
350 test_mode[MISC_SIZE], test_acl[ACL_SIZE],
|
|
351 test_mtime[MISC_SIZE], test_uid[MISC_SIZE],
|
|
352 test_gid[MISC_SIZE], test_dest[PATH_MAX],
|
|
353 test_contents[PATH_MAX], test_devnode[PATH_MAX],
|
|
354 *tag;
|
|
355 int ret_val;
|
|
356 struct rule *rule_ptr;
|
|
357
|
|
358 ret_val = 0;
|
|
359
|
|
360 parse_line(control_line, ctrl_fname, ctrl_type, ctrl_size, ctrl_mode,
|
|
361 ctrl_acl, ctrl_mtime, ctrl_uid, ctrl_gid, ctrl_contents,
|
|
362 ctrl_devnode, ctrl_dest);
|
|
363
|
|
364 /*
|
|
365 * Now we know the fname and type, let's get the rule that matches this
|
|
366 * manifest entry. If there is a match, make sure to setup the
|
|
367 * correct reporting flags.
|
|
368 */
|
|
369 rule_ptr = check_rules(ctrl_fname, ctrl_type[0]);
|
|
370 if (rule_ptr != NULL)
|
|
371 flags = rule_ptr->attr_list;
|
|
372
|
|
373 parse_line(test_line, test_fname, test_type, test_size, test_mode,
|
|
374 test_acl, test_mtime, test_uid, test_gid, test_contents,
|
|
375 test_devnode, test_dest);
|
|
376
|
|
377 /*
|
|
378 * Report the errors based upon which keywords have been set by
|
|
379 * the user.
|
|
380 */
|
|
381 if ((flags & ATTR_TYPE) && (ctrl_type[0] != test_type[0])) {
|
|
382 report_error(ctrl_fname, TYPE_KEYWORD, ctrl_type,
|
|
383 test_type, prog_fmt);
|
|
384 ret_val++;
|
|
385 }
|
|
386
|
|
387 if ((flags & ATTR_SIZE) && (strcmp(ctrl_size, test_size) != 0)) {
|
|
388 report_error(ctrl_fname, SIZE_KEYWORD, ctrl_size,
|
|
389 test_size, prog_fmt);
|
|
390 ret_val++;
|
|
391 }
|
|
392
|
|
393 if ((flags & ATTR_MODE) && (strcmp(ctrl_mode, test_mode) != 0)) {
|
|
394 report_error(ctrl_fname, MODE_KEYWORD, ctrl_mode,
|
|
395 test_mode, prog_fmt);
|
|
396 ret_val++;
|
|
397 }
|
|
398
|
|
399 if ((flags & ATTR_ACL) && (strcmp(ctrl_acl, test_acl) != 0)) {
|
|
400 report_error(ctrl_fname, ACL_KEYWORD, ctrl_acl,
|
|
401 test_acl, prog_fmt);
|
|
402 ret_val++;
|
|
403 }
|
|
404
|
|
405 if ((flags & ATTR_MTIME) && (ctrl_type[0] == test_type[0])) {
|
|
406 if (strcmp(ctrl_mtime, test_mtime) != 0) {
|
|
407 switch (ctrl_type[0]) {
|
|
408 case 'D':
|
|
409 tag = "dirmtime";
|
|
410 break;
|
|
411 case 'L':
|
|
412 tag = "lnmtime";
|
|
413 break;
|
|
414 default:
|
|
415 tag = "mtime";
|
|
416 break;
|
|
417 }
|
|
418 if (flags == 0) {
|
|
419 report_error(ctrl_fname, tag, ctrl_mtime,
|
|
420 test_mtime, prog_fmt);
|
|
421 ret_val++;
|
|
422 }
|
|
423 }
|
|
424
|
|
425 if ((ctrl_type[0] == 'F') && (flags & ATTR_MTIME) &&
|
|
426 (strcmp(ctrl_mtime, test_mtime) != 0)) {
|
|
427 report_error(ctrl_fname, MTIME_KEYWORD, ctrl_mtime, test_mtime,
|
|
428 prog_fmt);
|
|
429 ret_val++;
|
|
430 }
|
|
431
|
|
432 if ((ctrl_type[0] == 'D') && (flags & ATTR_DIRMTIME) &&
|
|
433 (strcmp(ctrl_mtime, test_mtime) != 0)) {
|
|
434 report_error(ctrl_fname, DIRMTIME_KEYWORD, ctrl_mtime,
|
|
435 test_mtime, prog_fmt);
|
|
436 ret_val++;
|
|
437 }
|
|
438
|
|
439 if ((ctrl_type[0] == 'L') && (flags & ATTR_LNMTIME) &&
|
|
440 (strcmp(ctrl_mtime, test_mtime) != 0)) {
|
|
441 report_error(ctrl_fname, LNMTIME_KEYWORD, ctrl_mtime,
|
|
442 test_mtime, prog_fmt);
|
|
443 ret_val++;
|
|
444 }
|
|
445 } else if ((flags & ATTR_MTIME) &&
|
|
446 (strcmp(ctrl_mtime, test_mtime) != 0)) {
|
|
447 report_error(ctrl_fname, MTIME_KEYWORD, ctrl_mtime,
|
|
448 test_mtime, prog_fmt);
|
|
449 ret_val++;
|
|
450 }
|
|
451
|
|
452 if ((flags & ATTR_UID) && (strcmp(ctrl_uid, test_uid) != 0)) {
|
|
453 report_error(ctrl_fname, UID_KEYWORD, ctrl_uid,
|
|
454 test_uid, prog_fmt);
|
|
455 ret_val++;
|
|
456 }
|
|
457
|
|
458 if ((flags & ATTR_GID) && (strcmp(ctrl_gid, test_gid) != 0)) {
|
|
459 report_error(ctrl_fname, GID_KEYWORD, ctrl_gid,
|
|
460 test_gid, prog_fmt);
|
|
461 ret_val++;
|
|
462 }
|
|
463
|
|
464 if ((flags & ATTR_DEVNODE) &&
|
|
465 (strcmp(ctrl_devnode, test_devnode) != 0)) {
|
|
466 report_error(ctrl_fname, DEVNODE_KEYWORD, ctrl_devnode,
|
|
467 test_devnode, prog_fmt);
|
|
468 ret_val++;
|
|
469 }
|
|
470
|
|
471 if ((flags & ATTR_DEST) && (strcmp(ctrl_dest, test_dest) != 0)) {
|
|
472 report_error(ctrl_fname, DEST_KEYWORD, ctrl_dest,
|
|
473 test_dest, prog_fmt);
|
|
474 ret_val++;
|
|
475 }
|
|
476
|
|
477 if ((flags & ATTR_CONTENTS) &&
|
|
478 (strcmp(ctrl_contents, test_contents)) != 0) {
|
|
479 report_error(ctrl_fname, CONTENTS_KEYWORD, ctrl_contents,
|
|
480 test_contents, prog_fmt);
|
|
481 ret_val++;
|
|
482 }
|
|
483
|
|
484 return (ret_val);
|
|
485 }
|
|
486
|
|
487 /*
|
|
488 * Function responsible for reporting errors.
|
|
489 */
|
|
490 static void
|
|
491 report_error(char *fname, char *type, char *ctrl_val, char *test_val,
|
|
492 boolean_t prog_fmt)
|
|
493 {
|
|
494 static char last_fname[PATH_MAX] = "";
|
|
495
|
|
496 if (!prog_fmt) {
|
|
497 /* Verbose mode */
|
|
498 if (strcmp(fname, last_fname) != 0) {
|
|
499 (void) printf("%s:\n", fname);
|
|
500 (void) strlcpy(last_fname, fname, sizeof (last_fname));
|
|
501 }
|
|
502
|
|
503 if (strcmp(type, ADD_KEYWORD) == 0 ||
|
|
504 strcmp(type, DELETE_KEYWORD) == 0)
|
|
505 (void) printf(" %s\n", type);
|
|
506 else
|
|
507 (void) printf(" %s control:%s test:%s\n", type,
|
|
508 ctrl_val, test_val);
|
|
509 } else {
|
|
510 /* Programmatic mode */
|
|
511 if (strcmp(fname, last_fname) != 0) {
|
|
512 /* Ensure a line is not printed for the initial case */
|
|
513 if (strlen(last_fname) != 0)
|
|
514 (void) printf("\n");
|
|
515 (void) strlcpy(last_fname, fname, sizeof (last_fname));
|
|
516 (void) printf("%s ", fname);
|
|
517 }
|
|
518
|
|
519 (void) printf("%s ", type);
|
|
520 if (strcmp(type, ADD_KEYWORD) != 0 &&
|
|
521 strcmp(type, DELETE_KEYWORD) != 0) {
|
|
522 (void) printf("%s ", ctrl_val);
|
|
523 (void) printf("%s ", test_val);
|
|
524 }
|
|
525 }
|
|
526 }
|
|
527
|
|
528 /*
|
|
529 * Function responsible for reading in a line from the manifest.
|
|
530 * Takes in the file ptr and a buffer, parses the buffer and sets the 'line'
|
|
531 * ptr correctly. In the case when the buffer is fully parsed, this function
|
|
532 * reads more data from the file ptr and refills the buffer.
|
|
533 */
|
|
534 static int
|
|
535 read_manifest_line(FILE *fd, char *buf, int buf_size, int start_pos,
|
|
536 char **line, char *fname)
|
|
537 {
|
|
538 int end_pos, len, iscomment = 0, filepos;
|
|
539
|
|
540 /*
|
|
541 * Initialization case: make sure the manifest version is OK
|
|
542 */
|
|
543 if (start_pos == 0) {
|
|
544 end_pos = 0;
|
|
545 buf[0] = '\0';
|
|
546 filepos = ftell(fd);
|
|
547 (void) fread((void *) buf, (size_t)buf_size, (size_t)1, fd);
|
|
548
|
|
549 *line = buf;
|
|
550
|
|
551 if (filepos == 0) {
|
|
552 if (strncmp(buf, MANIFEST_VER,
|
|
553 strlen(MANIFEST_VER)) != 0)
|
|
554 (void) fprintf(stderr, MISSING_VER, fname);
|
|
555 if ((*line[0] == '!') || (*line[0] == '#'))
|
|
556 iscomment++;
|
|
557
|
|
558 while (iscomment) {
|
|
559 while ((buf[end_pos] != '\n') &&
|
|
560 (buf[end_pos] != '\0') &&
|
|
561 (end_pos < buf_size))
|
|
562 end_pos++;
|
|
563
|
|
564 if (end_pos >= buf_size)
|
|
565 return (-1);
|
|
566
|
|
567 end_pos++;
|
|
568 *line = &(buf[end_pos]);
|
|
569 iscomment = 0;
|
|
570 if ((*line[0] == '!') || (*line[0] == '#'))
|
|
571 iscomment++;
|
|
572 }
|
|
573 }
|
|
574
|
|
575 while ((buf[end_pos] != '\n') && (buf[end_pos] != '\0') &&
|
|
576 (end_pos < buf_size))
|
|
577 end_pos++;
|
|
578
|
|
579 if (end_pos < buf_size) {
|
|
580 if (buf[end_pos] == '\n') {
|
|
581 buf[end_pos] = '\0';
|
|
582 return (end_pos);
|
|
583 }
|
|
584
|
|
585 if (buf[end_pos] == '\0')
|
|
586 return (-1);
|
|
587 }
|
|
588
|
|
589 (void) fprintf(stderr, MANIFEST_ERR);
|
|
590 exit(FATAL_EXIT);
|
|
591 }
|
|
592
|
|
593 end_pos = (start_pos+1);
|
|
594 *line = &(buf[end_pos]);
|
|
595
|
|
596 /* Read the buffer until EOL or the buffer is empty */
|
|
597 while ((buf[end_pos] != '\n') && (buf[end_pos] != '\0') &&
|
|
598 (end_pos < buf_size))
|
|
599 end_pos++;
|
|
600
|
|
601 if (end_pos < buf_size) {
|
|
602 /* Found the end of the line, normal exit */
|
|
603 if (buf[end_pos] == '\n') {
|
|
604 buf[end_pos] = '\0';
|
|
605 return (end_pos);
|
|
606 }
|
|
607
|
|
608 /* No more input to read */
|
|
609 if (buf[end_pos] == '\0')
|
|
610 return (-1);
|
|
611 }
|
|
612
|
|
613 /*
|
|
614 * The following code takes the remainder of the buffer and
|
|
615 * puts it at the beginning. The space after the remainder, which
|
|
616 * is now at the beginning, is blanked.
|
|
617 * At this point, read in more data and continue to find the EOL....
|
|
618 */
|
|
619 len = end_pos - (start_pos + 1);
|
|
620 (void) memcpy(buf, &(buf[start_pos+1]), (size_t)len);
|
|
621 (void) memset(&buf[len], '\0', (buf_size - len));
|
|
622 (void) fread((void *) &buf[len], (size_t)(buf_size-len), (size_t)1, fd);
|
|
623 *line = buf;
|
|
624 end_pos = len;
|
|
625
|
|
626 /* Read the buffer until EOL or the buffer is empty */
|
|
627 while ((buf[end_pos] != '\n') && (buf[end_pos] != '\0') &&
|
|
628 (end_pos < buf_size))
|
|
629 end_pos++;
|
|
630
|
|
631 if (end_pos < buf_size) {
|
|
632 /* Found the end of the line, normal exit */
|
|
633 if (buf[end_pos] == '\n') {
|
|
634 buf[end_pos] = '\0';
|
|
635 return (end_pos);
|
|
636 }
|
|
637
|
|
638 /* No more input to read */
|
|
639 if (buf[end_pos] == '\0')
|
|
640 return (-1);
|
|
641 }
|
|
642
|
|
643 (void) fprintf(stderr, MANIFEST_ERR);
|
|
644 exit(FATAL_EXIT);
|
|
645
|
|
646 /* NOTREACHED */
|
|
647 }
|
|
648
|
|
649 static void
|
|
650 init_default_flags(uint_t *flags)
|
|
651 {
|
|
652 /* Default behavior: everything is checked *except* dirmtime */
|
|
653 *flags = ATTR_ALL & ~(ATTR_DIRMTIME);
|
|
654 }
|