ca77a76875cf5b723a1601408c84137c4f8c8b9c
[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 }