1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/hpfs/hpfs.h
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * HPFS structures by Chris Smith, 1993
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * a little bit modified by Mikulas Patocka, 1998-1999
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds
101da177e4SLinus Torvalds /* The paper
111da177e4SLinus Torvalds
121da177e4SLinus Torvalds Duncan, Roy
131da177e4SLinus Torvalds Design goals and implementation of the new High Performance File System
141da177e4SLinus Torvalds Microsoft Systems Journal Sept 1989 v4 n5 p1(13)
151da177e4SLinus Torvalds
161da177e4SLinus Torvalds describes what HPFS looked like when it was new, and it is the source
171da177e4SLinus Torvalds of most of the information given here. The rest is conjecture.
181da177e4SLinus Torvalds
191da177e4SLinus Torvalds For definitive information on the Duncan paper, see it, not this file.
201da177e4SLinus Torvalds For definitive information on HPFS, ask somebody else -- this is guesswork.
211da177e4SLinus Torvalds There are certain to be many mistakes. */
221da177e4SLinus Torvalds
230b69760bSMikulas Patocka #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
240b69760bSMikulas Patocka #error unknown endian
250b69760bSMikulas Patocka #endif
260b69760bSMikulas Patocka
271da177e4SLinus Torvalds /* Notation */
281da177e4SLinus Torvalds
29d878597cSMikulas Patocka typedef u32 secno; /* sector number, partition relative */
301da177e4SLinus Torvalds
311da177e4SLinus Torvalds typedef secno dnode_secno; /* sector number of a dnode */
321da177e4SLinus Torvalds typedef secno fnode_secno; /* sector number of an fnode */
331da177e4SLinus Torvalds typedef secno anode_secno; /* sector number of an anode */
341da177e4SLinus Torvalds
351da177e4SLinus Torvalds typedef u32 time32_t; /* 32-bit time_t type */
361da177e4SLinus Torvalds
371da177e4SLinus Torvalds /* sector 0 */
381da177e4SLinus Torvalds
391da177e4SLinus Torvalds /* The boot block is very like a FAT boot block, except that the
401da177e4SLinus Torvalds 29h signature byte is 28h instead, and the ID string is "HPFS". */
411da177e4SLinus Torvalds
421da177e4SLinus Torvalds #define BB_MAGIC 0xaa55
431da177e4SLinus Torvalds
441da177e4SLinus Torvalds struct hpfs_boot_block
451da177e4SLinus Torvalds {
46d878597cSMikulas Patocka u8 jmp[3];
47d878597cSMikulas Patocka u8 oem_id[8];
48d878597cSMikulas Patocka u8 bytes_per_sector[2]; /* 512 */
49d878597cSMikulas Patocka u8 sectors_per_cluster;
50d878597cSMikulas Patocka u8 n_reserved_sectors[2];
51d878597cSMikulas Patocka u8 n_fats;
52d878597cSMikulas Patocka u8 n_rootdir_entries[2];
53d878597cSMikulas Patocka u8 n_sectors_s[2];
54d878597cSMikulas Patocka u8 media_byte;
5528fe3c19SAl Viro __le16 sectors_per_fat;
5628fe3c19SAl Viro __le16 sectors_per_track;
5728fe3c19SAl Viro __le16 heads_per_cyl;
5828fe3c19SAl Viro __le32 n_hidden_sectors;
5928fe3c19SAl Viro __le32 n_sectors_l; /* size of partition */
60d878597cSMikulas Patocka u8 drive_number;
61d878597cSMikulas Patocka u8 mbz;
62d878597cSMikulas Patocka u8 sig_28h; /* 28h */
63d878597cSMikulas Patocka u8 vol_serno[4];
64d878597cSMikulas Patocka u8 vol_label[11];
65d878597cSMikulas Patocka u8 sig_hpfs[8]; /* "HPFS " */
66d878597cSMikulas Patocka u8 pad[448];
6728fe3c19SAl Viro __le16 magic; /* aa55 */
681da177e4SLinus Torvalds };
691da177e4SLinus Torvalds
701da177e4SLinus Torvalds
711da177e4SLinus Torvalds /* sector 16 */
721da177e4SLinus Torvalds
731da177e4SLinus Torvalds /* The super block has the pointer to the root directory. */
741da177e4SLinus Torvalds
751da177e4SLinus Torvalds #define SB_MAGIC 0xf995e849
761da177e4SLinus Torvalds
771da177e4SLinus Torvalds struct hpfs_super_block
781da177e4SLinus Torvalds {
7928fe3c19SAl Viro __le32 magic; /* f995 e849 */
8028fe3c19SAl Viro __le32 magic1; /* fa53 e9c5, more magic? */
81d878597cSMikulas Patocka u8 version; /* version of a filesystem usually 2 */
82d878597cSMikulas Patocka u8 funcversion; /* functional version - oldest version
831da177e4SLinus Torvalds of filesystem that can understand
841da177e4SLinus Torvalds this disk */
8528fe3c19SAl Viro __le16 zero; /* 0 */
8628fe3c19SAl Viro __le32 root; /* fnode of root directory */
8728fe3c19SAl Viro __le32 n_sectors; /* size of filesystem */
8828fe3c19SAl Viro __le32 n_badblocks; /* number of bad blocks */
8928fe3c19SAl Viro __le32 bitmaps; /* pointers to free space bit maps */
9028fe3c19SAl Viro __le32 zero1; /* 0 */
9128fe3c19SAl Viro __le32 badblocks; /* bad block list */
9228fe3c19SAl Viro __le32 zero3; /* 0 */
9328fe3c19SAl Viro __le32 last_chkdsk; /* date last checked, 0 if never */
9428fe3c19SAl Viro __le32 last_optimize; /* date last optimized, 0 if never */
9528fe3c19SAl Viro __le32 n_dir_band; /* number of sectors in dir band */
9628fe3c19SAl Viro __le32 dir_band_start; /* first sector in dir band */
9728fe3c19SAl Viro __le32 dir_band_end; /* last sector in dir band */
9828fe3c19SAl Viro __le32 dir_band_bitmap; /* free space map, 1 dnode per bit */
99d878597cSMikulas Patocka u8 volume_name[32]; /* not used */
10028fe3c19SAl Viro __le32 user_id_table; /* 8 preallocated sectors - user id */
101d878597cSMikulas Patocka u32 zero6[103]; /* 0 */
1021da177e4SLinus Torvalds };
1031da177e4SLinus Torvalds
1041da177e4SLinus Torvalds
1051da177e4SLinus Torvalds /* sector 17 */
1061da177e4SLinus Torvalds
1071da177e4SLinus Torvalds /* The spare block has pointers to spare sectors. */
1081da177e4SLinus Torvalds
1091da177e4SLinus Torvalds #define SP_MAGIC 0xf9911849
1101da177e4SLinus Torvalds
1111da177e4SLinus Torvalds struct hpfs_spare_block
1121da177e4SLinus Torvalds {
11328fe3c19SAl Viro __le32 magic; /* f991 1849 */
11428fe3c19SAl Viro __le32 magic1; /* fa52 29c5, more magic? */
1151da177e4SLinus Torvalds
1160b69760bSMikulas Patocka #ifdef __LITTLE_ENDIAN
1170b69760bSMikulas Patocka u8 dirty: 1; /* 0 clean, 1 "improperly stopped" */
1180b69760bSMikulas Patocka u8 sparedir_used: 1; /* spare dirblks used */
1190b69760bSMikulas Patocka u8 hotfixes_used: 1; /* hotfixes used */
1200b69760bSMikulas Patocka u8 bad_sector: 1; /* bad sector, corrupted disk (???) */
1210b69760bSMikulas Patocka u8 bad_bitmap: 1; /* bad bitmap */
1220b69760bSMikulas Patocka u8 fast: 1; /* partition was fast formatted */
123cb1d150dSColin Ian King u8 old_wrote: 1; /* old version wrote to partition */
124cb1d150dSColin Ian King u8 old_wrote_1: 1; /* old version wrote to partition (?) */
1250b69760bSMikulas Patocka #else
126cb1d150dSColin Ian King u8 old_wrote_1: 1; /* old version wrote to partition (?) */
127cb1d150dSColin Ian King u8 old_wrote: 1; /* old version wrote to partition */
1280b69760bSMikulas Patocka u8 fast: 1; /* partition was fast formatted */
1290b69760bSMikulas Patocka u8 bad_bitmap: 1; /* bad bitmap */
1300b69760bSMikulas Patocka u8 bad_sector: 1; /* bad sector, corrupted disk (???) */
1310b69760bSMikulas Patocka u8 hotfixes_used: 1; /* hotfixes used */
1320b69760bSMikulas Patocka u8 sparedir_used: 1; /* spare dirblks used */
1330b69760bSMikulas Patocka u8 dirty: 1; /* 0 clean, 1 "improperly stopped" */
1340b69760bSMikulas Patocka #endif
1350b69760bSMikulas Patocka
1360b69760bSMikulas Patocka #ifdef __LITTLE_ENDIAN
1370b69760bSMikulas Patocka u8 install_dasd_limits: 1; /* HPFS386 flags */
1380b69760bSMikulas Patocka u8 resynch_dasd_limits: 1;
1390b69760bSMikulas Patocka u8 dasd_limits_operational: 1;
1400b69760bSMikulas Patocka u8 multimedia_active: 1;
1410b69760bSMikulas Patocka u8 dce_acls_active: 1;
1420b69760bSMikulas Patocka u8 dasd_limits_dirty: 1;
1430b69760bSMikulas Patocka u8 flag67: 2;
1440b69760bSMikulas Patocka #else
1450b69760bSMikulas Patocka u8 flag67: 2;
1460b69760bSMikulas Patocka u8 dasd_limits_dirty: 1;
1470b69760bSMikulas Patocka u8 dce_acls_active: 1;
1480b69760bSMikulas Patocka u8 multimedia_active: 1;
1490b69760bSMikulas Patocka u8 dasd_limits_operational: 1;
1500b69760bSMikulas Patocka u8 resynch_dasd_limits: 1;
1510b69760bSMikulas Patocka u8 install_dasd_limits: 1; /* HPFS386 flags */
1520b69760bSMikulas Patocka #endif
1530b69760bSMikulas Patocka
154d878597cSMikulas Patocka u8 mm_contlgulty;
155d878597cSMikulas Patocka u8 unused;
1561da177e4SLinus Torvalds
15728fe3c19SAl Viro __le32 hotfix_map; /* info about remapped bad sectors */
15828fe3c19SAl Viro __le32 n_spares_used; /* number of hotfixes */
15928fe3c19SAl Viro __le32 n_spares; /* number of spares in hotfix map */
16028fe3c19SAl Viro __le32 n_dnode_spares_free; /* spare dnodes unused */
16128fe3c19SAl Viro __le32 n_dnode_spares; /* length of spare_dnodes[] list,
1621da177e4SLinus Torvalds follows in this block*/
16328fe3c19SAl Viro __le32 code_page_dir; /* code page directory block */
16428fe3c19SAl Viro __le32 n_code_pages; /* number of code pages */
16528fe3c19SAl Viro __le32 super_crc; /* on HPFS386 and LAN Server this is
1661da177e4SLinus Torvalds checksum of superblock, on normal
1671da177e4SLinus Torvalds OS/2 unused */
16828fe3c19SAl Viro __le32 spare_crc; /* on HPFS386 checksum of spareblock */
16928fe3c19SAl Viro __le32 zero1[15]; /* unused */
17028fe3c19SAl Viro __le32 spare_dnodes[100]; /* emergency free dnode list */
17128fe3c19SAl Viro __le32 zero2[1]; /* room for more? */
1721da177e4SLinus Torvalds };
1731da177e4SLinus Torvalds
1741da177e4SLinus Torvalds /* The bad block list is 4 sectors long. The first word must be zero,
1751da177e4SLinus Torvalds the remaining words give n_badblocks bad block numbers.
1761da177e4SLinus Torvalds I bet you can see it coming... */
1771da177e4SLinus Torvalds
1781da177e4SLinus Torvalds #define BAD_MAGIC 0
1791da177e4SLinus Torvalds
1801da177e4SLinus Torvalds /* The hotfix map is 4 sectors long. It looks like
1811da177e4SLinus Torvalds
1821da177e4SLinus Torvalds secno from[n_spares];
1831da177e4SLinus Torvalds secno to[n_spares];
1841da177e4SLinus Torvalds
1851da177e4SLinus Torvalds The to[] list is initialized to point to n_spares preallocated empty
1861da177e4SLinus Torvalds sectors. The from[] list contains the sector numbers of bad blocks
1871da177e4SLinus Torvalds which have been remapped to corresponding sectors in the to[] list.
1881da177e4SLinus Torvalds n_spares_used gives the length of the from[] list. */
1891da177e4SLinus Torvalds
1901da177e4SLinus Torvalds
1911da177e4SLinus Torvalds /* Sectors 18 and 19 are preallocated and unused.
1921da177e4SLinus Torvalds Maybe they're spares for 16 and 17, but simple substitution fails. */
1931da177e4SLinus Torvalds
1941da177e4SLinus Torvalds
1951da177e4SLinus Torvalds /* The code page info pointed to by the spare block consists of an index
1961da177e4SLinus Torvalds block and blocks containing uppercasing tables. I don't know what
1971da177e4SLinus Torvalds these are for (CHKDSK, maybe?) -- OS/2 does not seem to use them
1981da177e4SLinus Torvalds itself. Linux doesn't use them either. */
1991da177e4SLinus Torvalds
2001da177e4SLinus Torvalds /* block pointed to by spareblock->code_page_dir */
2011da177e4SLinus Torvalds
2021da177e4SLinus Torvalds #define CP_DIR_MAGIC 0x494521f7
2031da177e4SLinus Torvalds
2041da177e4SLinus Torvalds struct code_page_directory
2051da177e4SLinus Torvalds {
20628fe3c19SAl Viro __le32 magic; /* 4945 21f7 */
20728fe3c19SAl Viro __le32 n_code_pages; /* number of pointers following */
20828fe3c19SAl Viro __le32 zero1[2];
2091da177e4SLinus Torvalds struct {
21028fe3c19SAl Viro __le16 ix; /* index */
21128fe3c19SAl Viro __le16 code_page_number; /* code page number */
21228fe3c19SAl Viro __le32 bounds; /* matches corresponding word
2131da177e4SLinus Torvalds in data block */
21428fe3c19SAl Viro __le32 code_page_data; /* sector number of a code_page_data
2151da177e4SLinus Torvalds containing c.p. array */
21628fe3c19SAl Viro __le16 index; /* index in c.p. array in that sector*/
21728fe3c19SAl Viro __le16 unknown; /* some unknown value; usually 0;
2181da177e4SLinus Torvalds 2 in Japanese version */
2191da177e4SLinus Torvalds } array[31]; /* unknown length */
2201da177e4SLinus Torvalds };
2211da177e4SLinus Torvalds
2221da177e4SLinus Torvalds /* blocks pointed to by code_page_directory */
2231da177e4SLinus Torvalds
2241da177e4SLinus Torvalds #define CP_DATA_MAGIC 0x894521f7
2251da177e4SLinus Torvalds
2261da177e4SLinus Torvalds struct code_page_data
2271da177e4SLinus Torvalds {
22828fe3c19SAl Viro __le32 magic; /* 8945 21f7 */
22928fe3c19SAl Viro __le32 n_used; /* # elements used in c_p_data[] */
23028fe3c19SAl Viro __le32 bounds[3]; /* looks a bit like
2311da177e4SLinus Torvalds (beg1,end1), (beg2,end2)
2321da177e4SLinus Torvalds one byte each */
23328fe3c19SAl Viro __le16 offs[3]; /* offsets from start of sector
2341da177e4SLinus Torvalds to start of c_p_data[ix] */
2351da177e4SLinus Torvalds struct {
23628fe3c19SAl Viro __le16 ix; /* index */
23728fe3c19SAl Viro __le16 code_page_number; /* code page number */
23828fe3c19SAl Viro __le16 unknown; /* the same as in cp directory */
239d878597cSMikulas Patocka u8 map[128]; /* upcase table for chars 80..ff */
24028fe3c19SAl Viro __le16 zero2;
2411da177e4SLinus Torvalds } code_page[3];
242d878597cSMikulas Patocka u8 incognita[78];
2431da177e4SLinus Torvalds };
2441da177e4SLinus Torvalds
2451da177e4SLinus Torvalds
2461da177e4SLinus Torvalds /* Free space bitmaps are 4 sectors long, which is 16384 bits.
2471da177e4SLinus Torvalds 16384 sectors is 8 meg, and each 8 meg band has a 4-sector bitmap.
2481da177e4SLinus Torvalds Bit order in the maps is little-endian. 0 means taken, 1 means free.
2491da177e4SLinus Torvalds
2501da177e4SLinus Torvalds Bit map sectors are marked allocated in the bit maps, and so are sectors
2511da177e4SLinus Torvalds off the end of the partition.
2521da177e4SLinus Torvalds
2531da177e4SLinus Torvalds Band 0 is sectors 0-3fff, its map is in sectors 18-1b.
2541da177e4SLinus Torvalds Band 1 is 4000-7fff, its map is in 7ffc-7fff.
2551da177e4SLinus Torvalds Band 2 is 8000-ffff, its map is in 8000-8003.
2561da177e4SLinus Torvalds The remaining bands have maps in their first (even) or last (odd) 4 sectors
2571da177e4SLinus Torvalds -- if the last, partial, band is odd its map is in its last 4 sectors.
2581da177e4SLinus Torvalds
2591da177e4SLinus Torvalds The bitmap locations are given in a table pointed to by the super block.
2601da177e4SLinus Torvalds No doubt they aren't constrained to be at 18, 7ffc, 8000, ...; that is
2611da177e4SLinus Torvalds just where they usually are.
2621da177e4SLinus Torvalds
2631da177e4SLinus Torvalds The "directory band" is a bunch of sectors preallocated for dnodes.
2641da177e4SLinus Torvalds It has a 4-sector free space bitmap of its own. Each bit in the map
2651da177e4SLinus Torvalds corresponds to one 4-sector dnode, bit 0 of the map corresponding to
2661da177e4SLinus Torvalds the first 4 sectors of the directory band. The entire band is marked
2671da177e4SLinus Torvalds allocated in the main bitmap. The super block gives the locations
2681da177e4SLinus Torvalds of the directory band and its bitmap. ("band" doesn't mean it is
2691da177e4SLinus Torvalds 8 meg long; it isn't.) */
2701da177e4SLinus Torvalds
2711da177e4SLinus Torvalds
2721da177e4SLinus Torvalds /* dnode: directory. 4 sectors long */
2731da177e4SLinus Torvalds
2741da177e4SLinus Torvalds /* A directory is a tree of dnodes. The fnode for a directory
2751da177e4SLinus Torvalds contains one pointer, to the root dnode of the tree. The fnode
2761da177e4SLinus Torvalds never moves, the dnodes do the B-tree thing, splitting and merging
2771da177e4SLinus Torvalds as files are added and removed. */
2781da177e4SLinus Torvalds
2791da177e4SLinus Torvalds #define DNODE_MAGIC 0x77e40aae
2801da177e4SLinus Torvalds
2811da177e4SLinus Torvalds struct dnode {
28239413c60SAl Viro __le32 magic; /* 77e4 0aae */
28339413c60SAl Viro __le32 first_free; /* offset from start of dnode to
2841da177e4SLinus Torvalds first free dir entry */
2850b69760bSMikulas Patocka #ifdef __LITTLE_ENDIAN
2860b69760bSMikulas Patocka u8 root_dnode: 1; /* Is it root dnode? */
2870b69760bSMikulas Patocka u8 increment_me: 7; /* some kind of activity counter? */
2880b69760bSMikulas Patocka /* Neither HPFS.IFS nor CHKDSK cares
2891da177e4SLinus Torvalds if you change this word */
2900b69760bSMikulas Patocka #else
2910b69760bSMikulas Patocka u8 increment_me: 7; /* some kind of activity counter? */
2920b69760bSMikulas Patocka /* Neither HPFS.IFS nor CHKDSK cares
2930b69760bSMikulas Patocka if you change this word */
2940b69760bSMikulas Patocka u8 root_dnode: 1; /* Is it root dnode? */
2950b69760bSMikulas Patocka #endif
2960b69760bSMikulas Patocka u8 increment_me2[3];
29739413c60SAl Viro __le32 up; /* (root dnode) directory's fnode
2981da177e4SLinus Torvalds (nonroot) parent dnode */
29939413c60SAl Viro __le32 self; /* pointer to this dnode */
300d878597cSMikulas Patocka u8 dirent[2028]; /* one or more dirents */
3011da177e4SLinus Torvalds };
3021da177e4SLinus Torvalds
3031da177e4SLinus Torvalds struct hpfs_dirent {
30446287aa6SAl Viro __le16 length; /* offset to next dirent */
3050b69760bSMikulas Patocka
3060b69760bSMikulas Patocka #ifdef __LITTLE_ENDIAN
3070b69760bSMikulas Patocka u8 first: 1; /* set on phony ^A^A (".") entry */
3080b69760bSMikulas Patocka u8 has_acl: 1;
3090b69760bSMikulas Patocka u8 down: 1; /* down pointer present (after name) */
3100b69760bSMikulas Patocka u8 last: 1; /* set on phony \377 entry */
3110b69760bSMikulas Patocka u8 has_ea: 1; /* entry has EA */
3120b69760bSMikulas Patocka u8 has_xtd_perm: 1; /* has extended perm list (???) */
3130b69760bSMikulas Patocka u8 has_explicit_acl: 1;
3140b69760bSMikulas Patocka u8 has_needea: 1; /* ?? some EA has NEEDEA set
3151da177e4SLinus Torvalds I have no idea why this is
3161da177e4SLinus Torvalds interesting in a dir entry */
3170b69760bSMikulas Patocka #else
3180b69760bSMikulas Patocka u8 has_needea: 1; /* ?? some EA has NEEDEA set
3190b69760bSMikulas Patocka I have no idea why this is
3200b69760bSMikulas Patocka interesting in a dir entry */
3210b69760bSMikulas Patocka u8 has_explicit_acl: 1;
3220b69760bSMikulas Patocka u8 has_xtd_perm: 1; /* has extended perm list (???) */
3230b69760bSMikulas Patocka u8 has_ea: 1; /* entry has EA */
3240b69760bSMikulas Patocka u8 last: 1; /* set on phony \377 entry */
3250b69760bSMikulas Patocka u8 down: 1; /* down pointer present (after name) */
3260b69760bSMikulas Patocka u8 has_acl: 1;
3270b69760bSMikulas Patocka u8 first: 1; /* set on phony ^A^A (".") entry */
3280b69760bSMikulas Patocka #endif
3290b69760bSMikulas Patocka
3300b69760bSMikulas Patocka #ifdef __LITTLE_ENDIAN
3310b69760bSMikulas Patocka u8 read_only: 1; /* dos attrib */
3320b69760bSMikulas Patocka u8 hidden: 1; /* dos attrib */
3330b69760bSMikulas Patocka u8 system: 1; /* dos attrib */
3340b69760bSMikulas Patocka u8 flag11: 1; /* would be volume label dos attrib */
3350b69760bSMikulas Patocka u8 directory: 1; /* dos attrib */
3360b69760bSMikulas Patocka u8 archive: 1; /* dos attrib */
3370b69760bSMikulas Patocka u8 not_8x3: 1; /* name is not 8.3 */
3380b69760bSMikulas Patocka u8 flag15: 1;
3390b69760bSMikulas Patocka #else
3400b69760bSMikulas Patocka u8 flag15: 1;
3410b69760bSMikulas Patocka u8 not_8x3: 1; /* name is not 8.3 */
3420b69760bSMikulas Patocka u8 archive: 1; /* dos attrib */
3430b69760bSMikulas Patocka u8 directory: 1; /* dos attrib */
3440b69760bSMikulas Patocka u8 flag11: 1; /* would be volume label dos attrib */
3450b69760bSMikulas Patocka u8 system: 1; /* dos attrib */
3460b69760bSMikulas Patocka u8 hidden: 1; /* dos attrib */
3470b69760bSMikulas Patocka u8 read_only: 1; /* dos attrib */
3480b69760bSMikulas Patocka #endif
3490b69760bSMikulas Patocka
35046287aa6SAl Viro __le32 fnode; /* fnode giving allocation info */
35146287aa6SAl Viro __le32 write_date; /* mtime */
35246287aa6SAl Viro __le32 file_size; /* file length, bytes */
35346287aa6SAl Viro __le32 read_date; /* atime */
35446287aa6SAl Viro __le32 creation_date; /* ctime */
35546287aa6SAl Viro __le32 ea_size; /* total EA length, bytes */
3560b69760bSMikulas Patocka u8 no_of_acls; /* number of ACL's (low 3 bits) */
357d878597cSMikulas Patocka u8 ix; /* code page index (of filename), see
3581da177e4SLinus Torvalds struct code_page_data */
359c1e4726fSGustavo A. R. Silva u8 namelen; /* file name length */
360c1e4726fSGustavo A. R. Silva u8 name[]; /* file name */
3611da177e4SLinus Torvalds /* dnode_secno down; btree down pointer, if present,
3621da177e4SLinus Torvalds follows name on next word boundary, or maybe it
3631da177e4SLinus Torvalds precedes next dirent, which is on a word boundary. */
3641da177e4SLinus Torvalds };
3651da177e4SLinus Torvalds
3661da177e4SLinus Torvalds
3671da177e4SLinus Torvalds /* B+ tree: allocation info in fnodes and anodes */
3681da177e4SLinus Torvalds
3691da177e4SLinus Torvalds /* dnodes point to fnodes which are responsible for listing the sectors
3701da177e4SLinus Torvalds assigned to the file. This is done with trees of (length,address)
3711da177e4SLinus Torvalds pairs. (Actually triples, of (length, file-address, disk-address)
3721da177e4SLinus Torvalds which can represent holes. Find out if HPFS does that.)
3731da177e4SLinus Torvalds At any rate, fnodes contain a small tree; if subtrees are needed
3741da177e4SLinus Torvalds they occupy essentially a full block in anodes. A leaf-level tree node
3751da177e4SLinus Torvalds has 3-word entries giving sector runs, a non-leaf node has 2-word
3761da177e4SLinus Torvalds entries giving subtree pointers. A flag in the header says which. */
3771da177e4SLinus Torvalds
3781da177e4SLinus Torvalds struct bplus_leaf_node
3791da177e4SLinus Torvalds {
380ddc19e6eSAl Viro __le32 file_secno; /* first file sector in extent */
381ddc19e6eSAl Viro __le32 length; /* length, sectors */
382ddc19e6eSAl Viro __le32 disk_secno; /* first corresponding disk sector */
3831da177e4SLinus Torvalds };
3841da177e4SLinus Torvalds
3851da177e4SLinus Torvalds struct bplus_internal_node
3861da177e4SLinus Torvalds {
387ddc19e6eSAl Viro __le32 file_secno; /* subtree maps sectors < this */
388ddc19e6eSAl Viro __le32 down; /* pointer to subtree */
3891da177e4SLinus Torvalds };
3901da177e4SLinus Torvalds
391ddc19e6eSAl Viro enum {
392ddc19e6eSAl Viro BP_hbff = 1,
393ddc19e6eSAl Viro BP_fnode_parent = 0x20,
394ddc19e6eSAl Viro BP_binary_search = 0x40,
395ddc19e6eSAl Viro BP_internal = 0x80
396ddc19e6eSAl Viro };
3971da177e4SLinus Torvalds struct bplus_header
3981da177e4SLinus Torvalds {
399ddc19e6eSAl Viro u8 flags; /* bit 0 - high bit of first free entry offset
400ddc19e6eSAl Viro bit 5 - we're pointed to by an fnode,
4011da177e4SLinus Torvalds the data btree or some ea or the
402ddc19e6eSAl Viro main ea bootage pointer ea_secno
403ddc19e6eSAl Viro bit 6 - suggest binary search (unused)
404ddc19e6eSAl Viro bit 7 - 1 -> (internal) tree of anodes
4051da177e4SLinus Torvalds 0 -> (leaf) list of extents */
406d878597cSMikulas Patocka u8 fill[3];
407d878597cSMikulas Patocka u8 n_free_nodes; /* free nodes in following array */
408d878597cSMikulas Patocka u8 n_used_nodes; /* used nodes in following array */
409ddc19e6eSAl Viro __le16 first_free; /* offset from start of header to
4101da177e4SLinus Torvalds first free node in array */
4111da177e4SLinus Torvalds union {
412*fa7845cfSKees Cook /* (internal) 2-word entries giving subtree pointers */
413*fa7845cfSKees Cook DECLARE_FLEX_ARRAY(struct bplus_internal_node, internal);
414*fa7845cfSKees Cook /* (external) 3-word entries giving sector runs */
415*fa7845cfSKees Cook DECLARE_FLEX_ARRAY(struct bplus_leaf_node, external);
4161da177e4SLinus Torvalds } u;
4171da177e4SLinus Torvalds };
4181da177e4SLinus Torvalds
bp_internal(struct bplus_header * bp)419ddc19e6eSAl Viro static inline bool bp_internal(struct bplus_header *bp)
420ddc19e6eSAl Viro {
421ddc19e6eSAl Viro return bp->flags & BP_internal;
422ddc19e6eSAl Viro }
423ddc19e6eSAl Viro
bp_fnode_parent(struct bplus_header * bp)424ddc19e6eSAl Viro static inline bool bp_fnode_parent(struct bplus_header *bp)
425ddc19e6eSAl Viro {
426ddc19e6eSAl Viro return bp->flags & BP_fnode_parent;
427ddc19e6eSAl Viro }
428ddc19e6eSAl Viro
4291da177e4SLinus Torvalds /* fnode: root of allocation b+ tree, and EA's */
4301da177e4SLinus Torvalds
4311da177e4SLinus Torvalds /* Every file and every directory has one fnode, pointed to by the directory
4321da177e4SLinus Torvalds entry and pointing to the file's sectors or directory's root dnode. EA's
4331da177e4SLinus Torvalds are also stored here, and there are said to be ACL's somewhere here too. */
4341da177e4SLinus Torvalds
4351da177e4SLinus Torvalds #define FNODE_MAGIC 0xf7e40aae
4361da177e4SLinus Torvalds
437c4c99543SAl Viro enum {FNODE_anode = cpu_to_le16(2), FNODE_dir = cpu_to_le16(256)};
4381da177e4SLinus Torvalds struct fnode
4391da177e4SLinus Torvalds {
4402b9f1cc2SAl Viro __le32 magic; /* f7e4 0aae */
4412b9f1cc2SAl Viro __le32 zero1[2]; /* read history */
442d878597cSMikulas Patocka u8 len, name[15]; /* true length, truncated name */
4432b9f1cc2SAl Viro __le32 up; /* pointer to file's directory fnode */
4442b9f1cc2SAl Viro __le32 acl_size_l;
4452b9f1cc2SAl Viro __le32 acl_secno;
4462b9f1cc2SAl Viro __le16 acl_size_s;
447d878597cSMikulas Patocka u8 acl_anode;
448d878597cSMikulas Patocka u8 zero2; /* history bit count */
4492b9f1cc2SAl Viro __le32 ea_size_l; /* length of disk-resident ea's */
4502b9f1cc2SAl Viro __le32 ea_secno; /* first sector of disk-resident ea's*/
4512b9f1cc2SAl Viro __le16 ea_size_s; /* length of fnode-resident ea's */
4521da177e4SLinus Torvalds
453c4c99543SAl Viro __le16 flags; /* bit 1 set -> ea_secno is an anode */
454c4c99543SAl Viro /* bit 8 set -> directory. first & only extent
4551da177e4SLinus Torvalds points to dnode. */
4561da177e4SLinus Torvalds struct bplus_header btree; /* b+ tree, 8 extents or 12 subtrees */
4571da177e4SLinus Torvalds union {
4581da177e4SLinus Torvalds struct bplus_leaf_node external[8];
4591da177e4SLinus Torvalds struct bplus_internal_node internal[12];
4601da177e4SLinus Torvalds } u;
4611da177e4SLinus Torvalds
4622b9f1cc2SAl Viro __le32 file_size; /* file length, bytes */
4632b9f1cc2SAl Viro __le32 n_needea; /* number of EA's with NEEDEA set */
464d878597cSMikulas Patocka u8 user_id[16]; /* unused */
4652b9f1cc2SAl Viro __le16 ea_offs; /* offset from start of fnode
4661da177e4SLinus Torvalds to first fnode-resident ea */
467d878597cSMikulas Patocka u8 dasd_limit_treshhold;
468d878597cSMikulas Patocka u8 dasd_limit_delta;
4692b9f1cc2SAl Viro __le32 dasd_limit;
4702b9f1cc2SAl Viro __le32 dasd_usage;
471d878597cSMikulas Patocka u8 ea[316]; /* zero or more EA's, packed together
4721da177e4SLinus Torvalds with no alignment padding.
4731da177e4SLinus Torvalds (Do not use this name, get here
4741da177e4SLinus Torvalds via fnode + ea_offs. I think.) */
4751da177e4SLinus Torvalds };
4761da177e4SLinus Torvalds
fnode_in_anode(struct fnode * p)477c4c99543SAl Viro static inline bool fnode_in_anode(struct fnode *p)
478c4c99543SAl Viro {
479c4c99543SAl Viro return (p->flags & FNODE_anode) != 0;
480c4c99543SAl Viro }
481c4c99543SAl Viro
fnode_is_dir(struct fnode * p)482c4c99543SAl Viro static inline bool fnode_is_dir(struct fnode *p)
483c4c99543SAl Viro {
484c4c99543SAl Viro return (p->flags & FNODE_dir) != 0;
485c4c99543SAl Viro }
486c4c99543SAl Viro
4871da177e4SLinus Torvalds
4881da177e4SLinus Torvalds /* anode: 99.44% pure allocation tree */
4891da177e4SLinus Torvalds
4901da177e4SLinus Torvalds #define ANODE_MAGIC 0x37e40aae
4911da177e4SLinus Torvalds
4921da177e4SLinus Torvalds struct anode
4931da177e4SLinus Torvalds {
4946ce2bbbaSAl Viro __le32 magic; /* 37e4 0aae */
4956ce2bbbaSAl Viro __le32 self; /* pointer to this anode */
4966ce2bbbaSAl Viro __le32 up; /* parent anode or fnode */
4971da177e4SLinus Torvalds
4981da177e4SLinus Torvalds struct bplus_header btree; /* b+tree, 40 extents or 60 subtrees */
4991da177e4SLinus Torvalds union {
5001da177e4SLinus Torvalds struct bplus_leaf_node external[40];
5011da177e4SLinus Torvalds struct bplus_internal_node internal[60];
5021da177e4SLinus Torvalds } u;
5031da177e4SLinus Torvalds
5046ce2bbbaSAl Viro __le32 fill[3]; /* unused */
5051da177e4SLinus Torvalds };
5061da177e4SLinus Torvalds
5071da177e4SLinus Torvalds
5081da177e4SLinus Torvalds /* extended attributes.
5091da177e4SLinus Torvalds
5101da177e4SLinus Torvalds A file's EA info is stored as a list of (name,value) pairs. It is
5111da177e4SLinus Torvalds usually in the fnode, but (if it's large) it is moved to a single
5121da177e4SLinus Torvalds sector run outside the fnode, or to multiple runs with an anode tree
5131da177e4SLinus Torvalds that points to them.
5141da177e4SLinus Torvalds
5151da177e4SLinus Torvalds The value of a single EA is stored along with the name, or (if large)
5161da177e4SLinus Torvalds it is moved to a single sector run, or multiple runs pointed to by an
5171da177e4SLinus Torvalds anode tree, pointed to by the value field of the (name,value) pair.
5181da177e4SLinus Torvalds
5191da177e4SLinus Torvalds Flags in the EA tell whether the value is immediate, in a single sector
5201da177e4SLinus Torvalds run, or in multiple runs. Flags in the fnode tell whether the EA list
5211da177e4SLinus Torvalds is immediate, in a single run, or in multiple runs. */
5221da177e4SLinus Torvalds
5234085e155SAl Viro enum {EA_indirect = 1, EA_anode = 2, EA_needea = 128 };
5241da177e4SLinus Torvalds struct extended_attribute
5251da177e4SLinus Torvalds {
5264085e155SAl Viro u8 flags; /* bit 0 set -> value gives sector number
5271da177e4SLinus Torvalds where real value starts */
5284085e155SAl Viro /* bit 1 set -> sector is an anode
5291da177e4SLinus Torvalds that points to fragmented value */
5304085e155SAl Viro /* bit 7 set -> required ea */
531d878597cSMikulas Patocka u8 namelen; /* length of name, bytes */
532d0969d19SMikulas Patocka u8 valuelen_lo; /* length of value, bytes */
533d0969d19SMikulas Patocka u8 valuelen_hi; /* length of value, bytes */
5344085e155SAl Viro u8 name[];
5351da177e4SLinus Torvalds /*
536d878597cSMikulas Patocka u8 name[namelen]; ascii attrib name
537d878597cSMikulas Patocka u8 nul; terminating '\0', not counted
538d878597cSMikulas Patocka u8 value[valuelen]; value, arbitrary
5394085e155SAl Viro if this.flags & 1, valuelen is 8 and the value is
540d878597cSMikulas Patocka u32 length; real length of value, bytes
5411da177e4SLinus Torvalds secno secno; sector address where it starts
5421da177e4SLinus Torvalds if this.anode, the above sector number is the root of an anode tree
5431da177e4SLinus Torvalds which points to the value.
5441da177e4SLinus Torvalds */
5451da177e4SLinus Torvalds };
5461da177e4SLinus Torvalds
ea_indirect(struct extended_attribute * ea)5474085e155SAl Viro static inline bool ea_indirect(struct extended_attribute *ea)
5484085e155SAl Viro {
5494085e155SAl Viro return ea->flags & EA_indirect;
5504085e155SAl Viro }
5514085e155SAl Viro
ea_in_anode(struct extended_attribute * ea)5524085e155SAl Viro static inline bool ea_in_anode(struct extended_attribute *ea)
5534085e155SAl Viro {
5544085e155SAl Viro return ea->flags & EA_anode;
5554085e155SAl Viro }
5564085e155SAl Viro
5571da177e4SLinus Torvalds /*
5581da177e4SLinus Torvalds Local Variables:
5591da177e4SLinus Torvalds comment-column: 40
5601da177e4SLinus Torvalds End:
5611da177e4SLinus Torvalds */
562