-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathefs.h
439 lines (380 loc) · 10.8 KB
/
efs.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
#pragma once
#include <dirent.h>
#include <time.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
#define BLKSIZ 512
#define EFS_BLK_SB (1)
#define EFS_BLK_ROOTINO (2)
#define EFS_OLDMAGIC 0x00072959L
#define EFS_NEWMAGIC 0x0007295AL
#define IS_EFS_OLDMAGIC(x) (x == EFS_OLDMAGIC)
#define IS_EFS_NEWMAGIC(x) (x == EFS_NEWMAGIC)
#define IS_EFS_MAGIC(x) (IS_EFS_OLDMAGIC(x) || IS_EFS_NEWMAGIC(x))
#define EFS_MAXLBSIZE
#define EFS_DIRECTEXTENTS 12
/* #define EFS_MAXINDIRBBS 64 */
#define EFS_MAXINDIRBBS 128
#define EFS_MAXEXTENTS 32767
#define EFS_INODESPERPAGE (NBPC / sizeof(struct efs_dinode))
#define EFS_MAXEXTENTLEN (256 - 8)
#define EFS_EFSINOSHIFT 7
#define IFMT 0170000
#define IFIFO 0010000
#define IFCHR 0020000
#define IFDIR 0040000
#define IFBLK 0060000
#define IFREG 0100000
#define IFLNK 0120000
#define IFSOCK 0140000
#define ISMT 07000
#define ISUID 04000
#define ISGID 02000
#define ISVTX 01000
#define EFS_DIRBSHIFT 9
#define EFS_DIRBSIZE (1<<EFS_DIRBSHIFT)
#define EFS_DIRBMASK (EFS_DIRBSIZE-1)
#define EFS_DENTSIZE (sizeof(struct efs_dent) - 3 + 1)
#define EFS_MAX_NAME 255
#define EFS_DIRBLK_HEADERSIZE 4
#define EFS_DIRBLK_MAGIC 0xbeef
/*
* Locations of the efs superblock, bitmap and root inode.
*/
#define EFS_SUPERBB (1) /* bb # of the superblock */
#define EFS_BITMAPBB (2) /* bb of the bitmap, pre 3.3*/
#define EFS_SUPERBOFF BBTOB(EFS_SUPERBB) /* superblock byte offset */
#define EFS_BITMAPBOFF BBTOB(EFS_BITMAPBB) /* bitmap byte offset */
#define EFS_ROOTINO ((efs_ino_t)2) /* where else... */
/*
* Inode parameters.
*/
/* number of inodes per bb */
#define BBSHIFT 9
#define BBSIZE (1<<BBSHIFT)
#undef BBMASK
#define BBMASK (BBSIZE - 1)
#define EFS_INOPBB (1 << EFS_INOPBBSHIFT)
#define EFS_INOPBBSHIFT (BBSHIFT - EFS_EFSINOSHIFT)
#define EFS_INOPBBMASK (EFS_INOPBB - 1)
/*
* Compute the number of inodes-per-cylinder-group (IPCG) and the number
* of inodes-per-basic-block (INOPBB).
*/
#define EFS_COMPUTE_IPCG(fs) \
((short) ((fs)->fs_cgisize << EFS_INOPBBSHIFT))
/*
* Layout macros. These macro provide easy access to the layout by
* translating between sectors, basic blocks, and inode numbers.
* WARNING: The macro EFS_SETUP_SUPERB must be executed before most
* of these macros!
*/
/* inode number to bb, relative to cylinder group */
#define EFS_ITOCGBB(fs, i) \
((size_t) (((i) >> EFS_INOPBBSHIFT) % (fs)->fs_cgisize))
/* inode number to offset from bb base */
#define EFS_ITOO(fs, i) \
((short) ((i) & EFS_INOPBBMASK))
/* inode number to cylinder group */
#define EFS_ITOCG(fs, i) \
((short) ((i) / EFS_COMPUTE_IPCG(fs)))
/* inode number to cylinder group inode number offset */
#define EFS_ITOCGOFF(fs, i) \
((short) ((i) % EFS_COMPUTE_IPCG(fs)))
/* inode number to disk bb number */
#define EFS_ITOBB(fs, i) \
((size_t) ((fs)->fs_firstcg + \
(EFS_ITOCG(fs, i) * (fs)->fs_cgfsize) + \
EFS_ITOCGBB(fs, i)))
/* bb to cylinder group number */
#define EFS_BBTOCG(fs, bb) \
((short) ((bb - (fs)->fs_firstcg) / (fs)->fs_cgfsize))
/* cylinder group number to disk bb of base of cg */
#define EFS_CGIMIN(fs, cg) \
((size_t) ((fs)->fs_firstcg + (cg) * (fs)->fs_cgfsize))
/* inode number to base inode number in its chunk */
#define EFS_ITOCHUNKI(fs, cg, inum) \
(((((inum) - (cg)->cg_firsti) / (fs)->fs_inopchunk) * \
(fs)->fs_inopchunk) + (cg)->cg_firsti)
#define VDNAMESIZE 8
#define VHMAGIC 0x0be5a941
#define NPARTAB 16
#define NVDIR 15
#define BFNAMESIZE 16
#define NPTYPES 16
#define BLKSIZ 512
typedef struct _fileslice_s {
FILE *f;
fpos_t base;
fpos_t cur;
} fileslice_t;
enum partition_type_e {
PT_VOLHDR = 0,
PT_BSD = 4,
PT_SYSV = 5,
PT_VOLUME = 6,
PT_EFS = 7,
PT_XFS = 10
};
struct dvh_dp_s {
uint8_t dp_skew;
uint8_t dp_gap1;
uint8_t dp_gap2;
uint8_t dp_spares_cyl;
uint16_t dp_cyls;
uint16_t dp_shd0;
uint16_t dp_trks0;
uint8_t dp_ctq_depth;
uint8_t dp_cylshi;
uint16_t dp_unused;
uint16_t dp_secs;
uint16_t dp_secbytes;
uint16_t dp_interleave;
int32_t dp_flags;
int32_t dp_datarate;
int32_t dp_nretries;
int32_t dp_mspw;
uint16_t dp_xgap1;
uint16_t dp_xsync;
uint16_t dp_xrdly;
uint16_t dp_xgap2;
uint16_t dp_xrgate;
uint16_t dp_xwcont;
} __attribute__((packed));
struct dvh_vd_s {
char vd_name[VDNAMESIZE];
int32_t vd_lbn;
int32_t vd_nbytes;
} __attribute__((packed));
struct dvh_pt_s {
int32_t pt_nblks;
int32_t pt_firstlbn;
int32_t pt_type;
} __attribute__((packed));
struct dvh_s {
uint32_t vh_magic;
uint16_t vh_rootpt;
uint16_t vh_swappt;
char vh_bootfile[BFNAMESIZE];
struct dvh_dp_s vh_dp;
struct dvh_vd_s vh_pd[NVDIR];
struct dvh_pt_s vh_pt[NPARTAB];
int32_t vh_csum;
int32_t vh_fill;
} __attribute__((packed));
typedef struct dvh_ctx {
FILE *f;
struct dvh_s dvh;
} dvh_t;
typedef uint32_t efs_ino_t;
struct efs_sb {
int32_t fs_size;
int32_t fs_firstcg;
int32_t fs_cgfsize;
int16_t fs_cgisize;
int16_t fs_sectors;
int16_t fs_heads;
int16_t fs_ncg;
int16_t fs_dirty;
int16_t __pad;
int32_t fs_time;
int32_t fs_magic;
char fs_fname[6];
char fs_fpack[6];
int32_t fs_bmsize;
int32_t fs_tfree;
int32_t fs_tinode;
int32_t fs_bmblock;
int32_t fs_replsb;
int32_t fs_lastialloc;
char fs_spare[20];
int32_t fs_checksum;
/* followed by a bunch of in-memory-only fields */
char __pad2[BLKSIZ-92];
} __attribute__((packed));
struct efs_extent {
uint32_t ex_magic:8,
ex_bn:24,
ex_length:8,
ex_offset:24;
/*
uint8_t ex_magic;
uint8_t ex_bn[3];
uint8_t ex_length;
uint8_t ex_offset[3];
*/
} __attribute__((packed));
struct efs_edevs {
uint16_t odev;
uint32_t ndev;
} __attribute__((packed));
struct efs_dinode {
uint16_t di_mode;
int16_t di_nlink;
uint16_t di_uid;
uint16_t di_gid;
int32_t di_size;
int32_t di_atime;
int32_t di_mtime;
int32_t di_ctime;
uint32_t di_gen;
int16_t di_numextents;
uint8_t di_version;
uint8_t di_spare;
union di_addr {
struct efs_extent di_extents[EFS_DIRECTEXTENTS];
struct efs_edevs di_dev;
} di_u;
} __attribute__((packed));
struct efs_dent {
uint32_t l;
uint8_t d_namelen;
char d_name[0];
} __attribute__((packed));
struct efs_dirblk {
uint16_t magic;
uint8_t firstused;
uint8_t slots;
uint8_t space[EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE];
} __attribute__((packed));
struct efs_sb efstoh (struct efs_sb efs);
struct efs_dinode efs_dinodetoh(struct efs_dinode inode);
enum efs_fstype {
EFS_FSTYPE_NONE = 0,
EFS_FSTYPE_EFS,
EFS_FSTYPE_VH
};
typedef struct efs_ctx {
dvh_t *dvh;
fileslice_t *fs;
struct efs_sb sb;
size_t nblks;
efs_ino_t ipcg;
} efs_t;
struct efs_dirent {
efs_ino_t d_ino;
char d_name[EFS_MAX_NAME + 1];
};
typedef struct efs_dir {
/*
* readdir() returns a pointer to a dirent.
* XPG3 says that the data at the pointer can be overwritten
* by successive calls to readdir() on the same directory.
* Therefore, define a dirent here, and return a pointer to
* it for each readdir() call.
*/
struct efs_dirent *dirent;
/* private */
struct efs_dirent *_dirent_memobj;
efs_ino_t ino;
} efs_dir_t;
typedef struct efs_file {
struct efs_dinode dinode;
unsigned numextents;
struct efs_extent *exs;
efs_t *ctx;
efs_ino_t ino;
unsigned pos;
unsigned nbytes;
bool eof;
bool error;
uint8_t blockbuf[BLKSIZ];
int blocknum; /* set to -1 if blockbuf is not filled */
} efs_file_t;
struct efs_stat {
efs_ino_t st_ino;
uint16_t st_mode;
int16_t st_nlink;
uint16_t st_uid;
uint16_t st_gid;
int32_t st_size;
uint16_t st_major;
uint16_t st_minor;
struct timespec st_atimespec;
struct timespec st_mtimespec;
struct timespec st_ctimespec;
};
typedef enum {
EFS_ERR_OK = 0,
EFS_ERR_INVAL = 100,
EFS_ERR_NOENT,
EFS_ERR_NOMEM,
EFS_ERR_READFAIL,
EFS_ERR_NOPAR,
EFS_ERR_NOVH,
EFS_ERR_BADVH,
EFS_ERR_SBMAGIC,
EFS_ERR_PARTYPE,
EFS_ERR_BADPAR,
EFS_ERR_IS_BSD,
EFS_ERR_IS_ISO9660,
EFS_ERR_IS_XFS
} efs_err_t;
struct qent_s {
struct qent_s *next;
struct qent_s *prev;
char *path;
};
struct queue_s {
struct qent_s *head;
struct qent_s *tail;
};
typedef struct queue_s* queue_t;
extern efs_err_t dvh_open(dvh_t **ctx, const char *filename);
extern efs_err_t dvh_close(dvh_t *ctx);
extern fileslice_t *dvh_getParSlice(dvh_t *ctx, int parNum);
extern struct dvh_pt_s dvh_getParInfo(dvh_t *ctx, int parNum);
extern struct dvh_vd_s dvh_getFileInfo(dvh_t *ctx, int fileNum);
extern void *dvh_readFile(dvh_t *ctx, int fileNum);
extern const char *dvh_getNameForType(unsigned parType);
extern fileslice_t *fsopen(FILE *f, size_t base, size_t size);
extern int fsclose(fileslice_t *fs);
extern int fsseek(fileslice_t *fs, long offset, int whence);
extern void fsrewind(fileslice_t *fs);
extern size_t fsread(void *ptr, size_t size, size_t nmemb, fileslice_t *fs);
extern queue_t queue_init(void);
extern void queue_free(queue_t q);
extern int queue_add_tail(queue_t q, char *path);
extern int queue_add_head(queue_t q, char *path);
extern int queue_add_queue_head(queue_t dst, queue_t src);
extern struct qent_s *queue_dequeue(queue_t q);
extern const char *efs_strerror(efs_err_t e);
extern void vwarnefs(efs_err_t e, const char *fmt, va_list args);
extern void verrefs(int eval, efs_err_t e, const char *fmt, va_list args);
extern void warnefs(efs_err_t e, const char *fmt, ...);
extern void errefs(int eval, efs_err_t e, const char *fmt, ...);
extern efs_file_t *efs_fopen(efs_t *ctx, const char *path);
extern int efs_fclose(efs_file_t *file);
extern size_t efs_fread(void *ptr, size_t size, size_t nmemb, efs_file_t *file);
extern int efs_fseek(efs_file_t *file, long offset, int whence);
extern long efs_ftell(efs_file_t *file);
extern void efs_rewind(efs_file_t *file);
extern void efs_clearerr(efs_file_t *file);
extern int efs_feof(efs_file_t *file);
extern int efs_ferror(efs_file_t *file);
extern int efs_stat(efs_t *ctx, const char *pathname, struct efs_stat *statbuf);
extern int efs_stati(efs_t *ctx, efs_ino_t ino, struct efs_stat *statbuf);
extern int efs_fstat(efs_file_t *file, struct efs_stat *statbuf);
extern efs_ino_t efs_find_entry(efs_t *efs, const char *name);
extern efs_dir_t *efs_opendir(efs_t *efs, const char *dirname);
extern int efs_closedir(efs_dir_t *dirp);
extern struct efs_dirent *efs_readdir(efs_dir_t *dirp);
extern void efs_rewinddir(efs_dir_t *dirp);
extern efs_err_t efs_get_blocks(efs_t *ctx, void *buf, size_t firstlbn, size_t nblks);
extern efs_err_t efs_open(efs_t **ctx, fileslice_t *f);
extern void efs_close(efs_t *ctx);
extern struct efs_dinode efs_get_inode(efs_t *ctx, unsigned ino);
extern efs_err_t efs_easy_open(efs_t **ctx, const char *filename);
extern efs_ino_t efs_namei(efs_t *ctx, const char *name);
extern struct efs_dirent *_efs_read_dirblks(efs_t *ctx, efs_ino_t ino);
extern uint32_t efs_extent_get_bn(struct efs_extent extent);
extern uint32_t efs_extent_get_offset(struct efs_extent extent);
extern char *mkpath(char *path, char *name);
extern int efs_nftw(
efs_t *efs,
const char *dirpath,
int (*fn)(const char *fpath, const struct efs_stat *sb)
);