1/*
2 * Copyright (c) 2005 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 <sys/types.h>
25#include <sys/stat.h>
26#include <dirent.h>
27#include <stdio.h>
28#include <string.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <sysexits.h>
32
33#define FSTYP_PREFIX	"fstyp_"
34#define MAX_PATH_LEN	80
35#define MAX_CMD_LEN	(MAX_PATH_LEN * 2)
36#define NULL_REDIRECTION ">/dev/null 2>&1"
37
38void usage(void);
39int select_fstyp(const struct dirent * dp);
40int test(const char *dir, const struct dirent * dp, const char *dev);
41void dealloc(struct dirent ** dpp, int numElems);
42
43char           *progname;
44
45/*
46 * The fstyp command iterates through the binary directories to look for
47 * commands of the form fstyp_* and runs them, trying to find one that
48 * matches the given device. Once one of the returns success, fstyp
49 * prints out that file system type name and terminates. 1 is returned
50 * if any match is found, and 0 is returned if no match is found.
51 */
52
53int
54main(int argc, char *argv[])
55{
56	/* NULL-terminated list of directories to search for fstyp_* commands */
57	const char     *DIRS[] = {	"/bin/",
58					"/sbin/",
59					"/usr/bin/",
60					"/usr/sbin/",
61					"/usr/local/bin/",
62					"/usr/local/sbin/",
63					NULL};
64
65	int numMatches, i, j, found;
66	struct stat sb;
67	struct dirent **dpp;
68
69	numMatches = 0;
70	i = 0;
71	j = 0;
72	found = 0;
73
74	if ((progname = strrchr(*argv, '/')))
75		++progname;
76	else
77		progname = *argv;
78
79	if (argc != 2) {
80		usage();
81		return EX_USAGE;
82	}
83	if (0 == stat(argv[1], &sb)) {
84		for (i = 0; (!found && (NULL != DIRS[i])); i++) {
85			/*
86			 * scan DIRS[i] for files that start with
87			 * "fstyp_"
88			 */
89			numMatches = scandir(DIRS[i], &dpp, select_fstyp, NULL);
90
91			if (numMatches >= 0) {
92				for (j = 0; (!found && (j < numMatches)); j++) {
93					if (test(DIRS[i], dpp[j], argv[1]) == 1) {
94						puts(dpp[j]->d_name + 6);
95
96						found = 1;
97					}
98				}
99
100				dealloc(dpp, numMatches);
101				dpp = NULL;
102			}
103		}
104	}
105	return found;
106}
107
108int
109select_fstyp(const struct dirent * dp)
110{
111	return ((dp != NULL) &&
112		((dp->d_type == DT_REG) || (dp->d_type == DT_LNK)) &&
113		(dp->d_namlen > strlen(FSTYP_PREFIX)) &&
114		(!strncmp(FSTYP_PREFIX, dp->d_name, strlen(FSTYP_PREFIX))));
115}
116
117/* return dp if successful, else return NULL */
118int
119test(const char *dir, const struct dirent * dp, const char *dev)
120{
121	char cmd[MAX_CMD_LEN + 1] = {0};
122	int status;
123	FILE *fileptr;
124
125	status = 0;
126
127	/* + 1 for white space */
128	if ((strlen(dir) + dp->d_namlen + 1 + strlen(dev) +
129	    strlen(NULL_REDIRECTION)) > MAX_CMD_LEN) {
130		return 0;
131	}
132	snprintf(cmd, sizeof(cmd), "%s%s %s", dir, dp->d_name, dev);
133
134	if ((fileptr = popen(cmd, "r")) != NULL) {
135		status = pclose(fileptr);
136
137		if (WIFEXITED(status)) {
138			if (WEXITSTATUS(status) == 1) {
139				return 1;
140			}
141		}
142	}
143	return 0;
144}
145
146void
147dealloc(struct dirent ** dpp, int numElems)
148{
149	int i;
150
151	for (i = 0; i < numElems; i++) {
152		free(dpp[i]);
153		dpp[i] = NULL;
154	}
155
156	free(dpp);
157
158	return;
159}
160
161
162void
163usage(void)
164{
165	fprintf(stdout, "usage: %s device\n", progname);
166	return;
167}
168