2 * Copyright (c) 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 static const char copyright
[] =
33 "@(#) Copyright (c) 1989, 1990, 1993\n\
34 The Regents of the University of California. All rights reserved.\n";
38 static char sccsid
[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93";
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD: src/usr.sbin/mtree/mtree.c,v 1.29 2004/06/04 19:29:28 ru Exp $");
44 #include <CoreFoundation/CoreFoundation.h>
45 #include <sys/param.h>
57 #define SECONDS_IN_A_DAY (60 * 60 * 24)
59 int ftsoptions
= FTS_PHYSICAL
;
60 int cflag
, dflag
, eflag
, iflag
, nflag
, qflag
, rflag
, sflag
, uflag
, Uflag
, wflag
, mflag
, tflag
;
61 int insert_mod
, insert_birth
, insert_access
, insert_change
, insert_parent
;
64 char fullpath
[MAXPATHLEN
];
65 CFMutableDictionaryRef dict
;
68 static void usage(void);
69 static bool write_plist_to_file(void);
83 main(int argc
, char *argv
[])
90 char *timestamp
= NULL
;
91 char *timeformat
= "%FT%T";
99 set_metric_start_time(time(NULL
));
102 atexit(print_metrics_to_file
);
104 while ((ch
= getopt(argc
, argv
, "cdef:iK:k:LnPp:qrs:UuwxX:m:F:t:E:")) != -1)
116 if (spec1
== stdin
) {
117 spec1
= fopen(optarg
, "r");
120 RECORD_FAILURE(88, error
);
121 errc(1, error
, "%s", optarg
);
123 } else if (spec2
== NULL
) {
124 spec2
= fopen(optarg
, "r");
127 RECORD_FAILURE(89, error
);
128 errc(1, error
, "%s", optarg
);
131 RECORD_FAILURE(90, WARN_USAGE
);
139 while ((p
= strsep(&optarg
, " \t,")) != NULL
)
141 keys
|= parsekey(p
, NULL
);
145 while ((p
= strsep(&optarg
, " \t,")) != NULL
)
147 keys
|= parsekey(p
, NULL
);
150 ftsoptions
&= ~FTS_PHYSICAL
;
151 ftsoptions
|= FTS_LOGICAL
;
157 ftsoptions
&= ~FTS_LOGICAL
;
158 ftsoptions
|= FTS_PHYSICAL
;
171 crc_total
= (uint32_t)~strtoul(optarg
, &p
, 0);
173 RECORD_FAILURE(91, WARN_USAGE
);
174 errx(1, "illegal seed value -- %s", optarg
);
188 ftsoptions
|= FTS_XDEV
;
191 read_excludes_file(optarg
);
195 filepath
= strdup(optarg
);
196 dict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
197 &kCFTypeDictionaryKeyCallBacks
,
198 &kCFTypeDictionaryValueCallBacks
);
199 insert_access
= insert_mod
= insert_birth
= insert_change
= 0;
209 if (!strcmp(optarg
, "-")) {
212 file
= fopen(optarg
, "w");
215 warnx("Could not open metrics log file %s", optarg
);
217 set_metrics_file(file
);
223 RECORD_FAILURE(92, WARN_USAGE
);
230 RECORD_FAILURE(93, WARN_USAGE
);
236 char *r
= strptime(timestamp
, timeformat
, &t
);
237 if (r
&& r
[0] == '\0') {
238 ts
.tv_sec
= mktime(&t
);
239 if ((ts
.tv_sec
- time(NULL
)) > 30 * SECONDS_IN_A_DAY
) {
240 RECORD_FAILURE(94, WARN_TIME
);
241 errx(1, "Time is more then 30 days in the future");
242 } else if (ts
.tv_sec
< 0) {
243 RECORD_FAILURE(95, WARN_TIME
);
244 errx(1, "Time is too far in the past");
247 RECORD_FAILURE(96, WARN_TIME
);
248 errx(1,"Cannot parse timestamp '%s' using format \"%s\"\n", timestamp
, timeformat
);
252 if (dir
&& chdir(dir
)) {
254 RECORD_FAILURE(97, error
);
255 errc(1, error
, "%s", dir
);
258 if ((cflag
|| sflag
) && !getwd(fullpath
)) {
259 RECORD_FAILURE(98, errno
);
260 errx(1, "%s", fullpath
);
264 set_metric_path(dir
);
272 status
= mtree_specspec(spec1
, spec2
);
273 if (Uflag
& (status
== MISMATCHEXIT
)) {
276 RECORD_FAILURE(99, status
);
279 status
= mtree_verifyspec(spec1
);
280 if (Uflag
& (status
== MISMATCHEXIT
)) {
283 RECORD_FAILURE(100, status
);
285 if (mflag
&& CFDictionaryGetCount(dict
)) {
286 if (!write_plist_to_file()) {
287 RECORD_FAILURE(101, EIO
);
288 errx(1, "could not write manifest to the file\n");
298 (void)fprintf(stderr
,
299 "usage: mtree [-LPUcdeinqruxw] [-f spec] [-f spec] [-K key] [-k key] [-p path] [-s seed]\n"
300 "\t[-X excludes]\n");
305 write_plist_to_file(void)
307 if (!dict
|| !filepath
) {
308 RECORD_FAILURE(102, EINVAL
);
312 CFIndex bytes_written
= 0;
315 CFStringRef file_path_str
= CFStringCreateWithCString(kCFAllocatorDefault
, (const char *)filepath
, kCFStringEncodingUTF8
);
317 // Create a URL specifying the file to hold the XML data.
318 CFURLRef fileURL
= CFURLCreateWithFileSystemPath(kCFAllocatorDefault
,
319 file_path_str
, // file path name
320 kCFURLPOSIXPathStyle
, // interpret as POSIX path
321 false); // is it a directory?
324 CFRelease(file_path_str
);
325 RECORD_FAILURE(103, EINVAL
);
329 CFWriteStreamRef output_stream
= CFWriteStreamCreateWithFile(kCFAllocatorDefault
, fileURL
);
331 if (!output_stream
) {
332 CFRelease(file_path_str
);
334 RECORD_FAILURE(104, EIO
);
338 if ((status
= CFWriteStreamOpen(output_stream
))) {
339 bytes_written
= CFPropertyListWrite((CFPropertyListRef
)dict
, output_stream
, kCFPropertyListXMLFormat_v1_0
, 0, NULL
);
340 CFWriteStreamClose(output_stream
);
343 RECORD_FAILURE(105, EIO
);
347 if (!bytes_written
) {
349 RECORD_FAILURE(106, EIO
);
353 CFRelease(output_stream
);
355 CFRelease(file_path_str
);