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