hpfs.h revision 66615
1/*- 2 * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/fs/hpfs/hpfs.h 66615 2000-10-04 01:29:17Z jasone $ 27 */ 28 29/*#define HPFS_DEBUG 10*/ 30typedef u_int32_t lsn_t; /* Logical Sector Number */ 31typedef struct { 32 lsn_t lsn1; 33 lsn_t lsn2; 34} rsp_t; /* Redundant Sector Pointer */ 35typedef struct { 36 u_int32_t cnt; 37 lsn_t lsn; 38} sptr_t; /* Storage Pointer */ 39 40#define SUBLOCK 0x10 41#define SUSIZE DEV_BSIZE 42#define SPBLOCK 0x11 43#define SPSIZE DEV_BSIZE 44#define BMSIZE (4 * DEV_BSIZE) 45#define HPFS_MAXFILENAME 255 46 47#define SU_MAGIC ((u_int64_t)0xFA53E9C5F995E849) 48struct sublock { 49 u_int64_t su_magic; 50 u_int8_t su_hpfsver; 51 u_int8_t su_fnctver; 52 u_int16_t unused; 53 lsn_t su_rootfno; /* Root Fnode */ 54 u_int32_t su_btotal; /* Total blocks */ 55 u_int32_t su_badbtotal; /* Bad Sectors total */ 56 rsp_t su_bitmap; 57 rsp_t su_badbl; 58 u_long su_chkdskdate; 59 u_long su_dskoptdate; 60 u_int32_t su_dbbsz; /* Sectors in DirBlock Band */ 61 lsn_t su_dbbstart; 62 lsn_t su_dbbend; 63 lsn_t su_dbbbitmap; 64 char su_volname[0x20]; 65 lsn_t su_uidt; /* Ptr to User ID Table (8 sect) */ 66}; 67 68#define SP_MAGIC ((u_int64_t)0xFA5229C5F9911849) 69#define SP_DIRTY 0x0001 70#define SP_SPDBINUSE 0x0002 71#define SP_HFINUSE 0x0004 72#define SP_BADSECT 0x0008 73#define SP_BADBMBL 0x0010 74#define SP_FASTFRMT 0x0020 75#define SP_OLDHPFS 0x0080 76#define SP_IDASD 0x0100 77#define SP_RDASD 0x0200 78#define SP_DASD 0x0400 79#define SP_MMACTIVE 0x0800 80#define SP_DCEACLS 0x1000 81#define SP_DSADDIRTY 0x2000 82struct spblock { 83 u_int64_t sp_magic; 84 u_int16_t sp_flag; 85 u_int8_t sp_mmcontf; 86 u_int8_t unused; 87 lsn_t sp_hf; /* HotFix list */ 88 u_int32_t sp_hfinuse; /* HotFixes in use */ 89 u_int32_t sp_hfavail; /* HotFixes available */ 90 u_int32_t sp_spdbavail; /* Spare DirBlocks available */ 91 u_int32_t sp_spdbmax; /* Spare DirBlocks maximum */ 92 lsn_t sp_cpi; 93 u_int32_t sp_cpinum; 94 u_int32_t sp_suchecksum; 95 u_int32_t sp_spchecksum; 96 u_int8_t reserved[0x3C]; 97 lsn_t sp_spdb[0x65]; 98}; 99 100#define DE_SPECIAL 0x0001 101#define DE_ACL 0x0002 102#define DE_DOWN 0x0004 103#define DE_END 0x0008 104#define DE_EALIST 0x0010 105#define DE_EPERM 0x0020 106#define DE_EXPLACL 0x0040 107#define DE_NEEDEA 0x0080 108#define DE_RONLY 0x0100 109#define DE_HIDDEN 0x0200 110#define DE_SYSTEM 0x0400 111#define DE_VOLLABEL 0x0800 112#define DE_DIR 0x1000 113#define DE_ARCHIV 0x2000 114#define DE_DOWNLSN(dep) (*(lsn_t *)((caddr_t)(dep) + (dep)->de_reclen - sizeof(lsn_t))) 115#define DE_NEXTDE(dep) ((struct hpfsdirent *)((caddr_t)(dep) + (dep)->de_reclen)) 116typedef struct hpfsdirent { 117 u_int16_t de_reclen; 118 u_int16_t de_flag; 119 lsn_t de_fnode; 120 u_long de_mtime; 121 u_int32_t de_size; 122 u_long de_atime; 123 u_long de_ctime; 124 u_int32_t de_ealen; 125 u_int8_t de_flexflag; 126 u_int8_t de_cpid; 127 u_int8_t de_namelen; 128 char de_name[1]; 129/* ... de_flex; */ 130/* lsn_t de_down; */ 131} hpfsdirent_t; 132 133#define D_BSIZE (DEV_BSIZE*4) 134#define D_MAGIC 0x77E40AAE 135#define D_DIRENT(dbp) ((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t))) 136#define D_DE(dbp, deoff) ((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t) + (deoff))) 137typedef struct dirblk { 138 u_int32_t d_magic; 139 u_int32_t d_freeoff; /* Offset of first free byte */ 140 u_int32_t d_chcnt; /* Change count */ 141 lsn_t d_parent; 142 lsn_t d_self; 143} dirblk_t; 144 145/* 146 * Allocation Block (ALBLK) 147 */ 148#define AB_HBOFFEO 0x01 149#define AB_FNPARENT 0x20 150#define AB_SUGGBSCH 0x40 151#define AB_NODES 0x80 152#define AB_ALLEAF(abp) ((alleaf_t *)((caddr_t)(abp) + sizeof(alblk_t))) 153#define AB_ALNODE(abp) ((alnode_t *)((caddr_t)(abp) + sizeof(alblk_t))) 154#define AB_FREEALP(abp) ((alleaf_t *)((caddr_t)(abp) + (abp)->ab_freeoff)) 155#define AB_FREEANP(abp) ((alnode_t *)((caddr_t)(abp) + (abp)->ab_freeoff)) 156#define AB_LASTALP(abp) (AB_ALLEAF(abp) + (abp)->ab_busycnt - 1) 157#define AB_LASTANP(abp) (AB_ALNODE(abp) + (abp)->ab_busycnt - 1) 158#define AB_ADDNREC(abp, sz, n) { \ 159 (abp)->ab_busycnt += (n); \ 160 (abp)->ab_freecnt -= (n); \ 161 (abp)->ab_freeoff += (n) * (sz); \ 162} 163#define AB_RMNREC(abp, sz, n) { \ 164 (abp)->ab_busycnt -= (n); \ 165 (abp)->ab_freecnt += (n); \ 166 (abp)->ab_freeoff -= (n) * (sz);\ 167} 168#define AB_ADDAL(abp) AB_ADDNREC(abp,sizeof(alleaf_t), 1) 169#define AB_ADDAN(abp) AB_ADDNREC(abp,sizeof(alnode_t), 1) 170#define AB_RMAL(abp) AB_RMNREC(abp,sizeof(alleaf_t), 1) 171#define AB_RMAN(abp) AB_RMNREC(abp,sizeof(alnode_t), 1) 172typedef struct alblk { 173 u_int8_t ab_flag; 174 u_int8_t ab_res[3]; 175 u_int8_t ab_freecnt; 176 u_int8_t ab_busycnt; 177 u_int16_t ab_freeoff; 178} alblk_t; 179 180/* 181 * FNode 182 */ 183#define FNODESIZE DEV_BSIZE 184#define FN_MAGIC 0xF7E40AAE 185struct fnode { 186 u_int32_t fn_magic; 187 u_int64_t fn_readhist; 188 u_int8_t fn_namelen; 189 char fn_name[0xF]; /* First 15 symbols or less */ 190 lsn_t fn_parent; 191 sptr_t fn_extacl; 192 u_int16_t fn_acllen; 193 u_int8_t fn_extaclflag; 194 u_int8_t fn_histbitcount; 195 sptr_t fn_extea; 196 u_int16_t fn_ealen; /* Len of EAs in Fnode */ 197 u_int8_t fn_exteaflag; /* EAs in exteas */ 198 u_int8_t fn_flag; 199 alblk_t fn_ab; 200 u_int8_t fn_abd[0x60]; 201 u_int32_t fn_size; 202 u_int32_t fn_reqea; 203 u_int8_t fn_uid[0x10]; 204 u_int16_t fn_intoff; 205 u_int8_t fn_1dasdthr; 206 u_int8_t fn_dasdthr; 207 u_int32_t fn_dasdlim; 208 u_int32_t fn_dasdusage; 209 u_int8_t fn_int[0x13c]; 210}; 211 212#define EA_NAME(eap) ((char *)(((caddr_t)(eap)) + sizeof(struct ea))) 213struct ea { 214 u_int8_t ea_type; /* 0 - plain val */ 215 /* 1 - sptr to val */ 216 /* 3 - lsn point to AlSec, cont. val */ 217 u_int8_t ea_namelen; 218 u_int16_t ea_vallen; 219 /*u_int8_t ea_name[]; */ 220 /*u_int8_t ea_val[]; */ 221}; 222 223/* 224 * Allocation Block Data (ALNODE) 225 * 226 * NOTE: AlNodes are used when there are too many fragments 227 * to represent the data in the AlBlk 228 */ 229#define AN_SET(anp,nextoff,lsn) { \ 230 (anp)->an_nextoff = (nextoff); \ 231 (anp)->an_lsn = (lsn); \ 232} 233typedef struct alnode { 234 u_int32_t an_nextoff; /* next node offset in blocks */ 235 lsn_t an_lsn; /* position of AlSec structure */ 236} alnode_t; 237 238/* 239 * Allocaion Block Data (ALLEAF) 240 * 241 * NOTE: Leaves are used to point at contiguous block of data 242 * (a fragment or an "extent"); 243 */ 244#define AL_SET(alp,off,len,lsn) { \ 245 (alp)->al_off = (off); \ 246 (alp)->al_len = (len); \ 247 (alp)->al_lsn = (lsn); \ 248} 249typedef struct alleaf { 250 u_int32_t al_off; /* offset in blocks */ 251 u_int32_t al_len; /* len in blocks */ 252 lsn_t al_lsn; /* phys position */ 253} alleaf_t; 254 255/* 256 * Allocation Sector 257 * 258 * NOTE: AlSecs are not initialized before use, so they ussually 259 * look full of junk. Use the AlBlk tto validate the data. 260 */ 261#define AS_MAGIC 0x37E40AAE 262typedef struct alsec { 263 u_int32_t as_magic; 264 lsn_t as_self; 265 lsn_t as_parent; 266 alblk_t as_ab; 267 u_int8_t as_abd[0x1E0]; 268} alsec_t; 269 270/* 271 * Code Page structures 272 */ 273struct cpdblk { 274 u_int16_t b_country; /* Country code */ 275 u_int16_t b_cpid; /* CP ID */ 276 u_int16_t b_dbcscnt; /* Count of DBCS ranges in CP */ 277 char b_upcase[0x80]; /* Case conversion table */ 278 u_int16_t b_dbcsrange; /* Start/End DBCS range pairs */ 279 280}; 281 282#define CPD_MAGIC ((u_int32_t)0x894521F7) 283struct cpdsec { 284 u_int32_t d_magic; 285 u_int16_t d_cpcnt; /* CP Data count */ 286 u_int16_t d_cpfirst; /* Index of first CP Data */ 287 u_int32_t d_checksum[3]; /* CP Data checksumms */ 288 u_int16_t d_offset[3]; /* Offsets of CP Data blocks */ 289 struct cpdblk d_cpdblk[3]; /* Array of CP Data Blocks */ 290}; 291 292struct cpiblk { 293 u_int16_t b_country; /* Country code */ 294 u_int16_t b_cpid; /* CP ID */ 295 u_int32_t b_checksum; 296 lsn_t b_cpdsec; /* Pointer to CP Data Sector */ 297 u_int16_t b_vcpid; /* Volume spec. CP ID */ 298 u_int16_t b_dbcscnt; /* Count of DBCS ranges in CP */ 299}; 300 301#define CPI_MAGIC ((u_int32_t)0x494521F7) 302struct cpisec { 303 u_int32_t s_magic; 304 u_int32_t s_cpicnt; /* Count of CPI's in this sector */ 305 u_int32_t s_cpifirst; /* Index of first CPI in this sector */ 306 lsn_t s_next; /* Pointer to next CPI Sector */ 307 struct cpiblk s_cpi[0x1F]; /* Array of CPI blocks */ 308}; 309 310struct hpfsmount { 311 struct sublock hpm_su; 312 struct spblock hpm_sp; 313 struct netexport hpm_export; 314 struct mount * hpm_mp; 315 struct vnode * hpm_devvp; 316 dev_t hpm_dev; 317 uid_t hpm_uid; 318 gid_t hpm_gid; 319 mode_t hpm_mode; 320 321 lsn_t * hpm_bmind; 322 struct cpdblk * hpm_cpdblk; /* Array of CP Data Blocks */ 323 u_char hpm_u2d[0x80]; /* Unix to DOS Table*/ 324 u_char hpm_d2u[0x80]; /* DOS to Unix Table*/ 325 326 u_long hpm_bavail; /* Blocks available */ 327 u_long hpm_dbnum; /* Data Band number */ 328 u_int8_t * hpm_bitmap; 329}; 330 331#define H_HASHED 0x0001 /* Present in hash */ 332#define H_PARVALID 0x0002 /* parent info is valid */ 333#define H_CHANGE 0x0004 /* node date was changed */ 334#define H_PARCHANGE 0x0008 /* parent node date was changed */ 335#define H_INVAL 0x0010 /* Invalid node */ 336struct hpfsnode { 337 struct lock h_lock; /* Must be first, for std vops */ 338#ifndef NULL_SIMPLELOCKS 339 struct simplelock h_interlock; 340#endif 341 342 LIST_ENTRY(hpfsnode) h_hash; 343 344 struct hpfsmount *h_hpmp; 345 struct fnode h_fn; 346 struct vnode * h_vp; 347 struct vnode * h_devvp; 348 dev_t h_dev; 349 lsn_t h_no; 350 uid_t h_uid; 351 gid_t h_gid; 352 mode_t h_mode; 353 u_int32_t h_flag; 354 355 /* parent dir information */ 356 u_long h_mtime; 357 u_long h_atime; 358 u_long h_ctime; 359 char h_name[HPFS_MAXFILENAME+1]; /* Used to speedup dirent */ 360 int h_namelen; /* lookup */ 361}; 362 363/* This overlays the fid structure (see <sys/mount.h>) */ 364struct hpfid { 365 u_int16_t hpfid_len; /* Length of structure. */ 366 u_int16_t hpfid_pad; /* Force 32-bit alignment. */ 367 lsn_t hpfid_ino; /* File number (ino). */ 368 int32_t hpfid_gen; /* Generation number. */ 369}; 370 371#if defined(HPFS_DEBUG) 372#define dprintf(a) printf a 373#if HPFS_DEBUG > 1 374#define ddprintf(a) printf a 375#else 376#define ddprintf(a) 377#endif 378#else 379#define dprintf(a) 380#define ddprintf(a) 381#endif 382 383#if __FreeBSD_version >= 300000 384MALLOC_DECLARE(M_HPFSMNT); 385MALLOC_DECLARE(M_HPFSNO); 386#endif 387#define VFSTOHPFS(mp) ((struct hpfsmount *)((mp)->mnt_data)) 388#define VTOHP(v) ((struct hpfsnode *)((v)->v_data)) 389#define HPTOV(h) ((struct vnode *)((h)->h_vp)) 390#define FID(f) (*((lsn_t *)(f)->fid_data)) 391 392#if defined(__NetBSD__) 393#define MALLOC_DEFINE(a, b, c) 394#define M_HPFSMNT M_TEMP 395#define M_HPFSNO M_TEMP 396typedef int (vop_t) __P((void *)); 397#define HASHINIT(a, b, c, d) hashinit((a), (b), (c), (d)) 398#define bqrelse(bp) brelse(bp) 399#define VOP__LOCK(a, b, c) VOP_LOCK((a), (b) ? LK_EXCLUSIVE : LK_SHARED) 400#define VOP__UNLOCK(a, b, c) VOP_UNLOCK((a), 0) 401#define VGET(a, b, c) vget((a), LK_EXCLUSIVE) 402#define VN_LOCK(a, b, c) vn_lock((a), LK_EXCLUSIVE) 403#define LOCKMGR(a, b, c, d) lockmgr((a), (b), (c)) 404#else /* defined(__FreeBSD__) */ 405#define HASHINIT(a, b, c, d) hashinit((a), (b), (d)) 406#define VOP__LOCK(a, b, c) VOP_LOCK((a), (b), (c)) 407#define VOP__UNLOCK(a, b, c) VOP_UNLOCK((a), (b), (c)) 408#define VGET(a, b, c) vget((a), (b), (c)) 409#define VN_LOCK(a, b, c) vn_lock((a), (b), (c)) 410#define LOCKMGR(a, b, c, d) lockmgr((a), (b), (c), (d)) 411#endif 412 413extern vop_t ** hpfs_vnodeop_p; 414 415/* Hash routines, too small to be separate header */ 416void hpfs_hphashinit __P((void)); 417void hpfs_hphashdestroy __P((void)); 418struct hpfsnode *hpfs_hphashlookup __P((dev_t, lsn_t)); 419struct hpfsnode *hpfs_hphashget __P((dev_t, lsn_t)); 420struct vnode *hpfs_hphashvget __P((dev_t, lsn_t, struct proc *)); 421void hpfs_hphashins __P((register struct hpfsnode *)); 422void hpfs_hphashrem __P((register struct hpfsnode *)); 423extern struct lock hpfs_hphash_lock; 424