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
, xflag
;
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:S")) != -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
);
225 RECORD_FAILURE(92, WARN_USAGE
);
232 RECORD_FAILURE(93, WARN_USAGE
);
238 char *r
= strptime(timestamp
, timeformat
, &t
);
239 if (r
&& r
[0] == '\0') {
240 ts
.tv_sec
= mktime(&t
);
241 if ((ts
.tv_sec
- time(NULL
)) > 30 * SECONDS_IN_A_DAY
) {
242 RECORD_FAILURE(94, WARN_TIME
);
243 errx(1, "Time is more then 30 days in the future");
244 } else if (ts
.tv_sec
< 0) {
245 RECORD_FAILURE(95, WARN_TIME
);
246 errx(1, "Time is too far in the past");
249 RECORD_FAILURE(96, WARN_TIME
);
250 errx(1,"Cannot parse timestamp '%s' using format \"%s\"\n", timestamp
, timeformat
);
254 if (dir
&& chdir(dir
)) {
256 RECORD_FAILURE(97, error
);
257 errc(1, error
, "%s", dir
);
260 if ((cflag
|| sflag
) && !getwd(fullpath
)) {
261 RECORD_FAILURE(98, errno
);
262 errx(1, "%s", fullpath
);
266 set_metric_path(dir
);
274 status
= mtree_specspec(spec1
, spec2
);
275 if (Uflag
& (status
== MISMATCHEXIT
)) {
278 RECORD_FAILURE(99, status
);
281 status
= mtree_verifyspec(spec1
);
282 if (Uflag
& (status
== MISMATCHEXIT
)) {
285 RECORD_FAILURE(100, status
);
287 if (mflag
&& CFDictionaryGetCount(dict
)) {
288 if (!write_plist_to_file()) {
289 RECORD_FAILURE(101, EIO
);
290 errx(1, "could not write manifest to the file\n");
300 (void)fprintf(stderr
,
301 "usage: mtree [-LPUScdeinqruxw] [-f spec] [-K key] [-k key] [-p path] [-s seed] [-m xml dictionary] [-t timestamp]\n"
302 "\t[-X excludes]\n");
307 write_plist_to_file(void)
309 if (!dict
|| !filepath
) {
310 RECORD_FAILURE(102, EINVAL
);
314 CFIndex bytes_written
= 0;
317 CFStringRef file_path_str
= CFStringCreateWithCString(kCFAllocatorDefault
, (const char *)filepath
, kCFStringEncodingUTF8
);
319 // Create a URL specifying the file to hold the XML data.
320 CFURLRef fileURL
= CFURLCreateWithFileSystemPath(kCFAllocatorDefault
,
321 file_path_str
, // file path name
322 kCFURLPOSIXPathStyle
, // interpret as POSIX path
323 false); // is it a directory?
326 CFRelease(file_path_str
);
327 RECORD_FAILURE(103, EINVAL
);
331 CFWriteStreamRef output_stream
= CFWriteStreamCreateWithFile(kCFAllocatorDefault
, fileURL
);
333 if (!output_stream
) {
334 CFRelease(file_path_str
);
336 RECORD_FAILURE(104, EIO
);
340 if ((status
= CFWriteStreamOpen(output_stream
))) {
341 bytes_written
= CFPropertyListWrite((CFPropertyListRef
)dict
, output_stream
, kCFPropertyListXMLFormat_v1_0
, 0, NULL
);
342 CFWriteStreamClose(output_stream
);
345 RECORD_FAILURE(105, EIO
);
349 if (!bytes_written
) {
351 RECORD_FAILURE(106, EIO
);
355 CFRelease(output_stream
);
357 CFRelease(file_path_str
);