hpfs.h revision 75934
1219820Sjeff/*- 2219820Sjeff * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org) 3219820Sjeff * All rights reserved. 4219820Sjeff * 5219820Sjeff * Redistribution and use in source and binary forms, with or without 6219820Sjeff * modification, are permitted provided that the following conditions 7219820Sjeff * are met: 8219820Sjeff * 1. Redistributions of source code must retain the above copyright 9219820Sjeff * notice, this list of conditions and the following disclaimer. 10219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright 11219820Sjeff * notice, this list of conditions and the following disclaimer in the 12219820Sjeff * documentation and/or other materials provided with the distribution. 13219820Sjeff * 14219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15219820Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16219820Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17219820Sjeff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18219820Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19219820Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20219820Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21219820Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22219820Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23219820Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24219820Sjeff * SUCH DAMAGE. 25219820Sjeff * 26219820Sjeff * $FreeBSD: head/sys/fs/hpfs/hpfs.h 75934 2001-04-25 07:07:52Z phk $ 27219820Sjeff */ 28219820Sjeff 29219820Sjeff/*#define HPFS_DEBUG 10*/ 30219820Sjefftypedef u_int32_t lsn_t; /* Logical Sector Number */ 31219820Sjefftypedef struct { 32219820Sjeff lsn_t lsn1; 33219820Sjeff lsn_t lsn2; 34219820Sjeff} rsp_t; /* Redundant Sector Pointer */ 35219820Sjefftypedef struct { 36219820Sjeff u_int32_t cnt; 37219820Sjeff lsn_t lsn; 38219820Sjeff} sptr_t; /* Storage Pointer */ 39219820Sjeff 40219820Sjeff#define SUBLOCK 0x10 41219820Sjeff#define SUSIZE DEV_BSIZE 42219820Sjeff#define SPBLOCK 0x11 43219820Sjeff#define SPSIZE DEV_BSIZE 44219820Sjeff#define BMSIZE (4 * DEV_BSIZE) 45219820Sjeff#define HPFS_MAXFILENAME 255 46219820Sjeff 47219820Sjeff#define SU_MAGIC ((u_int64_t)0xFA53E9C5F995E849) 48219820Sjeffstruct sublock { 49219820Sjeff u_int64_t su_magic; 50219820Sjeff u_int8_t su_hpfsver; 51219820Sjeff u_int8_t su_fnctver; 52219820Sjeff u_int16_t unused; 53219820Sjeff lsn_t su_rootfno; /* Root Fnode */ 54219820Sjeff u_int32_t su_btotal; /* Total blocks */ 55219820Sjeff u_int32_t su_badbtotal; /* Bad Sectors total */ 56219820Sjeff rsp_t su_bitmap; 57219820Sjeff rsp_t su_badbl; 58219820Sjeff u_long su_chkdskdate; 59219820Sjeff u_long su_dskoptdate; 60219820Sjeff u_int32_t su_dbbsz; /* Sectors in DirBlock Band */ 61219820Sjeff lsn_t su_dbbstart; 62219820Sjeff lsn_t su_dbbend; 63219820Sjeff lsn_t su_dbbbitmap; 64219820Sjeff char su_volname[0x20]; 65219820Sjeff lsn_t su_uidt; /* Ptr to User ID Table (8 sect) */ 66219820Sjeff}; 67219820Sjeff 68219820Sjeff#define SP_MAGIC ((u_int64_t)0xFA5229C5F9911849) 69219820Sjeff#define SP_DIRTY 0x0001 70219820Sjeff#define SP_SPDBINUSE 0x0002 71219820Sjeff#define SP_HFINUSE 0x0004 72219820Sjeff#define SP_BADSECT 0x0008 73219820Sjeff#define SP_BADBMBL 0x0010 74219820Sjeff#define SP_FASTFRMT 0x0020 75219820Sjeff#define SP_OLDHPFS 0x0080 76219820Sjeff#define SP_IDASD 0x0100 77219820Sjeff#define SP_RDASD 0x0200 78219820Sjeff#define SP_DASD 0x0400 79219820Sjeff#define SP_MMACTIVE 0x0800 80219820Sjeff#define SP_DCEACLS 0x1000 81219820Sjeff#define SP_DSADDIRTY 0x2000 82219820Sjeffstruct spblock { 83219820Sjeff u_int64_t sp_magic; 84219820Sjeff u_int16_t sp_flag; 85219820Sjeff u_int8_t sp_mmcontf; 86219820Sjeff u_int8_t unused; 87219820Sjeff lsn_t sp_hf; /* HotFix list */ 88219820Sjeff u_int32_t sp_hfinuse; /* HotFixes in use */ 89219820Sjeff u_int32_t sp_hfavail; /* HotFixes available */ 90219820Sjeff u_int32_t sp_spdbavail; /* Spare DirBlocks available */ 91219820Sjeff u_int32_t sp_spdbmax; /* Spare DirBlocks maximum */ 92219820Sjeff lsn_t sp_cpi; 93219820Sjeff u_int32_t sp_cpinum; 94219820Sjeff u_int32_t sp_suchecksum; 95219820Sjeff u_int32_t sp_spchecksum; 96219820Sjeff u_int8_t reserved[0x3C]; 97219820Sjeff lsn_t sp_spdb[0x65]; 98219820Sjeff}; 99219820Sjeff 100219820Sjeff#define DE_SPECIAL 0x0001 101219820Sjeff#define DE_ACL 0x0002 102219820Sjeff#define DE_DOWN 0x0004 103219820Sjeff#define DE_END 0x0008 104219820Sjeff#define DE_EALIST 0x0010 105219820Sjeff#define DE_EPERM 0x0020 106219820Sjeff#define DE_EXPLACL 0x0040 107219820Sjeff#define DE_NEEDEA 0x0080 108219820Sjeff#define DE_RONLY 0x0100 109219820Sjeff#define DE_HIDDEN 0x0200 110219820Sjeff#define DE_SYSTEM 0x0400 111219820Sjeff#define DE_VOLLABEL 0x0800 112219820Sjeff#define DE_DIR 0x1000 113219820Sjeff#define DE_ARCHIV 0x2000 114219820Sjeff#define DE_DOWNLSN(dep) (*(lsn_t *)((caddr_t)(dep) + (dep)->de_reclen - sizeof(lsn_t))) 115219820Sjeff#define DE_NEXTDE(dep) ((struct hpfsdirent *)((caddr_t)(dep) + (dep)->de_reclen)) 116219820Sjefftypedef struct hpfsdirent { 117219820Sjeff u_int16_t de_reclen; 118219820Sjeff u_int16_t de_flag; 119219820Sjeff lsn_t de_fnode; 120219820Sjeff u_long de_mtime; 121219820Sjeff u_int32_t de_size; 122219820Sjeff u_long de_atime; 123219820Sjeff u_long de_ctime; 124219820Sjeff u_int32_t de_ealen; 125219820Sjeff u_int8_t de_flexflag; 126219820Sjeff u_int8_t de_cpid; 127219820Sjeff u_int8_t de_namelen; 128219820Sjeff char de_name[1]; 129219820Sjeff/* ... de_flex; */ 130219820Sjeff/* lsn_t de_down; */ 131219820Sjeff} hpfsdirent_t; 132219820Sjeff 133219820Sjeff#define D_BSIZE (DEV_BSIZE*4) 134219820Sjeff#define D_MAGIC 0x77E40AAE 135219820Sjeff#define D_DIRENT(dbp) ((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t))) 136219820Sjeff#define D_DE(dbp, deoff) ((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t) + (deoff))) 137219820Sjefftypedef struct dirblk { 138219820Sjeff u_int32_t d_magic; 139219820Sjeff u_int32_t d_freeoff; /* Offset of first free byte */ 140219820Sjeff u_int32_t d_chcnt; /* Change count */ 141219820Sjeff lsn_t d_parent; 142219820Sjeff lsn_t d_self; 143219820Sjeff} dirblk_t; 144219820Sjeff 145219820Sjeff/* 146219820Sjeff * Allocation Block (ALBLK) 147219820Sjeff */ 148219820Sjeff#define AB_HBOFFEO 0x01 149219820Sjeff#define AB_FNPARENT 0x20 150219820Sjeff#define AB_SUGGBSCH 0x40 151219820Sjeff#define AB_NODES 0x80 152219820Sjeff#define AB_ALLEAF(abp) ((alleaf_t *)((caddr_t)(abp) + sizeof(alblk_t))) 153219820Sjeff#define AB_ALNODE(abp) ((alnode_t *)((caddr_t)(abp) + sizeof(alblk_t))) 154219820Sjeff#define AB_FREEALP(abp) ((alleaf_t *)((caddr_t)(abp) + (abp)->ab_freeoff)) 155219820Sjeff#define AB_FREEANP(abp) ((alnode_t *)((caddr_t)(abp) + (abp)->ab_freeoff)) 156219820Sjeff#define AB_LASTALP(abp) (AB_ALLEAF(abp) + (abp)->ab_busycnt - 1) 157219820Sjeff#define AB_LASTANP(abp) (AB_ALNODE(abp) + (abp)->ab_busycnt - 1) 158219820Sjeff#define AB_ADDNREC(abp, sz, n) { \ 159219820Sjeff (abp)->ab_busycnt += (n); \ 160219820Sjeff (abp)->ab_freecnt -= (n); \ 161219820Sjeff (abp)->ab_freeoff += (n) * (sz); \ 162219820Sjeff} 163219820Sjeff#define AB_RMNREC(abp, sz, n) { \ 164219820Sjeff (abp)->ab_busycnt -= (n); \ 165219820Sjeff (abp)->ab_freecnt += (n); \ 166219820Sjeff (abp)->ab_freeoff -= (n) * (sz);\ 167219820Sjeff} 168219820Sjeff#define AB_ADDAL(abp) AB_ADDNREC(abp,sizeof(alleaf_t), 1) 169219820Sjeff#define AB_ADDAN(abp) AB_ADDNREC(abp,sizeof(alnode_t), 1) 170219820Sjeff#define AB_RMAL(abp) AB_RMNREC(abp,sizeof(alleaf_t), 1) 171219820Sjeff#define AB_RMAN(abp) AB_RMNREC(abp,sizeof(alnode_t), 1) 172219820Sjefftypedef struct alblk { 173219820Sjeff u_int8_t ab_flag; 174219820Sjeff u_int8_t ab_res[3]; 175219820Sjeff u_int8_t ab_freecnt; 176219820Sjeff u_int8_t ab_busycnt; 177219820Sjeff u_int16_t ab_freeoff; 178219820Sjeff} alblk_t; 179219820Sjeff 180219820Sjeff/* 181219820Sjeff * FNode 182219820Sjeff */ 183219820Sjeff#define FNODESIZE DEV_BSIZE 184219820Sjeff#define FN_MAGIC 0xF7E40AAE 185219820Sjeffstruct fnode { 186219820Sjeff u_int32_t fn_magic; 187219820Sjeff u_int64_t fn_readhist; 188219820Sjeff u_int8_t fn_namelen; 189219820Sjeff char fn_name[0xF]; /* First 15 symbols or less */ 190219820Sjeff lsn_t fn_parent; 191219820Sjeff sptr_t fn_extacl; 192219820Sjeff u_int16_t fn_acllen; 193219820Sjeff u_int8_t fn_extaclflag; 194219820Sjeff u_int8_t fn_histbitcount; 195219820Sjeff sptr_t fn_extea; 196219820Sjeff u_int16_t fn_ealen; /* Len of EAs in Fnode */ 197219820Sjeff u_int8_t fn_exteaflag; /* EAs in exteas */ 198219820Sjeff u_int8_t fn_flag; 199219820Sjeff alblk_t fn_ab; 200219820Sjeff u_int8_t fn_abd[0x60]; 201219820Sjeff u_int32_t fn_size; 202219820Sjeff 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#if !defined(__FreeBSD__) 314 struct netexport hpm_export; 315#endif 316 struct mount * hpm_mp; 317 struct vnode * hpm_devvp; 318 dev_t hpm_dev; 319 uid_t hpm_uid; 320 gid_t hpm_gid; 321 mode_t hpm_mode; 322 323 lsn_t * hpm_bmind; 324 struct cpdblk * hpm_cpdblk; /* Array of CP Data Blocks */ 325 u_char hpm_u2d[0x80]; /* Unix to DOS Table*/ 326 u_char hpm_d2u[0x80]; /* DOS to Unix Table*/ 327 328 u_long hpm_bavail; /* Blocks available */ 329 u_long hpm_dbnum; /* Data Band number */ 330 u_int8_t * hpm_bitmap; 331}; 332 333#define H_HASHED 0x0001 /* Present in hash */ 334#define H_PARVALID 0x0002 /* parent info is valid */ 335#define H_CHANGE 0x0004 /* node date was changed */ 336#define H_PARCHANGE 0x0008 /* parent node date was changed */ 337#define H_INVAL 0x0010 /* Invalid node */ 338struct hpfsnode { 339 struct lock h_lock; /* Must be first, for std vops */ 340 struct mtx h_interlock; 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