]> git.cameronkatri.com Git - apple_cmds.git/blob - diskdev_cmds/fstyp.tproj/fstyp_ntfs.c
libtelnet-13
[apple_cmds.git] / diskdev_cmds / fstyp.tproj / fstyp_ntfs.c
1 /*
2 * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/disk.h>
27 #include <fcntl.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <sys/stat.h>
32
33 /* copied from diskdev_cmds/fsck_msdos/dosfs.h */
34 #define DOSBOOTBLOCKSIZE 512
35 #define MAX_SECTOR_SIZE 4096
36
37 #define E_OPENDEV -1
38 #define E_READ -5
39
40 void usage(void);
41 char *rawname(char *name);
42 char *unrawname(char *name);
43 int checkVolHdr(const unsigned char *volhdr);
44 char *blockcheck(char *origname);
45
46 char *progname;
47
48 /*
49 * prefer to use raw device. TODO: suppose block device is valid but
50 * the corresponding raw device is not valid, then we fail. this is
51 * probably no the desired behavior.
52 */
53
54 int
55 main(int argc, char **argv)
56 {
57 unsigned char volhdr[MAX_SECTOR_SIZE] = {0};
58 int fd, retval;
59 char *devname;
60
61 fd = -1;
62 retval = 0;
63
64 if ((progname = strrchr(*argv, '/')))
65 ++progname;
66 else
67 progname = *argv;
68
69 if (argc != 2) {
70 usage();
71 } else {
72 devname = blockcheck(argv[1]);
73
74 if (devname != NULL) {
75 if ((fd = open(devname, O_RDONLY, 0)) < 0) {
76 retval = E_OPENDEV;
77 } else if (read(fd, volhdr, MAX_SECTOR_SIZE) != MAX_SECTOR_SIZE) {
78 retval = E_READ;
79 } else {
80 retval = checkVolHdr(volhdr);
81 }
82
83 if (-1 != fd) {
84 close(fd);
85 fd = -1;
86 }
87 }
88 }
89
90 return retval;
91 }
92
93 void
94 usage(void)
95 {
96 fprintf(stdout, "usage: %s device\n", progname);
97 return;
98 }
99
100 /* copied from diskdev_cmds/fsck_hfs/utilities.c */
101 char *
102 rawname(char *name)
103 {
104 static char rawbuf[32];
105 char *dp;
106
107 if ((dp = strrchr(name, '/')) == 0)
108 return (0);
109 *dp = 0;
110 (void) strlcpy(rawbuf, name, sizeof(rawbuf));
111 *dp = '/';
112 (void) strlcat(rawbuf, "/r", sizeof(rawbuf));
113 (void) strlcat(rawbuf, &dp[1], sizeof(rawbuf));
114
115 return (rawbuf);
116 }
117
118 /* copied from diskdev_cmds/fsck_hfs/utilities.c */
119 char *
120 unrawname(char *name)
121 {
122 char *dp;
123 struct stat stb;
124 size_t dp_len;
125
126 if ((dp = strrchr(name, '/')) == 0)
127 return (name);
128 if (stat(name, &stb) < 0)
129 return (name);
130 if ((stb.st_mode & S_IFMT) != S_IFCHR)
131 return (name);
132 if (dp[1] != 'r')
133 return (name);
134 dp_len = strlen(&dp[2]) + 1;
135 (void)memmove(&dp[1], &dp[2], dp_len);
136
137 return (name);
138 }
139
140 /*
141 * copied from diskdev_cmds/fsck_hfs/utilities.c, and modified:
142 * 1) remove "hotroot"
143 * 2) if error, return NULL
144 * 3) if not a char device, return NULL (effectively, this is treated
145 * as error even if accessing the block device might have been OK)
146 */
147 char *
148 blockcheck(char *origname)
149 {
150 struct stat stblock, stchar;
151 char *newname, *raw;
152 int retried;
153
154 retried = 0;
155 newname = origname;
156 retry:
157 if (stat(newname, &stblock) < 0) {
158 perror(newname);
159 fprintf(stderr, "Can't stat %s\n", newname);
160 return NULL;
161 }
162 if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
163 raw = rawname(newname);
164 if (stat(raw, &stchar) < 0) {
165 perror(raw);
166 fprintf(stderr, "Can't stat %s\n", raw);
167 return NULL;
168 }
169 if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
170 return (raw);
171 } else {
172 fprintf(stderr, "%s is not a character device\n", raw);
173 return NULL;
174 }
175 } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
176 newname = unrawname(newname);
177 retried++;
178 goto retry;
179 }
180 /* not a block or character device */
181 return NULL;
182 }
183
184 /*
185 * (sanity) check the volume header in volhdr
186 *
187 * return 1 if volhdr is a NTFS volhdr, 0 otherwise
188 */
189 int
190 checkVolHdr(const unsigned char *volhdr)
191 {
192 /* NTFS volumes have an OEMid of NTFS followed by four spaces. */
193 const char *ntfs_oemid = "NTFS ";
194 int retval;
195
196 retval = 1;
197
198 /*
199 * Only check the OEMid. This should be sufficiently specific so it
200 * does not match anything else. If it ever does it would be easy to
201 * check more bootsector fields for validity...
202 */
203 if (memcmp(ntfs_oemid, volhdr + 3, 8))
204 retval = 0;
205 return retval;
206 }