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 }