From 5fd83771641d15c418f747bd343ba6738d3875f7 Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Sun, 9 May 2021 14:20:58 -0400 Subject: Import macOS userland adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106 --- file_cmds/mtree/mtree.c | 358 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 file_cmds/mtree/mtree.c (limited to 'file_cmds/mtree/mtree.c') diff --git a/file_cmds/mtree/mtree.c b/file_cmds/mtree/mtree.c new file mode 100644 index 0000000..edf0cce --- /dev/null +++ b/file_cmds/mtree/mtree.c @@ -0,0 +1,358 @@ +/*- + * Copyright (c) 1989, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1989, 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ +#endif +#include +__FBSDID("$FreeBSD: src/usr.sbin/mtree/mtree.c,v 1.29 2004/06/04 19:29:28 ru Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "metrics.h" +#include "mtree.h" +#include "extern.h" + +#define SECONDS_IN_A_DAY (60 * 60 * 24) + +int ftsoptions = FTS_PHYSICAL; +int cflag, dflag, eflag, iflag, nflag, qflag, rflag, sflag, uflag, Uflag, wflag, mflag, tflag; +int insert_mod, insert_birth, insert_access, insert_change, insert_parent; +struct timespec ts; +u_int keys; +char fullpath[MAXPATHLEN]; +CFMutableDictionaryRef dict; +char *filepath; + +static void usage(void); +static bool write_plist_to_file(void); + +static void +do_cleanup(void) { + + if (mflag) { + if (dict) + CFRelease(dict); + if (filepath) + free(filepath); + } +} + +int +main(int argc, char *argv[]) +{ + int error = 0; + int ch; + char *dir, *p; + int status; + FILE *spec1, *spec2; + char *timestamp = NULL; + char *timeformat = "%FT%T"; + FILE *file = NULL; + + dir = NULL; + keys = KEYDEFAULT; + init_excludes(); + spec1 = stdin; + spec2 = NULL; + set_metric_start_time(time(NULL)); + + atexit(do_cleanup); + atexit(print_metrics_to_file); + + while ((ch = getopt(argc, argv, "cdef:iK:k:LnPp:qrs:UuwxX:m:F:t:E:")) != -1) + switch((char)ch) { + case 'c': + cflag = 1; + break; + case 'd': + dflag = 1; + break; + case 'e': + eflag = 1; + break; + case 'f': + if (spec1 == stdin) { + spec1 = fopen(optarg, "r"); + if (spec1 == NULL) { + error = errno; + RECORD_FAILURE(88, error); + errc(1, error, "%s", optarg); + } + } else if (spec2 == NULL) { + spec2 = fopen(optarg, "r"); + if (spec2 == NULL) { + error = errno; + RECORD_FAILURE(89, error); + errc(1, error, "%s", optarg); + } + } else { + RECORD_FAILURE(90, WARN_USAGE); + usage(); + } + break; + case 'i': + iflag = 1; + break; + case 'K': + while ((p = strsep(&optarg, " \t,")) != NULL) + if (*p != '\0') + keys |= parsekey(p, NULL); + break; + case 'k': + keys = F_TYPE; + while ((p = strsep(&optarg, " \t,")) != NULL) + if (*p != '\0') + keys |= parsekey(p, NULL); + break; + case 'L': + ftsoptions &= ~FTS_PHYSICAL; + ftsoptions |= FTS_LOGICAL; + break; + case 'n': + nflag = 1; + break; + case 'P': + ftsoptions &= ~FTS_LOGICAL; + ftsoptions |= FTS_PHYSICAL; + break; + case 'p': + dir = optarg; + break; + case 'q': + qflag = 1; + break; + case 'r': + rflag = 1; + break; + case 's': + sflag = 1; + crc_total = (uint32_t)~strtoul(optarg, &p, 0); + if (*p) { + RECORD_FAILURE(91, WARN_USAGE); + errx(1, "illegal seed value -- %s", optarg); + } + break; + case 'U': + Uflag = 1; + uflag = 1; + break; + case 'u': + uflag = 1; + break; + case 'w': + wflag = 1; + break; + case 'x': + ftsoptions |= FTS_XDEV; + break; + case 'X': + read_excludes_file(optarg); + break; + case 'm': + mflag = 1; + filepath = strdup(optarg); + dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + insert_access = insert_mod = insert_birth = insert_change = 0; + break; + case 'F': + timeformat = optarg; + break; + case 't': + timestamp = optarg; + tflag = 1; + break; + case 'E': + if (!strcmp(optarg, "-")) { + file = stdout; + } else { + file = fopen(optarg, "w"); + } + if (file == NULL) { + warnx("Could not open metrics log file %s", optarg); + } else { + set_metrics_file(file); + } + break; + + case '?': + default: + RECORD_FAILURE(92, WARN_USAGE); + usage(); + } + argc -= optind; +// argv += optind; + + if (argc) { + RECORD_FAILURE(93, WARN_USAGE); + usage(); + } + + if (timestamp) { + struct tm t = {}; + char *r = strptime(timestamp, timeformat, &t); + if (r && r[0] == '\0') { + ts.tv_sec = mktime(&t); + if ((ts.tv_sec - time(NULL)) > 30 * SECONDS_IN_A_DAY) { + RECORD_FAILURE(94, WARN_TIME); + errx(1, "Time is more then 30 days in the future"); + } else if (ts.tv_sec < 0) { + RECORD_FAILURE(95, WARN_TIME); + errx(1, "Time is too far in the past"); + } + } else { + RECORD_FAILURE(96, WARN_TIME); + errx(1,"Cannot parse timestamp '%s' using format \"%s\"\n", timestamp, timeformat); + } + } + + if (dir && chdir(dir)) { + error = errno; + RECORD_FAILURE(97, error); + errc(1, error, "%s", dir); + } + + if ((cflag || sflag) && !getwd(fullpath)) { + RECORD_FAILURE(98, errno); + errx(1, "%s", fullpath); + } + + if (dir) { + set_metric_path(dir); + } + + if (cflag) { + cwalk(); + exit(0); + } + if (spec2 != NULL) { + status = mtree_specspec(spec1, spec2); + if (Uflag & (status == MISMATCHEXIT)) { + status = 0; + } else { + RECORD_FAILURE(99, status); + } + } else { + status = mtree_verifyspec(spec1); + if (Uflag & (status == MISMATCHEXIT)) { + status = 0; + } else { + RECORD_FAILURE(100, status); + } + if (mflag && CFDictionaryGetCount(dict)) { + if (!write_plist_to_file()) { + RECORD_FAILURE(101, EIO); + errx(1, "could not write manifest to the file\n"); + } + } + } + exit(status); +} + +static void +usage(void) +{ + (void)fprintf(stderr, +"usage: mtree [-LPUcdeinqruxw] [-f spec] [-f spec] [-K key] [-k key] [-p path] [-s seed]\n" +"\t[-X excludes]\n"); + exit(1); +} + +static bool +write_plist_to_file(void) +{ + if (!dict || !filepath) { + RECORD_FAILURE(102, EINVAL); + return false; + } + + CFIndex bytes_written = 0; + bool status = true; + + CFStringRef file_path_str = CFStringCreateWithCString(kCFAllocatorDefault, (const char *)filepath, kCFStringEncodingUTF8); + + // Create a URL specifying the file to hold the XML data. + CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, + file_path_str, // file path name + kCFURLPOSIXPathStyle, // interpret as POSIX path + false); // is it a directory? + + if (!fileURL) { + CFRelease(file_path_str); + RECORD_FAILURE(103, EINVAL); + return false; + } + + CFWriteStreamRef output_stream = CFWriteStreamCreateWithFile(kCFAllocatorDefault, fileURL); + + if (!output_stream) { + CFRelease(file_path_str); + CFRelease(fileURL); + RECORD_FAILURE(104, EIO); + return false; + } + + if ((status = CFWriteStreamOpen(output_stream))) { + bytes_written = CFPropertyListWrite((CFPropertyListRef)dict, output_stream, kCFPropertyListXMLFormat_v1_0, 0, NULL); + CFWriteStreamClose(output_stream); + } else { + status = false; + RECORD_FAILURE(105, EIO); + goto out; + } + + if (!bytes_written) { + status = false; + RECORD_FAILURE(106, EIO); + } + +out: + CFRelease(output_stream); + CFRelease(fileURL); + CFRelease(file_path_str); + + return status; +} -- cgit v1.2.3-56-ge451