hfs+ journal partition support as read only
[project/mountd.git] / fs.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8
9 #include "include/fs.h"
10
11 typedef int (*dfunc)(int);
12
13 static unsigned short
14 get_le_short(void *from)
15 {
16 unsigned char *p = from;
17 return ((unsigned short)(p[1]) << 8) +
18 (unsigned short)p[0];
19 }
20
21 static unsigned int get_le_long(void *from)
22 {
23 unsigned char *p = from;
24 return ((unsigned int)(p[3]) << 24) +
25 ((unsigned int)(p[2]) << 16) +
26 ((unsigned int)(p[1]) << 8) +
27 (unsigned int)p[0];
28 }
29
30 static unsigned short get_be_short(void *from)
31 {
32 unsigned char *p = from;
33 return ((unsigned short)(p[0]) << 8) +
34 (unsigned short)p[1];
35 }
36
37 static unsigned int get_be_long(void *from)
38 {
39 unsigned char *p = from;
40 return ((unsigned int)(p[0]) << 24) +
41 ((unsigned int)(p[1]) << 16) +
42 ((unsigned int)(p[2]) << 8) +
43 (unsigned int)p[3];
44 }
45
46 static int get_buffer(int fd, unsigned char *b, int offset, int len)
47 {
48 if(lseek(fd, offset, SEEK_SET) != offset)
49 return -1;
50 if(read(fd, b, len) != len)
51 return -1;
52 return 0;
53 }
54
55 #define MBR_BUF_SIZE 512
56 static int detect_mbr(int fd)
57 {
58 int ret = NONE;
59 unsigned char *buffer = (unsigned char*)malloc(MBR_BUF_SIZE);
60 if(get_buffer(fd, buffer, 0, MBR_BUF_SIZE) != 0)
61 goto out;
62 if((buffer[510] == 0x55) && (buffer[511] == 0xAA))
63 ret = MBR;
64 out:
65 free(buffer);
66 return ret;
67 }
68
69 #define EFI_BUF_OFFSET 512
70 #define EFI_BUF_SIZE 512
71 static int detect_efi(int fd)
72 {
73 int ret = NONE;
74 unsigned char *buffer = (unsigned char*)malloc(EFI_BUF_SIZE);
75 if(get_buffer(fd, buffer, EFI_BUF_OFFSET, EFI_BUF_SIZE) != 0)
76 goto out;
77 if(!memcmp(buffer, "EFI PART", 8))
78 ret = EFI;
79 out:
80 free(buffer);
81 return ret;
82 }
83
84 #define EXT2_BUF_SIZE 1024
85 static int detect_ext23(int fd)
86 {
87 int ret = NONE;
88 unsigned char *buffer = (unsigned char*)malloc(EXT2_BUF_SIZE);
89 if(get_buffer(fd, buffer, 1024, EXT2_BUF_SIZE) != 0)
90 goto out;
91 if(get_le_short(buffer + 56) == 0xEF53)
92 {
93 if(get_le_long(buffer + 92) & 0x0004)
94 {
95 if ((get_le_long(buffer + 96) < 0x0000040)
96 && (get_le_long(buffer + 100) < 0x0000008))
97 ret = EXT3;
98 else
99 ret = EXT4;
100 }
101 else
102 ret = EXT2;
103 }
104 out:
105 free(buffer);
106 return ret;
107 }
108
109 #define FAT_BUF_SIZE 512
110 static int detect_fat(int fd)
111 {
112 int ret = NONE;
113 unsigned char *buffer = (unsigned char*)malloc(FAT_BUF_SIZE);
114 if(get_buffer(fd, buffer, 0, FAT_BUF_SIZE) != 0)
115 goto out;
116
117 if (((((buffer[0] & 0xff) == 0xEB) && ((buffer[2] & 0xff) == 0x90)) || ((buffer[0] & 0xff) == 0xE9))
118 && ((buffer[510] & 0xff) == 0x55) /*&& ((buffer[511] & 0xff == 0xAA))*/
119 && (memcmp(buffer + 3, "NTFS ", 8)))
120 ret = FAT;
121 out:
122 free(buffer);
123 return ret;
124 }
125
126 static int detect_exfat(int fd)
127 {
128 int ret = NONE;
129 unsigned char *buffer = (unsigned char*)malloc(FAT_BUF_SIZE);
130 if(get_buffer(fd, buffer, 0, FAT_BUF_SIZE) != 0)
131 goto out;
132
133 if (!memcmp(buffer + 3, "EXFAT ", 7))
134 ret = EXFAT;
135 out:
136 free(buffer);
137 return ret;
138 }
139
140 #define HFSPLUS_VOL_JOURNALED (1 << 13)
141 #define HFSPLUS_BUF_SIZE 512
142 static int detect_hfsplus(int fd)
143 {
144 int ret = NONE;
145 unsigned short magic;
146 unsigned int journal;
147 unsigned char *buffer = (unsigned char*)malloc(HFSPLUS_BUF_SIZE);
148 if(get_buffer(fd, buffer, 1024, HFSPLUS_BUF_SIZE) != 0)
149 goto out;
150 magic = get_be_short(buffer);
151 journal = get_be_long(buffer + 4) & HFSPLUS_VOL_JOURNALED;
152 if(magic == 0x482B)
153 {
154 if(!journal)
155 ret = HFSPLUS;
156 else
157 ret = HFSPLUSJOURNAL;
158 }
159 out:
160 free(buffer);
161 return ret;
162 }
163
164 #define NTFS_BUF_SIZE 512
165 static int detect_ntfs(int fd)
166 {
167 int ret = NONE;
168 unsigned char *buffer = (unsigned char*)malloc(NTFS_BUF_SIZE);
169 if(get_buffer(fd, buffer, 0, NTFS_BUF_SIZE) != 0)
170 goto out;
171 if(!memcmp(buffer + 3, "NTFS ", 8))
172 ret = NTFS;
173 out:
174 free(buffer);
175 return ret;
176 }
177
178 #define EXTENDED_BUF_SIZE 512
179 static int detect_extended(int fd)
180 {
181 int ret = NONE;
182 unsigned char *buffer = (unsigned char*)malloc(MBR_BUF_SIZE);
183 if(get_buffer(fd, buffer, 0, 512) != 0)
184 goto out;
185 if((((buffer[0] & 0xff) == 0xEB) && ((buffer[2] & 0xff) == 0x90)) || ((buffer[0] & 0xff) == 0xE9))
186 goto out;
187 if(((buffer[510] & 0xff) == 0x55) && ((buffer[511] & 0xff) == 0xAA))
188 ret = EXTENDED;
189 out:
190 free(buffer);
191 return ret;
192 }
193
194 dfunc funcs[] = {
195 detect_ext23,
196 detect_exfat,
197 detect_fat,
198 detect_ntfs,
199 detect_hfsplus,
200 detect_extended,
201 detect_efi,
202 detect_mbr,
203 };
204
205 int detect_fs(char *device)
206 {
207 int i = 0;
208 int ret = NONE;
209 int fd;
210
211 fd = open(device, O_RDONLY);
212 if(!fd)
213 return NONE;
214
215 while((i < 6) && (ret == NONE))
216 ret = funcs[i++](fd);
217
218 close(fd);
219
220 return ret;
221 }