make mountd also work for mmc partitions
[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 #define HFSPLUS_VOL_JOURNALED (1 << 13)
127 #define HFSPLUS_BUF_SIZE 512
128 static int detect_hfsplus(int fd)
129 {
130 int ret = NONE;
131 unsigned short magic;
132 unsigned int journal;
133 unsigned char *buffer = (unsigned char*)malloc(HFSPLUS_BUF_SIZE);
134 if(get_buffer(fd, buffer, 1024, HFSPLUS_BUF_SIZE) != 0)
135 goto out;
136 magic = get_be_short(buffer);
137 journal = get_be_long(buffer + 4) & HFSPLUS_VOL_JOURNALED;
138 if(magic == 0x482B)
139 {
140 if(!journal)
141 ret = HFSPLUS;
142 // else
143 // ret = HFSPLUSJOURNAL;
144 }
145 out:
146 free(buffer);
147 return ret;
148 }
149
150 #define NTFS_BUF_SIZE 512
151 static int detect_ntfs(int fd)
152 {
153 int ret = NONE;
154 unsigned char *buffer = (unsigned char*)malloc(NTFS_BUF_SIZE);
155 if(get_buffer(fd, buffer, 0, NTFS_BUF_SIZE) != 0)
156 goto out;
157 if(!memcmp(buffer + 3, "NTFS ", 8))
158 ret = NTFS;
159 out:
160 free(buffer);
161 return ret;
162 }
163
164 #define EXTENDED_BUF_SIZE 512
165 static int detect_extended(int fd)
166 {
167 int ret = NONE;
168 unsigned char *buffer = (unsigned char*)malloc(MBR_BUF_SIZE);
169 if(get_buffer(fd, buffer, 0, 512) != 0)
170 goto out;
171 if((((buffer[0] & 0xff) == 0xEB) && ((buffer[2] & 0xff) == 0x90)) || ((buffer[0] & 0xff) == 0xE9))
172 goto out;
173 if(((buffer[510] & 0xff) == 0x55) && ((buffer[511] & 0xff) == 0xAA))
174 ret = EXTENDED;
175 out:
176 free(buffer);
177 return ret;
178 }
179
180 dfunc funcs[] = {
181 detect_ext23,
182 detect_fat,
183 detect_ntfs,
184 detect_hfsplus,
185 detect_extended,
186 detect_efi,
187 detect_mbr,
188 };
189
190 int detect_fs(char *device)
191 {
192 int i = 0;
193 int ret = NONE;
194 int fd;
195
196 fd = open(device, O_RDONLY);
197 if(!fd)
198 return NONE;
199
200 while((i < 6) && (ret == NONE))
201 ret = funcs[i++](fd);
202
203 close(fd);
204
205 return ret;
206 }