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
|
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*#define HPFS_DEBUG 10*/
typedef u_int32_t lsn_t; /* Logical Sector Number */
typedef struct {
lsn_t lsn1;
lsn_t lsn2;
} rsp_t; /* Redundant Sector Pointer */
typedef struct {
u_int32_t cnt;
lsn_t lsn;
} sptr_t; /* Storage Pointer */
#define SUBLOCK 0x10
#define SUSIZE DEV_BSIZE
#define SPBLOCK 0x11
#define SPSIZE DEV_BSIZE
#define BMSIZE (4 * DEV_BSIZE)
#define HPFS_MAXFILENAME 255
#define SU_MAGIC ((u_int64_t)0xFA53E9C5F995E849)
struct sublock {
u_int64_t su_magic;
u_int8_t su_hpfsver;
u_int8_t su_fnctver;
u_int16_t unused;
lsn_t su_rootfno; /* Root Fnode */
u_int32_t su_btotal; /* Total blocks */
u_int32_t su_badbtotal; /* Bad Sectors total */
rsp_t su_bitmap;
rsp_t su_badbl;
u_long su_chkdskdate;
u_long su_dskoptdate;
u_int32_t su_dbbsz; /* Sectors in DirBlock Band */
lsn_t su_dbbstart;
lsn_t su_dbbend;
lsn_t su_dbbbitmap;
char su_volname[0x20];
lsn_t su_uidt; /* Ptr to User ID Table (8 sect) */
};
#define SP_MAGIC ((u_int64_t)0xFA5229C5F9911849)
#define SP_DIRTY 0x0001
#define SP_SPDBINUSE 0x0002
#define SP_HFINUSE 0x0004
#define SP_BADSECT 0x0008
#define SP_BADBMBL 0x0010
#define SP_FASTFRMT 0x0020
#define SP_OLDHPFS 0x0080
#define SP_IDASD 0x0100
#define SP_RDASD 0x0200
#define SP_DASD 0x0400
#define SP_MMACTIVE 0x0800
#define SP_DCEACLS 0x1000
#define SP_DSADDIRTY 0x2000
struct spblock {
u_int64_t sp_magic;
u_int16_t sp_flag;
u_int8_t sp_mmcontf;
u_int8_t unused;
lsn_t sp_hf; /* HotFix list */
u_int32_t sp_hfinuse; /* HotFixes in use */
u_int32_t sp_hfavail; /* HotFixes available */
u_int32_t sp_spdbavail; /* Spare DirBlocks available */
u_int32_t sp_spdbmax; /* Spare DirBlocks maximum */
lsn_t sp_cpi;
u_int32_t sp_cpinum;
u_int32_t sp_suchecksum;
u_int32_t sp_spchecksum;
u_int8_t reserved[0x3C];
lsn_t sp_spdb[0x65];
};
#define DE_SPECIAL 0x0001
#define DE_ACL 0x0002
#define DE_DOWN 0x0004
#define DE_END 0x0008
#define DE_EALIST 0x0010
#define DE_EPERM 0x0020
#define DE_EXPLACL 0x0040
#define DE_NEEDEA 0x0080
#define DE_RONLY 0x0100
#define DE_HIDDEN 0x0200
#define DE_SYSTEM 0x0400
#define DE_VOLLABEL 0x0800
#define DE_DIR 0x1000
#define DE_ARCHIV 0x2000
#define DE_DOWNLSN(dep) (*(lsn_t *)((caddr_t)(dep) + (dep)->de_reclen - sizeof(lsn_t)))
#define DE_NEXTDE(dep) ((struct hpfsdirent *)((caddr_t)(dep) + (dep)->de_reclen))
typedef struct hpfsdirent {
u_int16_t de_reclen;
u_int16_t de_flag;
lsn_t de_fnode;
u_long de_mtime;
u_int32_t de_size;
u_long de_atime;
u_long de_ctime;
u_int32_t de_ealen;
u_int8_t de_flexflag;
u_int8_t de_cpid;
u_int8_t de_namelen;
char de_name[1];
/* ... de_flex; */
/* lsn_t de_down; */
} hpfsdirent_t;
#define D_BSIZE (DEV_BSIZE*4)
#define D_MAGIC 0x77E40AAE
#define D_DIRENT(dbp) ((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t)))
#define D_DE(dbp, deoff) ((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t) + (deoff)))
typedef struct dirblk {
u_int32_t d_magic;
u_int32_t d_freeoff; /* Offset of first free byte */
u_int32_t d_chcnt; /* Change count */
lsn_t d_parent;
lsn_t d_self;
} dirblk_t;
/*
* Allocation Block (ALBLK)
*/
#define AB_HBOFFEO 0x01
#define AB_FNPARENT 0x20
#define AB_SUGGBSCH 0x40
#define AB_NODES 0x80
#define AB_ALLEAF(abp) ((alleaf_t *)((caddr_t)(abp) + sizeof(alblk_t)))
#define AB_ALNODE(abp) ((alnode_t *)((caddr_t)(abp) + sizeof(alblk_t)))
#define AB_FREEALP(abp) ((alleaf_t *)((caddr_t)(abp) + (abp)->ab_freeoff))
#define AB_FREEANP(abp) ((alnode_t *)((caddr_t)(abp) + (abp)->ab_freeoff))
#define AB_LASTALP(abp) (AB_ALLEAF(abp) + (abp)->ab_busycnt - 1)
#define AB_LASTANP(abp) (AB_ALNODE(abp) + (abp)->ab_busycnt - 1)
#define AB_ADDNREC(abp, sz, n) { \
(abp)->ab_busycnt += (n); \
(abp)->ab_freecnt -= (n); \
(abp)->ab_freeoff += (n) * (sz); \
}
#define AB_RMNREC(abp, sz, n) { \
(abp)->ab_busycnt -= (n); \
(abp)->ab_freecnt += (n); \
(abp)->ab_freeoff -= (n) * (sz);\
}
#define AB_ADDAL(abp) AB_ADDNREC(abp,sizeof(alleaf_t), 1)
#define AB_ADDAN(abp) AB_ADDNREC(abp,sizeof(alnode_t), 1)
#define AB_RMAL(abp) AB_RMNREC(abp,sizeof(alleaf_t), 1)
#define AB_RMAN(abp) AB_RMNREC(abp,sizeof(alnode_t), 1)
typedef struct alblk {
u_int8_t ab_flag;
u_int8_t ab_res[3];
u_int8_t ab_freecnt;
u_int8_t ab_busycnt;
u_int16_t ab_freeoff;
} alblk_t;
/*
* FNode
*/
#define FNODESIZE DEV_BSIZE
#define FN_MAGIC 0xF7E40AAE
struct fnode {
u_int32_t fn_magic;
u_int64_t fn_readhist;
u_int8_t fn_namelen;
char fn_name[0xF]; /* First 15 symbols or less */
lsn_t fn_parent;
sptr_t fn_extacl;
u_int16_t fn_acllen;
u_int8_t fn_extaclflag;
u_int8_t fn_histbitcount;
sptr_t fn_extea;
u_int16_t fn_ealen; /* Len of EAs in Fnode */
u_int8_t fn_exteaflag; /* EAs in exteas */
u_int8_t fn_flag;
alblk_t fn_ab;
u_int8_t fn_abd[0x60];
u_int32_t fn_size;
u_int32_t fn_reqea;
u_int8_t fn_uid[0x10];
u_int16_t fn_intoff;
u_int8_t fn_1dasdthr;
u_int8_t fn_dasdthr;
u_int32_t fn_dasdlim;
u_int32_t fn_dasdusage;
u_int8_t fn_int[0x13c];
};
#define EA_NAME(eap) ((char *)(((caddr_t)(eap)) + sizeof(struct ea)))
struct ea {
u_int8_t ea_type; /* 0 - plain val */
/* 1 - sptr to val */
/* 3 - lsn point to AlSec, cont. val */
u_int8_t ea_namelen;
u_int16_t ea_vallen;
/*u_int8_t ea_name[]; */
/*u_int8_t ea_val[]; */
};
/*
* Allocation Block Data (ALNODE)
*
* NOTE: AlNodes are used when there are too many fragments
* to represent the data in the AlBlk
*/
#define AN_SET(anp,nextoff,lsn) { \
(anp)->an_nextoff = (nextoff); \
(anp)->an_lsn = (lsn); \
}
typedef struct alnode {
u_int32_t an_nextoff; /* next node offset in blocks */
lsn_t an_lsn; /* position of AlSec structure */
} alnode_t;
/*
* Allocaion Block Data (ALLEAF)
*
* NOTE: Leaves are used to point at contiguous block of data
* (a fragment or an "extent");
*/
#define AL_SET(alp,off,len,lsn) { \
(alp)->al_off = (off); \
(alp)->al_len = (len); \
(alp)->al_lsn = (lsn); \
}
typedef struct alleaf {
u_int32_t al_off; /* offset in blocks */
u_int32_t al_len; /* len in blocks */
lsn_t al_lsn; /* phys position */
} alleaf_t;
/*
* Allocation Sector
*
* NOTE: AlSecs are not initialized before use, so they ussually
* look full of junk. Use the AlBlk tto validate the data.
*/
#define AS_MAGIC 0x37E40AAE
typedef struct alsec {
u_int32_t as_magic;
lsn_t as_self;
lsn_t as_parent;
alblk_t as_ab;
u_int8_t as_abd[0x1E0];
} alsec_t;
/*
* Code Page structures
*/
struct cpdblk {
u_int16_t b_country; /* Country code */
u_int16_t b_cpid; /* CP ID */
u_int16_t b_dbcscnt; /* Count of DBCS ranges in CP */
char b_upcase[0x80]; /* Case conversion table */
u_int16_t b_dbcsrange; /* Start/End DBCS range pairs */
};
#define CPD_MAGIC ((u_int32_t)0x894521F7)
struct cpdsec {
u_int32_t d_magic;
u_int16_t d_cpcnt; /* CP Data count */
u_int16_t d_cpfirst; /* Index of first CP Data */
u_int32_t d_checksum[3]; /* CP Data checksumms */
u_int16_t d_offset[3]; /* Offsets of CP Data blocks */
struct cpdblk d_cpdblk[3]; /* Array of CP Data Blocks */
};
struct cpiblk {
u_int16_t b_country; /* Country code */
u_int16_t b_cpid; /* CP ID */
u_int32_t b_checksum;
lsn_t b_cpdsec; /* Pointer to CP Data Sector */
u_int16_t b_vcpid; /* Volume spec. CP ID */
u_int16_t b_dbcscnt; /* Count of DBCS ranges in CP */
};
#define CPI_MAGIC ((u_int32_t)0x494521F7)
struct cpisec {
u_int32_t s_magic;
u_int32_t s_cpicnt; /* Count of CPI's in this sector */
u_int32_t s_cpifirst; /* Index of first CPI in this sector */
lsn_t s_next; /* Pointer to next CPI Sector */
struct cpiblk s_cpi[0x1F]; /* Array of CPI blocks */
};
struct hpfsmount {
struct sublock hpm_su;
struct spblock hpm_sp;
struct mount * hpm_mp;
struct vnode * hpm_devvp;
dev_t hpm_dev;
uid_t hpm_uid;
gid_t hpm_gid;
mode_t hpm_mode;
lsn_t * hpm_bmind;
struct cpdblk * hpm_cpdblk; /* Array of CP Data Blocks */
u_char hpm_u2d[0x80]; /* Unix to DOS Table*/
u_char hpm_d2u[0x80]; /* DOS to Unix Table*/
u_long hpm_bavail; /* Blocks available */
u_long hpm_dbnum; /* Data Band number */
u_int8_t * hpm_bitmap;
};
#define H_HASHED 0x0001 /* Present in hash */
#define H_PARVALID 0x0002 /* parent info is valid */
#define H_CHANGE 0x0004 /* node date was changed */
#define H_PARCHANGE 0x0008 /* parent node date was changed */
#define H_INVAL 0x0010 /* Invalid node */
struct hpfsnode {
struct mtx h_interlock;
LIST_ENTRY(hpfsnode) h_hash;
struct hpfsmount *h_hpmp;
struct fnode h_fn;
struct vnode * h_vp;
struct vnode * h_devvp;
dev_t h_dev;
lsn_t h_no;
uid_t h_uid;
gid_t h_gid;
mode_t h_mode;
u_int32_t h_flag;
/* parent dir information */
u_long h_mtime;
u_long h_atime;
u_long h_ctime;
char h_name[HPFS_MAXFILENAME+1]; /* Used to speedup dirent */
int h_namelen; /* lookup */
};
/* This overlays the fid structure (see <sys/mount.h>) */
struct hpfid {
u_int16_t hpfid_len; /* Length of structure. */
u_int16_t hpfid_pad; /* Force 32-bit alignment. */
lsn_t hpfid_ino; /* File number (ino). */
int32_t hpfid_gen; /* Generation number. */
};
#if defined(HPFS_DEBUG)
#define dprintf(a) printf a
#if HPFS_DEBUG > 1
#define ddprintf(a) printf a
#else
#define ddprintf(a)
#endif
#else
#define dprintf(a)
#define ddprintf(a)
#endif
#if __FreeBSD_version >= 300000
MALLOC_DECLARE(M_HPFSMNT);
MALLOC_DECLARE(M_HPFSNO);
#endif
#define VFSTOHPFS(mp) ((struct hpfsmount *)((mp)->mnt_data))
#define VTOHP(v) ((struct hpfsnode *)((v)->v_data))
#define HPTOV(h) ((struct vnode *)((h)->h_vp))
#define FID(f) (*((lsn_t *)(f)->fid_data))
extern vop_t ** hpfs_vnodeop_p;
/* Hash routines, too small to be separate header */
void hpfs_hphashinit(void);
void hpfs_hphashdestroy(void);
struct hpfsnode *hpfs_hphashlookup(dev_t, lsn_t);
struct hpfsnode *hpfs_hphashget(dev_t, lsn_t);
int hpfs_hphashvget(dev_t, lsn_t, int, struct vnode **, struct thread *);
void hpfs_hphashins(register struct hpfsnode *);
void hpfs_hphashrem(register struct hpfsnode *);
extern struct lock hpfs_hphash_lock;
|