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 --- diskdev_cmds/fstyp.tproj/fstyp_ntfs.c | 206 ++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 diskdev_cmds/fstyp.tproj/fstyp_ntfs.c (limited to 'diskdev_cmds/fstyp.tproj/fstyp_ntfs.c') diff --git a/diskdev_cmds/fstyp.tproj/fstyp_ntfs.c b/diskdev_cmds/fstyp.tproj/fstyp_ntfs.c new file mode 100644 index 0000000..88e7568 --- /dev/null +++ b/diskdev_cmds/fstyp.tproj/fstyp_ntfs.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* copied from diskdev_cmds/fsck_msdos/dosfs.h */ +#define DOSBOOTBLOCKSIZE 512 +#define MAX_SECTOR_SIZE 4096 + +#define E_OPENDEV -1 +#define E_READ -5 + +void usage(void); +char *rawname(char *name); +char *unrawname(char *name); +int checkVolHdr(const unsigned char *volhdr); +char *blockcheck(char *origname); + +char *progname; + +/* + * prefer to use raw device. TODO: suppose block device is valid but + * the corresponding raw device is not valid, then we fail. this is + * probably no the desired behavior. + */ + +int +main(int argc, char **argv) +{ + unsigned char volhdr[MAX_SECTOR_SIZE] = {0}; + int fd, retval; + char *devname; + + fd = -1; + retval = 0; + + if ((progname = strrchr(*argv, '/'))) + ++progname; + else + progname = *argv; + + if (argc != 2) { + usage(); + } else { + devname = blockcheck(argv[1]); + + if (devname != NULL) { + if ((fd = open(devname, O_RDONLY, 0)) < 0) { + retval = E_OPENDEV; + } else if (read(fd, volhdr, MAX_SECTOR_SIZE) != MAX_SECTOR_SIZE) { + retval = E_READ; + } else { + retval = checkVolHdr(volhdr); + } + + if (-1 != fd) { + close(fd); + fd = -1; + } + } + } + + return retval; +} + +void +usage(void) +{ + fprintf(stdout, "usage: %s device\n", progname); + return; +} + +/* copied from diskdev_cmds/fsck_hfs/utilities.c */ +char * +rawname(char *name) +{ + static char rawbuf[32]; + char *dp; + + if ((dp = strrchr(name, '/')) == 0) + return (0); + *dp = 0; + (void) strlcpy(rawbuf, name, sizeof(rawbuf)); + *dp = '/'; + (void) strlcat(rawbuf, "/r", sizeof(rawbuf)); + (void) strlcat(rawbuf, &dp[1], sizeof(rawbuf)); + + return (rawbuf); +} + +/* copied from diskdev_cmds/fsck_hfs/utilities.c */ +char * +unrawname(char *name) +{ + char *dp; + struct stat stb; + size_t dp_len; + + if ((dp = strrchr(name, '/')) == 0) + return (name); + if (stat(name, &stb) < 0) + return (name); + if ((stb.st_mode & S_IFMT) != S_IFCHR) + return (name); + if (dp[1] != 'r') + return (name); + dp_len = strlen(&dp[2]) + 1; + (void)memmove(&dp[1], &dp[2], dp_len); + + return (name); +} + +/* + * copied from diskdev_cmds/fsck_hfs/utilities.c, and modified: + * 1) remove "hotroot" + * 2) if error, return NULL + * 3) if not a char device, return NULL (effectively, this is treated + * as error even if accessing the block device might have been OK) + */ +char * +blockcheck(char *origname) +{ + struct stat stblock, stchar; + char *newname, *raw; + int retried; + + retried = 0; + newname = origname; +retry: + if (stat(newname, &stblock) < 0) { + perror(newname); + fprintf(stderr, "Can't stat %s\n", newname); + return NULL; + } + if ((stblock.st_mode & S_IFMT) == S_IFBLK) { + raw = rawname(newname); + if (stat(raw, &stchar) < 0) { + perror(raw); + fprintf(stderr, "Can't stat %s\n", raw); + return NULL; + } + if ((stchar.st_mode & S_IFMT) == S_IFCHR) { + return (raw); + } else { + fprintf(stderr, "%s is not a character device\n", raw); + return NULL; + } + } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { + newname = unrawname(newname); + retried++; + goto retry; + } + /* not a block or character device */ + return NULL; +} + +/* + * (sanity) check the volume header in volhdr + * + * return 1 if volhdr is a NTFS volhdr, 0 otherwise + */ +int +checkVolHdr(const unsigned char *volhdr) +{ + /* NTFS volumes have an OEMid of NTFS followed by four spaces. */ + const char *ntfs_oemid = "NTFS "; + int retval; + + retval = 1; + + /* + * Only check the OEMid. This should be sufficiently specific so it + * does not match anything else. If it ever does it would be easy to + * check more bootsector fields for validity... + */ + if (memcmp(ntfs_oemid, volhdr + 3, 8)) + retval = 0; + return retval; +} -- cgit v1.2.3-56-ge451