1/*
2 * Copyright (c) 2003-2007 Apple 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 * You can do a pretty grueling self-test with:
25 * find -x /System -print0 | xargs -0 -n 1 ./build/testgetfileid  | grep -v ^Success:
26 */
27
28#define DEBUG 1
29
30#include <libc.h>
31#include <stdint.h>
32#include <inttypes.h>
33#include <bless.h>
34#include <AssertMacros.h>
35
36void usage() {
37    fprintf(stderr, "Usage: %s [ mountpoint cnid | path ]\n", getprogname());
38    exit(1);
39}
40
41int main(int argc, char *argv[]) {
42
43    if(argc < 2 || argc > 3) {
44	usage();
45    }
46
47    if(argc == 2) {
48	char *path = argv[1];
49	int isHFS = 0;
50	struct stat sb;
51	struct statfs sf;
52	uint32_t fileID = 0;
53	char newpath[MAXPATHLEN];
54
55	require_noerr(lstat(path, &sb), cantStat);
56	if(S_ISLNK(sb.st_mode)) {
57	  printf("Success: %s is a symlink\b", path);
58	  return 0;
59	}
60
61	require_noerr(statfs(path, &sf), cantStat);
62	require_noerr(BLIsMountHFS(NULL, path, &isHFS), notHFS);
63	require(isHFS == 1, notHFS);
64
65	require_noerr(BLGetFileID(NULL, path, &fileID), error);
66	require(fileID == sb.st_ino, error);
67
68	require_noerr(BLLookupFileIDOnMount(NULL,
69			   sf.f_mntonname,
70			   fileID,
71			       newpath), error);
72
73	require(strcmp(newpath, path) == 0, cantstrcmp);
74
75	printf("Success: %s\n", newpath);
76
77	return 0;
78
79    error:
80	printf("Error: %s\n", path);
81	 return 1;
82    cantstrcmp:
83	 printf("%s != %s\n", newpath, path);
84	 return 1;
85cantStat:
86	printf("%s: %s\n",path, strerror(errno));
87	return 1;
88notHFS:
89	printf("%s not on an HFS+ filesystem\n", path);
90	return 1;
91    } else if(argc == 3) {
92	char *path = argv[1];
93	int isHFS = 0;
94	struct statfs sf;
95	uint32_t fileID = 0;
96	char newpath[MAXPATHLEN];
97
98	fileID = strtoul(argv[2], NULL, 0);
99	require(fileID > 0, error2);
100
101	require_noerr(statfs(path, &sf), cantStat2);
102	require_noerr(BLIsMountHFS(NULL, path, &isHFS), notHFS2);
103	require(isHFS == 1, notHFS2);
104
105	require_noerr(BLLookupFileIDOnMount(NULL,
106				     sf.f_mntonname,
107				     fileID,
108				     newpath), error2);
109
110	printf("Success: %s\n", newpath);
111
112	return 0;
113
114error2:
115	    return 1;
116cantStat2:
117	    printf("%s: %s\n",path, strerror(errno));
118	return 1;
119notHFS2:
120	    printf("%s not on an HFS+ filesystem\n", path);
121	return 1;
122    }
123
124
125
126    return 0;
127}
128
129