linux/fs/hpfs/hpfs.h

/* SPDX-License-Identifier: GPL-2.0 */
/*
 *  linux/fs/hpfs/hpfs.h
 *
 *  HPFS structures by Chris Smith, 1993
 *
 *  a little bit modified by Mikulas Patocka, 1998-1999
 */

/* The paper

     Duncan, Roy
     Design goals and implementation of the new High Performance File System
     Microsoft Systems Journal  Sept 1989  v4 n5 p1(13)

   describes what HPFS looked like when it was new, and it is the source
   of most of the information given here.  The rest is conjecture.

   For definitive information on the Duncan paper, see it, not this file.
   For definitive information on HPFS, ask somebody else -- this is guesswork.
   There are certain to be many mistakes. */

#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
#error unknown endian
#endif

/* Notation */

secno;			/* sector number, partition relative */

dnode_secno;		/* sector number of a dnode */
fnode_secno;		/* sector number of an fnode */
anode_secno;		/* sector number of an anode */

time32_t;		/* 32-bit time_t type */

/* sector 0 */

/* The boot block is very like a FAT boot block, except that the
   29h signature byte is 28h instead, and the ID string is "HPFS". */

#define BB_MAGIC

struct hpfs_boot_block
{};


/* sector 16 */

/* The super block has the pointer to the root directory. */

#define SB_MAGIC

struct hpfs_super_block
{};


/* sector 17 */

/* The spare block has pointers to spare sectors.  */

#define SP_MAGIC

struct hpfs_spare_block
{};

/* The bad block list is 4 sectors long.  The first word must be zero,
   the remaining words give n_badblocks bad block numbers.
   I bet you can see it coming... */

#define BAD_MAGIC
       
/* The hotfix map is 4 sectors long.  It looks like

       secno from[n_spares];
       secno to[n_spares];

   The to[] list is initialized to point to n_spares preallocated empty
   sectors.  The from[] list contains the sector numbers of bad blocks
   which have been remapped to corresponding sectors in the to[] list.
   n_spares_used gives the length of the from[] list. */


/* Sectors 18 and 19 are preallocated and unused.
   Maybe they're spares for 16 and 17, but simple substitution fails. */


/* The code page info pointed to by the spare block consists of an index
   block and blocks containing uppercasing tables.  I don't know what
   these are for (CHKDSK, maybe?) -- OS/2 does not seem to use them
   itself.  Linux doesn't use them either. */

/* block pointed to by spareblock->code_page_dir */

#define CP_DIR_MAGIC

struct code_page_directory
{};

/* blocks pointed to by code_page_directory */

#define CP_DATA_MAGIC

struct code_page_data
{};


/* Free space bitmaps are 4 sectors long, which is 16384 bits.
   16384 sectors is 8 meg, and each 8 meg band has a 4-sector bitmap.
   Bit order in the maps is little-endian.  0 means taken, 1 means free.

   Bit map sectors are marked allocated in the bit maps, and so are sectors 
   off the end of the partition.

   Band 0 is sectors 0-3fff, its map is in sectors 18-1b.
   Band 1 is 4000-7fff, its map is in 7ffc-7fff.
   Band 2 is 8000-ffff, its map is in 8000-8003.
   The remaining bands have maps in their first (even) or last (odd) 4 sectors
     -- if the last, partial, band is odd its map is in its last 4 sectors.

   The bitmap locations are given in a table pointed to by the super block.
   No doubt they aren't constrained to be at 18, 7ffc, 8000, ...; that is
   just where they usually are.

   The "directory band" is a bunch of sectors preallocated for dnodes.
   It has a 4-sector free space bitmap of its own.  Each bit in the map
   corresponds to one 4-sector dnode, bit 0 of the map corresponding to
   the first 4 sectors of the directory band.  The entire band is marked
   allocated in the main bitmap.   The super block gives the locations
   of the directory band and its bitmap.  ("band" doesn't mean it is
   8 meg long; it isn't.)  */


/* dnode: directory.  4 sectors long */

/* A directory is a tree of dnodes.  The fnode for a directory
   contains one pointer, to the root dnode of the tree.  The fnode
   never moves, the dnodes do the B-tree thing, splitting and merging
   as files are added and removed.  */

#define DNODE_MAGIC

struct dnode {};

struct hpfs_dirent {};


/* B+ tree: allocation info in fnodes and anodes */

/* dnodes point to fnodes which are responsible for listing the sectors
   assigned to the file.  This is done with trees of (length,address)
   pairs.  (Actually triples, of (length, file-address, disk-address)
   which can represent holes.  Find out if HPFS does that.)
   At any rate, fnodes contain a small tree; if subtrees are needed
   they occupy essentially a full block in anodes.  A leaf-level tree node
   has 3-word entries giving sector runs, a non-leaf node has 2-word
   entries giving subtree pointers.  A flag in the header says which. */

struct bplus_leaf_node
{};

struct bplus_internal_node
{};

enum {};
struct bplus_header
{};

static inline bool bp_internal(struct bplus_header *bp)
{}

static inline bool bp_fnode_parent(struct bplus_header *bp)
{}

/* fnode: root of allocation b+ tree, and EA's */

/* Every file and every directory has one fnode, pointed to by the directory
   entry and pointing to the file's sectors or directory's root dnode.  EA's
   are also stored here, and there are said to be ACL's somewhere here too. */

#define FNODE_MAGIC

enum {};
struct fnode
{};

static inline bool fnode_in_anode(struct fnode *p)
{}

static inline bool fnode_is_dir(struct fnode *p)
{}


/* anode: 99.44% pure allocation tree */

#define ANODE_MAGIC

struct anode
{};


/* extended attributes.

   A file's EA info is stored as a list of (name,value) pairs.  It is
   usually in the fnode, but (if it's large) it is moved to a single
   sector run outside the fnode, or to multiple runs with an anode tree
   that points to them.

   The value of a single EA is stored along with the name, or (if large)
   it is moved to a single sector run, or multiple runs pointed to by an
   anode tree, pointed to by the value field of the (name,value) pair.

   Flags in the EA tell whether the value is immediate, in a single sector
   run, or in multiple runs.  Flags in the fnode tell whether the EA list
   is immediate, in a single run, or in multiple runs. */

enum {};
struct extended_attribute
{};

static inline bool ea_indirect(struct extended_attribute *ea)
{}

static inline bool ea_in_anode(struct extended_attribute *ea)
{}

/*
   Local Variables:
   comment-column: 40
   End:
*/