?? hpfs.h
字號:
time_t write_date; /* mtime */
unsigned file_size; /* file length, bytes */
time_t read_date; /* atime */
time_t creation_date; /* ctime */
unsigned ea_size; /* total EA length, bytes */
unsigned char zero1;
unsigned char locality; /* 0=unk 1=seq 2=random 3=both */
unsigned char namelen, name[1]; /* file name */
/* dnode_secno down; btree down pointer, if present,
follows name on next word boundary, or maybe it's
precedes next dirent, which is on a word boundary. */
};
/* The b-tree down pointer from a dir entry */
static inline dnode_secno de_down_pointer (struct hpfs_dirent *de)
{
return *(dnode_secno *) ((void *) de + de->length - 4);
}
/* The first dir entry in a dnode */
static inline struct hpfs_dirent *dnode_first_de (struct dnode *dnode)
{
return (void *) dnode->dirent;
}
/* The end+1 of the dir entries */
static inline struct hpfs_dirent *dnode_end_de (struct dnode *dnode)
{
return (void *) dnode + dnode->first_free;
}
/* The dir entry after dir entry de */
static inline struct hpfs_dirent *de_next_de (struct hpfs_dirent *de)
{
return (void *) de + de->length;
}
/* 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
{
unsigned file_secno; /* first file sector in extent */
unsigned length; /* length, sectors */
secno disk_secno; /* first corresponding disk sector */
};
struct bplus_internal_node
{
unsigned file_secno; /* subtree maps sectors < this */
anode_secno down; /* pointer to subtree */
};
struct bplus_header
{
unsigned flag0: 1;
unsigned flag1: 1;
unsigned flag2: 1;
unsigned flag3: 1;
unsigned flag4: 1;
unsigned fnode_parent: 1; /* ? we're pointed to by an fnode,
the data btree or some ea or the
main ea bootage pointer ea_secno */
/* also can get set in fnodes, which
may be a chkdsk glitch or may mean
this bit is irrelevant in fnodes,
or this interpretation is all wet */
unsigned flag6: 1;
unsigned internal: 1; /* 1 -> (internal) tree of anodes
0 -> (leaf) list of extents */
unsigned char fill[3];
unsigned char n_free_nodes; /* free nodes in following array */
unsigned char n_used_nodes; /* used nodes in following array */
unsigned short first_free; /* offset from start of header to
first free node in array */
union {
struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving
subtree pointers */
struct bplus_leaf_node external[0]; /* (external) 3-word entries giving
sector runs */
} u;
};
/* 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 0xf7e40aae
struct fnode
{
unsigned magic; /* f7e4 0aae */
unsigned zero1[2];
unsigned char len, name[15]; /* true length, truncated name */
fnode_secno up; /* pointer to file's directory fnode */
unsigned zero2[3];
unsigned ea_size_l; /* length of disk-resident ea's */
secno ea_secno; /* first sector of disk-resident ea's*/
unsigned short ea_size_s; /* length of fnode-resident ea's */
unsigned flag0: 1;
unsigned ea_anode: 1; /* 1 -> ea_secno is an anode */
unsigned flag2: 1;
unsigned flag3: 1;
unsigned flag4: 1;
unsigned flag5: 1;
unsigned flag6: 1;
unsigned flag7: 1;
unsigned dirflag: 1; /* 1 -> directory. first & only extent
points to dnode. */
unsigned flag9: 1;
unsigned flag10: 1;
unsigned flag11: 1;
unsigned flag12: 1;
unsigned flag13: 1;
unsigned flag14: 1;
unsigned flag15: 1;
struct bplus_header btree; /* b+ tree, 8 extents or 12 subtrees */
union {
struct bplus_leaf_node external[8];
struct bplus_internal_node internal[12];
} u;
unsigned file_size; /* file length, bytes */
unsigned n_needea; /* number of EA's with NEEDEA set */
unsigned zero4[4];
unsigned ea_offs; /* offset from start of fnode
to first fnode-resident ea */
unsigned zero5[2];
unsigned char ea[316]; /* zero or more EA's, packed together
with no alignment padding.
(Do not use this name, get here
via fnode + ea_offs. I think.) */
};
/* anode: 99.44% pure allocation tree */
#define ANODE_MAGIC 0x37e40aae
struct anode
{
unsigned magic; /* 37e4 0aae */
anode_secno self; /* pointer to this anode */
secno up; /* parent anode or fnode */
struct bplus_header btree; /* b+tree, 40 extents or 60 subtrees */
union {
struct bplus_leaf_node external[40];
struct bplus_internal_node internal[60];
} u;
unsigned fill[3]; /* unused */
};
/* 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. */
struct extended_attribute
{
unsigned indirect: 1; /* 1 -> value gives sector number
where real value starts */
unsigned anode: 1; /* 1 -> sector is an anode
that points to fragmented value */
unsigned flag2: 1;
unsigned flag3: 1;
unsigned flag4: 1;
unsigned flag5: 1;
unsigned flag6: 1;
unsigned needea: 1; /* required ea */
unsigned char namelen; /* length of name, bytes */
unsigned short valuelen; /* length of value, bytes */
/*
unsigned char name[namelen]; ascii attrib name
unsigned char nul; terminating '\0', not counted
unsigned char value[valuelen]; value, arbitrary
if this.indirect, valuelen is 8 and the value is
unsigned length; real length of value, bytes
secno secno; sector address where it starts
if this.anode, the above sector number is the root of an anode tree
which points to the value.
*/
};
static inline unsigned char *ea_name (struct extended_attribute *ea)
{
return (void *) ea + sizeof *ea;
}
static inline unsigned char *ea_value (struct extended_attribute *ea)
{
return (void *) ea + sizeof *ea + ea->namelen + 1;
}
static inline struct extended_attribute *
ea_next_ea (struct extended_attribute *ea)
{
return (void *) ea + sizeof *ea + ea->namelen + 1 + ea->valuelen;
}
static inline unsigned ea_indirect_length (struct extended_attribute *ea)
{
unsigned *v = (void *) ea_value (ea);
return v[0];
}
static inline secno ea_indirect_secno (struct extended_attribute *ea)
{
unsigned *v = (void *) ea_value (ea);
return v[1];
}
/*
Local Variables:
comment-column: 40
End:
*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -