home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / hpfslinx.zip / hpfs-lnx.pat < prev    next >
Text File  |  1993-10-11  |  64KB  |  2,006 lines

  1. diff -rc2N linux-dist/config.in linux/config.in
  2. *** linux-dist/config.in    Fri Sep 17 14:00:40 1993
  3. --- linux/config.in    Sun Oct 10 12:17:35 1993
  4. ***************
  5. *** 79,82 ****
  6. --- 79,83 ----
  7.   bool 'NFS filesystem support' CONFIG_NFS_FS y
  8.   bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
  9. + bool 'OS/2 HPFS filesystem support' CONFIG_HPFS_FS n
  10.   *
  11.   *  character devices
  12. diff -rc2N linux-dist/fs/Makefile linux/fs/Makefile
  13. *** linux-dist/fs/Makefile    Fri Aug 20 08:59:30 1993
  14. --- linux/fs/Makefile    Sun Oct 10 12:17:35 1993
  15. ***************
  16. *** 8,12 ****
  17.   # Note 2! The CFLAGS definitions are now in the main makefile...
  18.   
  19. ! SUBDIRS = minix ext ext2 msdos proc isofs nfs xiafs
  20.   
  21.   ifdef CONFIG_MINIX_FS
  22. --- 8,12 ----
  23.   # Note 2! The CFLAGS definitions are now in the main makefile...
  24.   
  25. ! SUBDIRS = minix ext ext2 msdos proc isofs nfs xiafs hpfs
  26.   
  27.   ifdef CONFIG_MINIX_FS
  28. ***************
  29. *** 33,36 ****
  30. --- 33,39 ----
  31.   ifdef CONFIG_XIA_FS
  32.   FS_SUBDIRS := $(FS_SUBDIRS) xiafs
  33. + endif
  34. + ifdef CONFIG_HPFS_FS
  35. + FS_SUBDIRS := $(FS_SUBDIRS) hpfs
  36.   endif
  37.   
  38. diff -rc2N linux-dist/fs/filesystems.c linux/fs/filesystems.c
  39. *** linux-dist/fs/filesystems.c    Sun Apr  4 07:08:51 1993
  40. --- linux/fs/filesystems.c    Sun Oct 10 12:17:35 1993
  41. ***************
  42. *** 33,36 ****
  43. --- 33,39 ----
  44.   #include <linux/iso_fs.h>
  45.   #endif
  46. + #ifdef CONFIG_HPFS_FS
  47. + #include <linux/hpfs_fs.h>
  48. + #endif
  49.   
  50.   struct file_system_type file_systems[] = {
  51. ***************
  52. *** 58,61 ****
  53. --- 61,67 ----
  54.   #ifdef CONFIG_ISO9660_FS
  55.       {isofs_read_super,    "iso9660",    1},
  56. + #endif
  57. + #ifdef CONFIG_HPFS_FS
  58. +     {hpfs_read_super,    "hpfs",        1},
  59.   #endif
  60.       {NULL,            NULL,        0}
  61. diff -rc2N linux-dist/fs/hpfs/Makefile linux/fs/hpfs/Makefile
  62. *** linux-dist/fs/hpfs/Makefile
  63. --- linux/fs/hpfs/Makefile    Sun Oct 10 12:18:35 1993
  64. ***************
  65. *** 0 ****
  66. --- 1,33 ----
  67. + #
  68. + # Makefile for the linux HPFS filesystem routines.
  69. + #
  70. + # Note! Dependencies are done automagically by 'make dep', which also
  71. + # removes any old dependencies. DON'T put your own dependencies here
  72. + # unless it's something special (ie not a .c file).
  73. + #
  74. + # Note 2! The CFLAGS definitions are now in the main makefile...
  75. + .c.s:
  76. +     $(CC) $(CFLAGS) -S $<
  77. + .c.o:
  78. +     $(CC) $(CFLAGS) -c $<
  79. + .s.o:
  80. +     $(AS) -o $*.o $<
  81. + OBJS=    hpfs_fs.o
  82. + hpfs.o: $(OBJS)
  83. +     ln -f hpfs_fs.o hpfs.o
  84. + clean:
  85. +     rm -f core *.o *.a *.s
  86. + dep:
  87. +     $(CPP) -M *.c > .depend
  88. + #
  89. + # include a dependency file if one exists
  90. + #
  91. + ifeq (.depend,$(wildcard .depend))
  92. + include .depend
  93. + endif
  94. diff -rc2N linux-dist/fs/hpfs/hpfs.h linux/fs/hpfs/hpfs.h
  95. *** linux-dist/fs/hpfs/hpfs.h
  96. --- linux/fs/hpfs/hpfs.h    Sun Oct 10 12:17:36 1993
  97. ***************
  98. *** 0 ****
  99. --- 1,383 ----
  100. + /* The article
  101. +      Duncan, Roy
  102. +      Design goals and implementation of the new High Performance File System
  103. +      Microsoft Systems Journal  Sept 1989  v4 n5 p1(13)
  104. +    describes what HPFS looked like when it was new, and it is the source
  105. +    of most of the information given here.  The rest is conjecture.
  106. +    For definitive information on the Duncan article, see it, not this file.
  107. +    For definitive information on HPFS, ask somebody else -- this is guesswork.
  108. +    There are certain to be many mistakes. */
  109. + /* Notation */
  110. + typedef unsigned secno;            /* sector number, partition relative */
  111. + typedef secno dnode_secno;        /* sector number of a dnode */
  112. + typedef secno fnode_secno;        /* sector number of an fnode */
  113. + typedef secno anode_secno;        /* sector number of an anode */
  114. + /* sector 0 */
  115. + /* The boot block is very like a FAT boot block, except that the
  116. +    29h signature byte is 28h instead, and the sig string is "HPFS". */
  117. + struct hpfs_boot_block
  118. + {
  119. +   unsigned char jmp[3];
  120. +   unsigned char oem_id[8];
  121. +   unsigned char bytes_per_sector[2];    /* 512 */
  122. +   unsigned char sectors_per_cluster;
  123. +   unsigned char n_reserved_sectors[2];
  124. +   unsigned char n_fats;
  125. +   unsigned char n_rootdir_entries[2];
  126. +   unsigned char n_sectors_s[2];
  127. +   unsigned char media_byte;
  128. +   unsigned short sectors_per_fat;
  129. +   unsigned short sectors_per_track;
  130. +   unsigned short heads_per_cyl;
  131. +   unsigned int n_hidden_sectors;
  132. +   unsigned int n_sectors_l;        /* size of partition */
  133. +   unsigned char drive_number;
  134. +   unsigned char mbz;
  135. +   unsigned char sig_28h;        /* 28h */
  136. +   unsigned char vol_serno[4];
  137. +   unsigned char vol_label[11];
  138. +   unsigned char sig_hpfs[8];        /* "HPFS    " */
  139. +   unsigned char pad[450];
  140. + };
  141. + /* sector 10h */
  142. + /* The super block has the pointer to the root directory. */
  143. + #define SB_MAGIC 0xf995e849
  144. + struct hpfs_super_block
  145. + {
  146. +   unsigned magic;            /* f995 e849 */
  147. +   unsigned magic1;            /* fa53 e9c5, more magic? */
  148. +   unsigned huh202;            /* 202 ?? version number(s)?
  149. +                           sector size again?
  150. +                              dnode multiplier?
  151. +                           n_spare_dnodes? */
  152. +   fnode_secno root;            /* fnode of root directory */
  153. +   secno n_sectors;            /* size of filesystem */
  154. +   unsigned zero1;            /* 0 */
  155. +   secno huh4;                /* 14  ?? 4 sectors long, has pointer
  156. +                              to band0 free space bitmap
  157. +                           and many zeros */
  158. +   unsigned zero2;            /* 0 */
  159. +   secno huh6;                /* 1c  ?? 4 sectors long, all zeros.
  160. +                               bad block list? */
  161. +   unsigned zero3;            /* 0 */
  162. +   time_t last_chkdsk;            /* date last checked, 0 if never */
  163. +   unsigned zero4;            /* 0 */
  164. +   secno n_dir_band;            /* number of sectors in dir band */
  165. +   secno dir_band_start;            /* first sector in dir band */
  166. +   secno dir_band_end;            /* last sector in dir band */
  167. +   secno dir_band_bitmap;        /* free space map, 1 dnode per bit */
  168. +   unsigned zero5[8];            /* 0 */
  169. +   secno spare_dnodes;            /* ?? 8 preallocated sectors near dir
  170. +                        band.  the node splitting spares? */
  171. +   unsigned pad[103];            /* 0 */
  172. + };
  173. + /* sector 11h */
  174. + /* The spare block has pointers to spare sectors.  The following
  175. +    struct is more than usually conjectural, since my disks hide the
  176. +    existence of bad blocks.  */
  177. + #define SP_MAGIC 0xf9911849
  178. + struct hpfs_spare_block
  179. + {
  180. +   unsigned magic;            /* f991 1849 */
  181. +   unsigned magic1;            /* fa52 29c5, more magic? */
  182. +   unsigned dirty;            /* 0 clean, 1 "improperly stopped" */
  183. +   secno hotfix_map;            /* 20  ?? 4 sectors long, looks like
  184. +                                  secno from[n_spares];
  185. +                              secno to[n_spares];
  186. +                            the from array is all 0's,
  187. +                            the to array is initialized
  188. +                            to point to n_spares
  189. +                            preallocated empties */
  190. +   unsigned n_spares_used;        /* 0   ??? used spare count? */
  191. +   unsigned n_spares;            /* 64  ?? unused spare count?
  192. +                               total spare count? */
  193. +   unsigned n_dnode_spares_1;        /* 14  ??? 20 decimal */
  194. +   unsigned n_dnode_spares_2;        /* 14  ??? 20 decimal */
  195. +                     /*     the above 2 words are probably
  196. +                            the number of dnode spares and
  197. +                            the number of free ones. */
  198. +   secno weirdblock;            /* 88  ?? first of 2 peculiar blocks */
  199. +   unsigned n_weird;            /* 2   ?? number of peculiar blocks */
  200. +   unsigned hash1, hash2;        /*     ?? checksums of something? */
  201. +   unsigned zero1[19];            /* 0 */
  202. +   
  203. +   dnode_secno spares[20];        /* ?? spare dnodes? */
  204. +   unsigned zero3[20];            /* ?? other half of hotfix map? */
  205. +   unsigned zero2[57];            /* 0 */
  206. + };
  207. + /* The two peculiar blocks pointed to by the spare block stump me completely.
  208. +    They start with what look like magic numbers: */
  209. + #define BIZZ1_MAGIC 0x494521f7
  210. + #define BIZZ2_MAGIC 0x894521f7
  211. + /* They have many other numbers, equally magic.  The location of these
  212. +    blocks varies with the size of the filesystem, their contents
  213. +    doesn't.  The first block is constant except for a couple of
  214. +    pointers to the second block.  It is mostly zero.  The second block
  215. +    is constant, period.  It is fond of byte sequences like
  216. +        cfcecdcc cbcac9c8 c7c7c5c4 c3c2c1c0  060  ........ ........
  217. +    with some like
  218. +        9f9e9d9c 9d9a9959 ebeae399 e2929290  030  ........ Y.......
  219. +        
  220. +    but it isn't, e.g., a permutation of the low-numbered blocks in the
  221. +    partition.  It isn't a permutation at all.  It looks like two words
  222. +    followed by 200h bytes, the bytes being a variation on x[i] = i but
  223. +    with what may be word values stuck in here and there.  Heaven knows
  224. +    what it means, I just hope it's not important. */
  225. +        
  226. + /* Free space bitmaps are 4 sectors long, which is 16384 bits.
  227. +    16384 sectors is 8 meg, and each 8 meg band has a 4-sector bitmap.
  228. +    Bit order in the maps is little-endian.  0 means taken, 1 means free.
  229. +    Bit map sectors are marked allocated in the bit maps, and so are sectors 
  230. +    off the end of the partition.
  231. +    Band 0 is sectors 0-3fff, its map is in sectors 18-1b.
  232. +    Band 1 is 4000-7fff, its map is in 7ffc-7fff.
  233. +    Band 2 is 8000-ffff, its map is in 8000-8003.
  234. +    The remaining bands have maps in their first (even) or last (odd) 4 sectors
  235. +      -- if the last, partial, band is odd its map is in its last 4 sectors.
  236. +    What happens if the last band is < 4 sectors long I don't know.
  237. +    The band-0 bitmap at 18 is pointed to by the first word of sector 14,
  238. +    which is pointed to by the super block.  The remaining words of
  239. +    sector 14 don't point to the other bitmaps, though.  On a wild guess,
  240. +    the 4 sectors from 14-17 can point to alternate bitmap locations for
  241. +    bands 0-511.  Or maybe it's a table of offsets.
  242. +    The "directory band" is a bunch of sectors preallocated for dnodes.
  243. +    It has a 4-sector free space bitmap of its own.  Each bit in the map
  244. +    corresponds to one 4-sector dnode, bit 0 of the map corresponding to
  245. +    the first 4 sectors of the directory band.  The entire band is marked
  246. +    allocated in the main bitmap.   The super block gives the locations
  247. +    of the directory band and its bitmap.  ("band" doesn't mean it is
  248. +    8 meg long; it isn't.)  */
  249. + /* dnode: directory.  4 sectors long */
  250. + /* A directory is a tree of dnodes.  There is one pointer to the root of
  251. +    the tree, in the fnode for the directory.  Every dnode in the tree
  252. +    points up to this fnode, and the parent directory points down to it.
  253. +    The fnode never moves, the dnodes do the B-tree thing, splitting
  254. +    and merging as files are added and removed.  */
  255. + #define DNODE_MAGIC   0x77e40aae
  256. + struct dnode {
  257. +   unsigned magic;            /* 77e4 0aae */
  258. +   unsigned first_free;            /* offset to first free dirent */
  259. +   unsigned increment_me;        /* some kind of activity counter?
  260. +                        Neither HPFS.IFS nor CHKDSK cares
  261. +                        if you change this word */
  262. +   fnode_secno up;            /* fnode that points to directory's
  263. +                        root dnode */
  264. +   dnode_secno self;            /* pointer to this dnode */
  265. +   unsigned char dirent[2028];        /* one or more dirents */
  266. + };
  267. + struct hpfs_dirent {
  268. +   unsigned short length;        /* offset to next dirent */
  269. +   unsigned first: 1;            /* set on phony ^A^A (".") entry */
  270. +   unsigned flag1: 1;
  271. +   unsigned down: 1;            /* down pointer present (after name) */
  272. +   unsigned last: 1;            /* set on phony \377 entry */
  273. +   unsigned flag4: 1;
  274. +   unsigned flag5: 1;
  275. +   unsigned flag6: 1;
  276. +   unsigned flag7: 1;
  277. +   unsigned read_only: 1;        /* dos attrib */
  278. +   unsigned hidden: 1;            /* dos attrib */
  279. +   unsigned system: 1;            /* dos attrib */
  280. +   unsigned flag11: 1;            /* would be volume label dos attrib */
  281. +   unsigned directory: 1;        /* dos attrib */
  282. +   unsigned archive: 1;            /* dos attrib */
  283. +   unsigned not_8x3: 1;            /* name is not 8.3 */
  284. +   unsigned flag15: 1;
  285. +   fnode_secno fnode;            /* fnode giving allocation info */
  286. +   time_t creation_date;            /* ctime */
  287. +   unsigned file_size;            /* file length, bytes */
  288. +   time_t read_date;            /* atime */
  289. +   time_t write_date;            /* mtime */
  290. +   unsigned ea_size;            /* total EA length, bytes */
  291. +   unsigned char zero1;
  292. +   unsigned char locality;        /* ?? 0=unk 1=seq 2=random 3=both */
  293. +   unsigned char namelen, name[1];    /* file name */
  294. +   /* dnode_secno down;      btree down pointer, if present,
  295. +                    follows name on next word boundary, or maybe it's
  296. +               precedes next dirent, which is on a word boundary. */
  297. + };
  298. + /* B+ tree: allocation info in fnodes and anodes */
  299. + /* dnodes point to fnodes which are responsible for listing the sectors
  300. +    assigned to the file.  This is done with trees of (length,address)
  301. +    pairs.  (Triples, actually, of (length, file-address, disk-address)
  302. +    which can represent holes.  Find out if HPFS does that.)
  303. +    At any rate, fnodes contain a small tree; if subtrees are needed
  304. +    they occupy essentially a full block in anodes.  A leaf-level tree node
  305. +    has 3-word entries giving sector runs, a non-leaf node has 2-word
  306. +    entries giving subtree pointers.  A flag in the header says which. */
  307. + struct bplus_header
  308. + {
  309. +   unsigned flag0: 1;
  310. +   unsigned flag1: 1;
  311. +   unsigned flag2: 1;
  312. +   unsigned flag3: 1;
  313. +   unsigned flag4: 1;
  314. +   unsigned fnode_parent: 1;        /* ?? parent is an fnode?
  315. +                           A particularly silly flag, but
  316. +                           that seems to be it */
  317. +   unsigned flag6: 1;
  318. +   unsigned internal: 1;            /* 1 -> (internal) tree of anodes
  319. +                        0 -> (leaf) list of extents */
  320. +   unsigned char fill[3];
  321. +   unsigned char n_free_nodes;        /* free nodes in following array */
  322. +   unsigned char n_used_nodes;        /* used nodes in following array */
  323. +   unsigned short first_free;        /* offset from start of header to
  324. +                        first free node in array */
  325. +   /* union { internal[], leaf[] }; follows here */
  326. + };
  327. + struct bplus_internal_node
  328. + {
  329. +   unsigned file_secno;            /* subtree maps sectors < this  */
  330. +   anode_secno down;            /* pointer to subtree */
  331. + };
  332. + struct bplus_leaf_node
  333. + {
  334. +   unsigned file_secno;            /* first file sector in extent */
  335. +   unsigned length;            /* length, sectors */
  336. +   secno disk_secno;            /* first corresponding disk sector */
  337. + };
  338. + /* fnode: root of allocation b+ tree, and EA's */
  339. + /* Every file and every directory has one fnode, pointed to by the directory
  340. +    entry and pointing to the file's sectors or directory's root dnode.  EA's
  341. +    are also stored here, and there are said to be ACL's somewhere here too. */
  342. + #define FNODE_MAGIC 0xf7e40aae
  343. + struct fnode
  344. + {
  345. +   unsigned magic;            /* f7e4 0aae */
  346. +   unsigned zero1[2];
  347. +   unsigned char len, name[15];        /* true length, truncated name */
  348. +   fnode_secno up;            /* pointer to file's directory fnode */
  349. +   unsigned zero2[5];
  350. +   unsigned short ea_size;        /* length of fnode-resident ea's */
  351. +   unsigned char zero3;
  352. +   unsigned char dirflag;        /* 1 -> directory */
  353. +                     /* if set, first & only extent 
  354. +                        points to dnode. */
  355. +   struct bplus_header btree;        /* b+ tree, 8 extents or 12 subtrees */
  356. +   union {
  357. +     struct bplus_leaf_node external[8];
  358. +     struct bplus_internal_node internal[12];
  359. +   } u;
  360. +   unsigned file_size;            /* file length, bytes */
  361. +   unsigned zero4[5];
  362. +   unsigned huhc4;            /* c4  [ea's start at c4] */
  363. +   unsigned zero5[2];
  364. +   unsigned char ea[280];        /* zero or more EA's, packed on
  365. +                        byte boundaries */
  366. +                        
  367. +   unsigned zero6[9];
  368. + };
  369. + /* anode: 99.44% pure allocation tree */
  370. + #define ANODE_MAGIC 0x37e40aae
  371. + struct anode
  372. + {
  373. +   unsigned magic;            /* 37e4 0aae */
  374. +   anode_secno self;            /* pointer to this anode */
  375. +   secno up;                /* parent anode or fnode */
  376. +   struct bplus_header btree;        /* b+tree, 40 extents or 60 subtrees */
  377. +   union {
  378. +     struct bplus_leaf_node external[40];
  379. +     struct bplus_internal_node internal[60];
  380. +   } u;
  381. +   unsigned fill[2];            /* unused */
  382. + };
  383. + /* extended attribute in fnode */
  384. + struct fnode_ea {
  385. +   unsigned indirect: 1;            /* 1 -> value gives sector number
  386. +                        where real value starts */
  387. +   unsigned flag1: 1;            /* user flag, I think */
  388. +   unsigned flag2: 1;            /* user flag, I think */
  389. +   unsigned flag3: 1;            /* user flag, I think */
  390. +   unsigned flag4: 1;            /* user flag, I think */
  391. +   unsigned flag5: 1;            /* user flag, I think */
  392. +   unsigned flag6: 1;            /* user flag, I think */
  393. +   unsigned flag7: 1;            /* user flag, I think */
  394. +   unsigned char namelen;        /* length of name, bytes */
  395. +   unsigned short valuelen;        /* length of value, bytes */
  396. +   /*
  397. +     unsigned char name[namelen];    ascii attrib name
  398. +     unsigned char nul;            terminating '\0', not counted
  399. +     unsigned char value[valuelen];    value, arbitrary
  400. +     if this.indirect, valuelen is 8 and the value is
  401. +       unsigned length;            real length of value, bytes
  402. +       secno secno;            sector address where it starts
  403. +   */
  404. + };
  405. + /* Large values are handled by the indirect mechanism.  I think one
  406. +    contiguous sector run is required to hold the value.  (?)
  407. +    When too many EA's are defined, what seems to happen is that an EA
  408. +    named .ASSOCTABLE appears whose value is a set of EA's.  Another EA
  409. +    named .CHECKSUM always seems to accompany it.  ASSOCTABLE always has
  410. +    a large value, CHECKSUM always doesn't.  I don't know whether
  411. +    this is an HPFS hack or a library hack. */
  412. + /*
  413. +    Local Variables:
  414. +    comment-column: 40
  415. +    End:
  416. + */
  417. diff -rc2N linux-dist/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c
  418. *** linux-dist/fs/hpfs/hpfs_fs.c
  419. --- linux/fs/hpfs/hpfs_fs.c    Sun Oct 10 12:18:53 1993
  420. ***************
  421. *** 0 ****
  422. --- 1,1391 ----
  423. + /*
  424. +  *  linux/fs/hpfs/hhpfs_fs.c
  425. +  *
  426. +  *  Sources & references:
  427. +  *   Duncan, _Design ... of HPFS_, MSSJ 4(5)   (C) 1989 Microsoft Corp
  428. +  *   linux/fs/minix  Copyright (C) 1991, 1992, 1993  Linus Torvalds
  429. +  *   linux/fs/msdos  Written 1992, 1993 by Werner Almesberger
  430. +  *   linux/fs/isofs  Copyright (C) 1991  Eric Youngdale
  431. +  */
  432. + /* read-only HPFS */
  433. + /* HPFS is a mixture of 512-byte blocks and 2048-byte blocks.  The 2k blocks
  434. +    are used for directories (dnodes) and bitmaps.  They are always aligned
  435. +    and never aliased with 512-byte blocks, so it's no big deal keeping them
  436. +    straight.  However, Linux currently does not mix block sizes, so we run
  437. +    the whole file system with 2k blocks.
  438. +    However, I want du/df and friends to work right, so everything is reported
  439. +    to the user as if the blocksize were 512 bytes.
  440. +    For a file's i-number we use the sector number of its fnode, coded.
  441. +    (Directory ino's are even, file ino's are odd, and ino >> 1 is the
  442. +    sector address of the fnode.  This is a hack to allow lookup() to
  443. +    tell read_inode() whether it is efficient to read the fnode.)
  444. +    The map_xxx routines all read something into a buffer and return a
  445. +    pointer somewhere in the buffer.  The caller must do the brelse.
  446. +    The other routines are balanced. */
  447. + #include <stddef.h>
  448. + #include <linux/fs.h>
  449. + #include <linux/hpfs_fs.h>
  450. + #include <linux/errno.h>
  451. + #include <linux/sched.h>
  452. + #include <linux/locks.h>
  453. + #include <linux/stat.h>
  454. + #include <linux/string.h>
  455. + #include <asm/bitops.h>
  456. + #include <asm/segment.h>
  457. + #include "hpfs.h"
  458. + /* For details on the data structures see hpfs.h and the Duncan article.
  459. +    Overview
  460. +    [ The names of these data structures, except fnode, are not IBM's or
  461. +    Microsoft's.  I don't know what names they use.  The semantics
  462. +    described here are those of this implementation, and any coincidence
  463. +    between it and real HPFS is to be hoped for but not guaranteed by me,
  464. +    and certainly not guaranteed by IBM or MS.  Who know nothing about this. ]
  465. +    [ Also, the following will make little sense if you haven't read the
  466. +    Duncan article, which is excellent. ]
  467. +    HPFS is a tree.  There are 3 kinds of nodes.  A directory is a tree
  468. +    of dnodes, and a file's allocation info is a tree of sector lists
  469. +    stored in fnodes and anodes.
  470. +    The top pointer is in the super block, it points to the fnode of the
  471. +    root directory.
  472. +    
  473. +    The root directory -- all directories -- gives file names, dates &c,
  474. +    and fnode addresses.  If the directory fits in one dnode, that's it,
  475. +    otherwise the top dnode points to other dnodes, forming a tree.  A
  476. +    directory tree might look like
  477. +        ((a b c) d (e f g) h (i j) k l (m n o p))
  478. +    The subtrees appear between the files.  Each dir entry contains, along
  479. +    with the name and fnode, a dnode pointer to the subtree that precedes it
  480. +    (if there is one; a flag tells that).  The first entry in every directory
  481. +    is ^A^A, the entry for the directory itself.  The last entry in every
  482. +    dnode is \377, a fake entry whose only valid fields are the bit marking
  483. +    it last and the down pointer to the subtree preceding it, if any.
  484. +    The "value" field of directory entries is an fnode address.  The fnode
  485. +    tells where the sectors of the file are.  The fnode for a subdirectory
  486. +    contains one pointer, to the root dnode of the subdirectory.  The fnode
  487. +    for a data file contains, in effect, a tiny anode.  (Most of the space
  488. +    in fnodes is for extended attributes.)
  489. +    anodes and the anode part of fnodes are trees of extent lists.  An extent
  490. +    is a (length, disk address) pair, labeled with the file address being
  491. +    mapped.  E.g.,
  492. +        (0: 3@1000  3: 1@2000  4: 2@10)
  493. +    means the file:disk sector map (0:1000 1:1001 2:1002 3:2000 4:10 5:11).
  494. +    There is space for 8 file:len@disk triples in an fnode, or for 40 in an
  495. +    anode.  If this is insufficient, subtrees are used, as in
  496. +     (6: (0: 3@1000  3: 1@2000  4: 2@10)  12: (6: 3@8000  9: 1@9000  10: 2@20))
  497. +    The label on a subtree is the first address *after* that tree.  The
  498. +    subtrees are always anodes.  The label:subtree pairs require only
  499. +    two words each, so non-leaf subtrees have a different format; there
  500. +    is room for 12 label:subtree pairs in an fnode, or 60 in an anode.
  501. +    There is only one pointer to any dnode.  If it is the root dnode of its
  502. +    directory, the pointer is in the directory's fnode.  If it is not the
  503. +    root, the pointer is in the parent dnode.
  504. +    The only real upward pointer around is in fnodes, which point to the
  505. +    directory containing them (to its fnode).  (So, in a directory's fnode,
  506. +    this pointer is "..".)  There are several pointers that seem to be for
  507. +    consistency checks -- all dnodes point to the directory's fnode, and
  508. +    several nodes contain pointers to themselves.
  509. +    
  510. +    On the disk, dnodes are all together in the center of the partition, and
  511. +    HPFS even manages to put all the dnodes for a single directory together,
  512. +    generally.   fnodes are out with the data.  anodes are pretty much not
  513. +    seen -- in fact noncontiguous files are pretty much not seen.  I think
  514. +    this is partly the open() call that lets programs specify the length of
  515. +    an output file when they know it, and partly because HPFS.IFS really is
  516. +    very good at avoiding fragmentation. */
  517. + /* notation */
  518. + #define little_ushort(x) (*(unsigned short *) &(x))
  519. + typedef void nonconst;
  520. + /* super block ops */
  521. + static void hpfs_read_inode (struct inode *);
  522. + static int hpfs_notify_change (int flags, struct inode *);
  523. + static void hpfs_write_inode (struct inode *);
  524. + static void hpfs_put_inode (struct inode *);
  525. + static void hpfs_put_super (struct super_block *);
  526. + static void hpfs_write_super (struct super_block *);
  527. + static void hpfs_statfs (struct super_block *, struct statfs *);
  528. + static int hpfs_remount_fs (struct super_block *, int *);
  529. + static const struct super_operations hpfs_sops =
  530. + {
  531. +   hpfs_read_inode,
  532. +   hpfs_notify_change,
  533. +   hpfs_write_inode,
  534. +   hpfs_put_inode,
  535. +   hpfs_put_super,
  536. +   hpfs_write_super,
  537. +   hpfs_statfs,
  538. +   hpfs_remount_fs,
  539. + };
  540. + /* file ops */
  541. + static int hpfs_file_read (struct inode *, struct file *, char *, int);
  542. + static int hpfs_file_write (struct inode *, struct file *, char *, int);
  543. + static void hpfs_truncate (struct inode *);
  544. + static const struct file_operations hpfs_file_ops = 
  545. + {
  546. +   NULL,                    /* lseek - default */
  547. +   hpfs_file_read,            /* read */
  548. +   hpfs_file_write,            /* write */
  549. +   NULL,                    /* readdir - bad */
  550. +   NULL,                    /* select - default */
  551. +   NULL,                    /* ioctl - default */
  552. +   NULL,                    /* mmap */
  553. +   NULL,                    /* no special open is needed */
  554. +   NULL,                    /* release */
  555. +   file_fsync,                /* fsync */
  556. + };
  557. + static const struct inode_operations hpfs_file_iops = 
  558. + {
  559. +   (nonconst *) &hpfs_file_ops,        /* default file operations */
  560. +   NULL,                    /* create */
  561. +   NULL,                    /* lookup */
  562. +   NULL,                    /* link */
  563. +   NULL,                    /* unlink */
  564. +   NULL,                    /* symlink */
  565. +   NULL,                    /* mkdir */
  566. +   NULL,                    /* rmdir */
  567. +   NULL,                    /* mknod */
  568. +   NULL,                    /* rename */
  569. +   NULL,                    /* readlink */
  570. +   NULL,                    /* follow_link */
  571. +   NULL,                    /* bmap */
  572. +   hpfs_truncate,            /* truncate */
  573. +   NULL,                    /* permission */
  574. + };
  575. + static int hpfs_dir_read (struct inode * inode, struct file *filp,
  576. +                char *buf, int count);
  577. + static int hpfs_readdir (struct inode *inode, struct file *filp,
  578. +              struct dirent *dirent, int count);
  579. + static int hpfs_create (struct inode *,const char *,int,int,struct inode **);
  580. + static int hpfs_lookup (struct inode *,const char *,int,struct inode **);
  581. + static int hpfs_unlink (struct inode *,const char *,int);
  582. + static int hpfs_mkdir (struct inode *,const char *,int,int);
  583. + static int hpfs_rmdir (struct inode *,const char *,int);
  584. + static int hpfs_rename (struct inode *,const char *,int,struct inode *,const char *,int);
  585. + static const struct file_operations hpfs_dir_ops = 
  586. + {
  587. +   NULL,                    /* lseek - default */
  588. +   hpfs_dir_read,            /* read */
  589. +   NULL,                    /* write - bad */
  590. +   hpfs_readdir,                /* readdir */
  591. +   NULL,                    /* select - default */
  592. +   NULL,                    /* ioctl - default */
  593. +   NULL,                    /* mmap */
  594. +   NULL,                    /* no special open code */
  595. +   NULL,                    /* no special release code */
  596. +   file_fsync,                /* fsync */
  597. + };
  598. + static const struct inode_operations hpfs_dir_iops =
  599. + {
  600. +   (nonconst *) &hpfs_dir_ops,        /* default directory file ops */
  601. +   hpfs_create,                /* create */
  602. +   hpfs_lookup,                /* lookup */
  603. +   NULL,                    /* link */
  604. +   hpfs_unlink,                /* unlink */
  605. +   NULL,                    /* symlink */
  606. +   hpfs_mkdir,                /* mkdir */
  607. +   hpfs_rmdir,                /* rmdir */
  608. +   NULL,                    /* mknod */
  609. +   hpfs_rename,                /* rename */
  610. +   NULL,                    /* readlink */
  611. +   NULL,                    /* follow_link */
  612. +   NULL,                    /* bmap */
  613. +   NULL,                    /* truncate */
  614. +   NULL,                    /* permission */
  615. + };
  616. + static int parse_opts (char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
  617. +                int *lowercase, int *conv);
  618. + static void count_dnodes (struct inode *inode, dnode_secno dno,
  619. +               unsigned *n_dnodes, unsigned *n_subdirs);
  620. + static unsigned count_bitmap (struct super_block *s);
  621. + static unsigned count_one_bitmap (dev_t dev, secno secno);
  622. + static secno file_disk_secno (struct inode *inode, unsigned file_secno);
  623. + static secno bplus_lookup (struct inode *inode, struct bplus_header *b,
  624. +                secno file_secno, struct buffer_head **bhp);
  625. + static struct hpfs_dirent *map_dirent (struct inode *inode, dnode_secno dno,
  626. +                        const char *name, unsigned len,
  627. +                        struct buffer_head **bhp);
  628. + static struct hpfs_dirent *map_pos_dirent (struct inode *inode, off_t *posp,
  629. +                        struct buffer_head **bhp);
  630. + static void write_one_dirent (struct dirent *dirent, const unsigned char *name,
  631. +                   unsigned namelen, ino_t ino, int lowercase);
  632. + static dnode_secno dir_subdno (struct inode *inode, unsigned pos);
  633. + static struct hpfs_dirent *map_nth_dirent (dev_t dev, dnode_secno dno,
  634. +                        int n, struct buffer_head **bhp);
  635. + static dnode_secno fnode_dno (dev_t dev, ino_t ino);
  636. + static void *map_fnode (dev_t dev, ino_t ino, struct buffer_head **bhp);
  637. + static void *map_anode (dev_t dev, unsigned secno, struct buffer_head **bhp);
  638. + static void *map_dnode (dev_t dev, unsigned secno, struct buffer_head **bhp);
  639. + static void *map_sector (dev_t dev, unsigned secno, struct buffer_head **bhp);
  640. + static void *map_4sectors (dev_t dev, unsigned secno,struct buffer_head **bhp);
  641. + static unsigned choose_conv (unsigned char *p, unsigned len);
  642. + static unsigned convcpy_tofs (unsigned char *out, unsigned char *in,
  643. +                   unsigned len);
  644. + /* make inode number for a file */
  645. + static ino_t file_ino (fnode_secno secno)
  646. + {
  647. +   return secno << 1 | 1;
  648. + }
  649. + /* make inode number for a directory */
  650. + static ino_t dir_ino (fnode_secno secno)
  651. + {
  652. +   return secno << 1;
  653. + }
  654. + /* get fnode address from an inode number */
  655. + static fnode_secno ino_secno (ino_t ino)
  656. + {
  657. +   return ino >> 1;
  658. + }
  659. + /* test for directory's inode number */
  660. + static int ino_is_dir (ino_t ino)
  661. + {
  662. +   return (ino & 1) == 0;
  663. + }
  664. + /* conv= options */
  665. + #define CONV_BINARY 0        /* no conversion */
  666. + #define CONV_TEXT 1        /* crlf->newline */
  667. + #define CONV_AUTO 2        /* decide based on file contents */
  668. + /* super block ops */
  669. + /* mount.  This gets one thing, the root directory inode.  It does a
  670. +    bunch of guessed-at consistency checks.  */
  671. + struct super_block *hpfs_read_super (struct super_block *s,
  672. +                      void *options, int silent)
  673. + {
  674. +   struct hpfs_boot_block *bootblock;
  675. +   struct hpfs_super_block *superblock;
  676. +   struct hpfs_spare_block *spareblock;
  677. +   struct hpfs_dirent *de;
  678. +   struct buffer_head *bh0, *bh1, *bh2;
  679. +   dev_t dev; 
  680. +   uid_t uid;
  681. +   gid_t gid;
  682. +   umode_t umask;
  683. +   int lowercase;
  684. +   int conv;
  685. +   /* Get the mount options */
  686. +   if (! parse_opts (options, &uid, &gid, &umask, &lowercase, &conv)) {
  687. +     printk ("HPFS: syntax error in mount options.  Not mounted.\n");
  688. +     s->s_dev = 0; return 0;
  689. +   }
  690. +   /* Fill in the super block struct */
  691. +   lock_super (s);
  692. +   dev = s->s_dev;
  693. +   set_blocksize (dev, 2048);
  694. +   /* fetch sectors 0, 16, 17 */
  695. +   bootblock = map_sector (dev, 0, &bh0);
  696. +   if (! bootblock)
  697. +     { s->s_dev = 0; unlock_super (s); return 0; }
  698. +   superblock = map_sector (dev, 16, &bh1);
  699. +   if (! superblock)
  700. +     { brelse (bh0); s->s_dev = 0; unlock_super (s); return 0; }
  701. +   spareblock = map_sector (dev, 17, &bh2);
  702. +   if (! spareblock)
  703. +     { brelse (bh1); brelse (bh0); s->s_dev = 0; unlock_super (s); return 0; }
  704. +   /* Check that this fs matches the ones I examined. 
  705. +      Probably some of these checks are unneeded, but the clueless do well
  706. +      to be timid. */
  707. +   if (little_ushort (bootblock->bytes_per_sector) != 512
  708. +       || bootblock->sig_28h != 0x28
  709. +       || memcmp (&bootblock->sig_hpfs, "HPFS    ", 8)
  710. +       || superblock->magic != SB_MAGIC
  711. +       || superblock->huh202 != 0x202
  712. +       || superblock->n_sectors != bootblock->n_sectors_l
  713. +       || (superblock->n_sectors % 4) != 0
  714. +       || spareblock->magic != SP_MAGIC
  715. +       || spareblock->dirty != 0
  716. +       || spareblock->n_spares_used != 0
  717. +       || spareblock->n_dnode_spares_1 != spareblock->n_dnode_spares_2
  718. +       || superblock->huh4 != 0x14
  719. +       || superblock->huh6 != 0x1c
  720. +       || superblock->zero1 || superblock->zero2
  721. +       || superblock->zero3 || superblock->zero4) {
  722. +     printk ("HPFS: hpfs_read_super: Not HPFS\n");
  723. +     brelse (bh2); brelse (bh1); brelse (bh0);
  724. +     s->s_dev = 0; unlock_super (s); return 0;
  725. +   }
  726. +   /* set fs read only */
  727. +   s->s_flags |= MS_RDONLY;
  728. +   /* fill in standard stuff */
  729. +   s->s_magic = HPFS_SUPER_MAGIC;
  730. +   s->s_blocksize = 2048;
  731. +   s->s_blocksize_bits = 11;
  732. +   s->s_op = (struct super_operations *) &hpfs_sops;
  733. +   /* fill in hpfs stuff */
  734. +   s->s_hpfs_root = dir_ino (superblock->root);
  735. +   s->s_hpfs_fs_size = superblock->n_sectors;
  736. +   s->s_hpfs_dirband_size = superblock->n_dir_band / 4;
  737. +   s->s_hpfs_dmap = superblock->dir_band_bitmap;
  738. +   s->s_hpfs_uid = uid;
  739. +   s->s_hpfs_gid = gid;
  740. +   s->s_hpfs_mode = 0777 & ~umask;
  741. +   s->s_hpfs_n_free = -1;
  742. +   s->s_hpfs_n_free_dnodes = -1;
  743. +   s->s_hpfs_lowercase = lowercase;
  744. +   s->s_hpfs_conv = conv;
  745. +   /* done with the low blocks */
  746. +   brelse (bh2); brelse (bh1); brelse (bh0);
  747. +   /* all set.  try it out. */
  748. +   s->s_mounted = iget (s, s->s_hpfs_root);
  749. +   unlock_super (s);
  750. +   if (! s->s_mounted) {
  751. +     printk ("HPFS: hpfs_read_super: inode get failed\n");
  752. +     s->s_dev = 0;
  753. +     return 0;
  754. +   } 
  755. +   /* find the root directory's . pointer & finish filling in the inode */
  756. +   de = map_dirent (s->s_mounted, fnode_dno (dev, s->s_hpfs_root),
  757. +            "\001\001", 2, &bh0);
  758. +   if (! de) {
  759. +     printk ("HPFS: hpfs_read_super: root dir isn't in the root dir\n");
  760. +     s->s_dev = 0;
  761. +     return 0;
  762. +   }
  763. +   s->s_mounted->i_atime = de->read_date;
  764. +   s->s_mounted->i_mtime = de->write_date;
  765. +   s->s_mounted->i_ctime = de->creation_date;
  766. +   brelse (bh0);
  767. +   return s;
  768. + }
  769. + /* A tiny parser for option strings, stolen from dosfs. */
  770. + static int parse_opts (char *opts, uid_t *uid, gid_t *gid, umode_t *umask,
  771. +                int *lowercase, int *conv)
  772. + {
  773. +   char *p, *rhs;
  774. +   *uid = current->uid;
  775. +   *gid = current->gid;
  776. +   *umask = current->umask;
  777. +   *lowercase = 1;
  778. +   *conv = CONV_BINARY;
  779. +   if (! opts) return 1;
  780. +   for (p = strtok (opts, ","); p != 0; p = strtok (0, ",")) {
  781. +     if ((rhs = strchr (p, '=')) != 0)
  782. +       *rhs++ = '\0';
  783. +     if (! strcmp (p, "uid")) {
  784. +       if (!rhs || !*rhs) return 0;
  785. +       *uid = simple_strtoul (rhs, &rhs, 0);
  786. +       if (*rhs) return 0;
  787. +     } else if (! strcmp (p, "gid")) {
  788. +       if (!rhs || !*rhs) return 0;
  789. +       *gid = simple_strtoul (rhs, &rhs, 0);
  790. +       if (*rhs) return 0;
  791. +     } else if (! strcmp (p, "umask")) {
  792. +       if (!rhs || !*rhs) return 0;
  793. +       *umask = simple_strtoul (rhs,&rhs,8);
  794. +       if  (*rhs) return 0;
  795. +     } else if (! strcmp (p, "case")) {
  796. +       if (! strcmp (rhs, "lower")) *lowercase = 1;
  797. +       else if (! strcmp (rhs, "asis")) *lowercase = 0;
  798. +       else return 0;
  799. +     } else if (! strcmp (p, "conv")) {
  800. +       if (! strcmp (rhs, "binary")) *conv = CONV_BINARY;
  801. +       else if (! strcmp (rhs, "text")) *conv = CONV_TEXT;
  802. +       else if (! strcmp (rhs, "auto")) *conv = CONV_AUTO;
  803. +       else return 0;
  804. +     } else
  805. +       return 0;
  806. +   }
  807. +   return 1;
  808. + }
  809. + /* read_inode.  This is called with exclusive access to a new inode that
  810. +    has only (i_dev,i_ino) set.  It is responsible for filling in the rest.
  811. +    We evilly leave the dates blank, for lookup() to fill in later.  
  812. +    (It really is evil, but consider the alternative: read the
  813. +    fnode, find the dir pointer in it, read that fnode to get the dnode
  814. +    pointer, search through that whole directory for the ino we're
  815. +    reading, and get the dates.  It works, but ls sounds like fsck.)
  816. +    (This will break someday if iget sleeps between calling us and
  817. +    returning to lookup.  Or if someone other than lookup calls iget.
  818. +    That's not too big a danger since lookup is the only source of
  819. +    i-numbers.  Neither is a problem right now, 0.99.13.)
  820. +    (An alternative would be to clone iget in this file so we can add
  821. +    args to it.  That's even more evil.) */
  822. + static void hpfs_read_inode (struct inode *inode)
  823. + {
  824. +   struct super_block *s = inode->i_sb;
  825. +   /* be ready to bail out */
  826. +   inode->i_op = 0;
  827. +   inode->i_mode = 0;
  828. +   if (inode->i_ino == 0
  829. +       || ino_secno (inode->i_ino) >= inode->i_sb->s_hpfs_fs_size)
  830. +     { printk ("HPFS: read_inode: bad ino\n"); return; }
  831. +   /* canned stuff */
  832. +   inode->i_uid = s->s_hpfs_uid;
  833. +   inode->i_gid = s->s_hpfs_gid;
  834. +   inode->i_mode = s->s_hpfs_mode;
  835. +   inode->i_hpfs_conv = s->s_hpfs_conv;
  836. +   inode->i_hpfs_dno = 0;
  837. +   inode->i_hpfs_n_secs = 0;
  838. +   inode->i_hpfs_file_sec = 0;
  839. +   inode->i_hpfs_disk_sec = 0;
  840. +   inode->i_hpfs_dpos = 0;
  841. +   inode->i_hpfs_dsubdno = 0;
  842. +   /* figure out whether we are looking at a directory or a file */
  843. +   if (ino_is_dir (inode->i_ino))
  844. +     inode->i_mode |= S_IFDIR;
  845. +   else {
  846. +     inode->i_mode |= S_IFREG;
  847. +     inode->i_mode &= ~0111;
  848. +   }
  849. +   /* these fields must be filled in from the dir entry, which we don't have
  850. +      but lookup does.  It will fill them in before letting the inode
  851. +      out of its grasp. */
  852. +   inode->i_atime = 0;
  853. +   inode->i_mtime = 0;
  854. +   inode->i_ctime = 0;
  855. +   inode->i_size = 0;
  856. +   /* fill in the rest */
  857. +   if (S_ISREG (inode->i_mode)) {
  858. +     inode->i_op = (struct inode_operations *) &hpfs_file_iops;
  859. +     inode->i_nlink = 1;
  860. +     inode->i_blksize = 512;
  861. +   } else {
  862. +     unsigned n_dnodes, n_subdirs;
  863. +     struct buffer_head *bh0;
  864. +     struct fnode *fnode = map_fnode (inode->i_dev, inode->i_ino, &bh0);
  865. +     if (! fnode)
  866. +       { printk ("HPFS: read_inode: no fnode\n"); inode->i_mode = 0; return; }
  867. +     inode->i_hpfs_parent_dir = dir_ino (fnode->up);
  868. +     inode->i_hpfs_dno = fnode->u.external[0].disk_secno;
  869. +     brelse (bh0);
  870. +     n_dnodes = n_subdirs = 0;
  871. +     count_dnodes (inode, inode->i_hpfs_dno, &n_dnodes, &n_subdirs);
  872. +     inode->i_op = (struct inode_operations *) &hpfs_dir_iops;
  873. +     inode->i_blksize = 512;        /* 2048 here confuses ls & du & ...*/
  874. +     inode->i_blocks = 4 * n_dnodes;
  875. +     inode->i_size = 512 * inode->i_blocks;
  876. +     inode->i_nlink = 2 + n_subdirs;
  877. +   }
  878. + }
  879. + static int hpfs_notify_change (int flags, struct inode *inode)
  880. + {
  881. +   return -EROFS;
  882. + }
  883. + static void hpfs_write_inode (struct inode *inode)
  884. + {
  885. + }
  886. + static void hpfs_put_inode (struct inode *inode)
  887. + {
  888. + }
  889. + static void hpfs_put_super (struct super_block *s)
  890. + {
  891. +   lock_super (s);
  892. +   s->s_dev = 0;
  893. +   unlock_super (s);
  894. + }
  895. + static void hpfs_write_super (struct super_block *s)
  896. + {
  897. + }
  898. + /* statfs.  We report results in 512-byte sectors, not our 2k buffer size.
  899. +    For inode counts we report the count of dnodes in the directory band --
  900. +    this is inaccurate because a dnode holds more than 1 file, and also
  901. +    because when the directory band fills up HPFS just puts dnodes elsewhere.
  902. +    But it's more interesting than zeros. */
  903. + static void hpfs_statfs (struct super_block *s, struct statfs *buf)
  904. + {
  905. +   if (s->s_hpfs_n_free == -1) {
  906. +     s->s_hpfs_n_free_dnodes = count_one_bitmap (s->s_dev, s->s_hpfs_dmap);
  907. +     s->s_hpfs_n_free = count_bitmap (s);
  908. +   }
  909. +   put_fs_long (s->s_magic, &buf->f_type);
  910. +   put_fs_long (512, &buf->f_bsize);
  911. +   put_fs_long (s->s_hpfs_fs_size, &buf->f_blocks);
  912. +   put_fs_long (s->s_hpfs_n_free, &buf->f_bfree);
  913. +   put_fs_long (s->s_hpfs_n_free, &buf->f_bavail);
  914. +   put_fs_long (s->s_hpfs_dirband_size, &buf->f_files);
  915. +   put_fs_long (s->s_hpfs_n_free_dnodes, &buf->f_ffree);
  916. +   put_fs_long (255, &buf->f_namelen);
  917. + }
  918. + static int hpfs_remount_fs (struct super_block *s, int *flags)
  919. + {
  920. +   if (! (*flags & MS_RDONLY))
  921. +     return -EINVAL;
  922. +   return 0;
  923. + }
  924. + /* count the dnodes in a directory, and the subdirs */
  925. + static void count_dnodes (struct inode *inode, dnode_secno dno,
  926. +               unsigned *n_dnodes, unsigned *n_subdirs)
  927. + {
  928. +   struct buffer_head *bh;
  929. +   struct dnode *dnode;
  930. +   struct hpfs_dirent *de;
  931. +   struct hpfs_dirent *de_end;
  932. +   dnode = map_dnode (inode->i_dev, dno, &bh);
  933. +   if (! dnode) return;
  934. +   de = (void *) dnode->dirent;
  935. +   de_end = (void *) de + dnode->first_free;
  936. +   (*n_dnodes)++;
  937. +   for ( ; de < de_end; de = (void *) de + de->length) {
  938. +     if (de->down)
  939. +       count_dnodes (inode, *(dnode_secno *) ((void *) de + de->length - 4),
  940. +             n_dnodes, n_subdirs);
  941. +     if (de->directory && ! de->first)
  942. +       (*n_subdirs)++;
  943. +     if (de->last || de->length == 0)
  944. +       break;
  945. +   }
  946. +   brelse (bh);
  947. + }
  948. + /* count the bits in the free space bit maps */
  949. + static unsigned count_bitmap (struct super_block *s)
  950. + {
  951. +   unsigned n, fs_size = s->s_hpfs_fs_size;
  952. +   unsigned count;
  953. +   /* band 0 bitmap is in 18-1b */
  954. +   count = count_one_bitmap (s->s_dev, 0x18);
  955. +   /* remaining bitmaps are in the first or last 4 sectors of band */
  956. +   for (n = 0x4000; n < fs_size; n += 0x4000)
  957. +     if (n & 0x4000) {
  958. +       unsigned t = n | 0x3ffc;
  959. +       if (t > fs_size - 4) t = fs_size - 4;
  960. +       count += count_one_bitmap (s->s_dev, t);
  961. +     } else
  962. +       count += count_one_bitmap (s->s_dev, n);
  963. +   return count;
  964. + }
  965. + /* Read in one bit map, count the bits, return the count. */
  966. + static unsigned count_one_bitmap (dev_t dev, secno secno)
  967. + {
  968. +   struct buffer_head *bh;
  969. +   char *bits; 
  970. +   unsigned i, count;
  971. +   bits = map_4sectors (dev, secno, &bh);
  972. +   if (! bits) return 0;
  973. +   count = 0;
  974. +   for (i = 0; i < 8 * 2048; i++)
  975. +     count += (test_bit (i, bits) != 0);
  976. +   brelse (bh);
  977. +   return count;
  978. + }
  979. + /* file ops */
  980. + /* read().  Read the bytes, put them in buf, return the count. */
  981. + static int hpfs_file_read (struct inode *inode, struct file *filp,
  982. +                char *buf, int count)
  983. + {
  984. +   unsigned q, r, n, n0;
  985. +   struct buffer_head *bh;
  986. +   char *block;
  987. +   char *start;
  988. +   if (inode == 0 || ! S_ISREG (inode->i_mode))
  989. +     return -EINVAL;
  990. +   /* truncate count at EOF */
  991. +   if (count > inode->i_size - filp->f_pos)
  992. +     count = inode->i_size - filp->f_pos;
  993. +   
  994. +   start = buf;
  995. +   while (count > 0) {
  996. +     /* get file sector number, offset in sector, length to end of sector */
  997. +     q = filp->f_pos >> 9;
  998. +     r = filp->f_pos & 511;
  999. +     n = 512 - r;
  1000. +     /* get length to copy to user buffer */
  1001. +     if (n > count)
  1002. +       n = count;
  1003. +     /* read the sector, copy to user */
  1004. +     block = map_sector (inode->i_dev, file_disk_secno (inode, q), &bh);
  1005. +     if (! block) return -EIO;
  1006. +     /* but first decide if it has \r\n, if the user asked for that */ 
  1007. +     if (inode->i_hpfs_conv == CONV_AUTO)
  1008. +       inode->i_hpfs_conv = choose_conv (block + r, n);
  1009. +     if (inode->i_hpfs_conv == CONV_BINARY) {
  1010. +       /* regular copy, output length is same as input length */
  1011. +       memcpy_tofs (buf, block + r, n);
  1012. +       n0 = n;
  1013. +     } else {
  1014. +       /* squeeze out \r, output length varies */
  1015. +       n0 = convcpy_tofs (buf, block + r, n);
  1016. +       if (count > inode->i_size - filp->f_pos - n + n0)
  1017. +     count = inode->i_size - filp->f_pos - n + n0;
  1018. +     }
  1019. +     brelse (bh);
  1020. +     /* advance input n bytes, output n0 bytes */
  1021. +     filp->f_pos += n;
  1022. +     buf += n0;
  1023. +     count -= n0;
  1024. +   }
  1025. +   return buf - start;
  1026. + }
  1027. + /* This routine implements conv=auto.  Return CONV_BINARY or CONV_TEXT. */
  1028. + static unsigned choose_conv (unsigned char *p, unsigned len)
  1029. + {
  1030. +   unsigned tvote, bvote;
  1031. +   unsigned c;
  1032. +   tvote = bvote = 0;
  1033. +   while (len--) {
  1034. +     c = *p++;
  1035. +     if (c < ' ')
  1036. +       if (c == '\r' && len && *p == '\n') tvote += 10;
  1037. +       else if (c == '\t' || c == '\n') ;
  1038. +       else bvote += 5;
  1039. +     else if (c < '\177')
  1040. +       tvote++;
  1041. +     else
  1042. +       bvote += 5;
  1043. +   }
  1044. +   if (tvote > bvote)
  1045. +     return CONV_TEXT;
  1046. +   else
  1047. +     return CONV_BINARY;
  1048. + }
  1049. + /* This routine implements conv=text.  :s/crlf/nl/  */
  1050. + static unsigned convcpy_tofs (unsigned char *out, unsigned char *in,
  1051. +                   unsigned len)
  1052. + {
  1053. +   unsigned char *start = out;
  1054. +   while (len--) {
  1055. +     unsigned c = *in++;
  1056. +     if (c == '\r' && (len == 0 || *in == '\n'))
  1057. +       ;
  1058. +     else
  1059. +       put_fs_byte (c, out++);
  1060. +   }
  1061. +   return out - start;
  1062. + }
  1063. + static int hpfs_file_write (struct inode *inode, struct file *filp,
  1064. +                 char *buf, int count)
  1065. + {
  1066. +   return -EROFS;
  1067. + }
  1068. + static void hpfs_truncate (struct inode *inode)
  1069. + {
  1070. + }
  1071. + /* Return the disk sector number containing a file sector. */
  1072. + static secno file_disk_secno (struct inode *inode, unsigned file_secno)
  1073. + {
  1074. +   unsigned n, disk_secno;
  1075. +   struct fnode *fnode;
  1076. +   struct buffer_head *bh;
  1077. +   /* There is one sector run cached in the inode.
  1078. +      See if the sector is in it. */
  1079. +   n = file_secno - inode->i_hpfs_file_sec;
  1080. +   if (n < inode->i_hpfs_n_secs)
  1081. +     return inode->i_hpfs_disk_sec + n;
  1082. +   /* No, read the fnode and go find the sector. */
  1083. +   else {
  1084. +     fnode = map_fnode (inode->i_dev, inode->i_ino, &bh);
  1085. +     if (! fnode) return 0;
  1086. +     disk_secno = bplus_lookup (inode, &fnode->btree, file_secno, &bh);
  1087. +     brelse (bh);
  1088. +     return disk_secno;
  1089. +   }
  1090. + }
  1091. + /* Search allocation tree *b for the given file sector number and return
  1092. +    the disk sector number.  Buffer *bhp has the tree in it, and can be
  1093. +    reused for subtrees when access to *b is no longer needed.
  1094. +    *bhp is busy on entry and exit. */
  1095. + static secno bplus_lookup (struct inode *inode, struct bplus_header *b,
  1096. +                secno file_secno, struct buffer_head **bhp)
  1097. + {
  1098. +   int i;
  1099. +   /* A leaf-level tree gives a list of sector runs.  Find the one
  1100. +      containing the file sector we want, cache the map info in the inode
  1101. +      for later, and return the corresponding disk sector. */
  1102. +   if (! b->internal) {
  1103. +     struct bplus_leaf_node *n = (void *) b + sizeof *b;
  1104. +     for (i = 0; i < b->n_used_nodes; i++) {
  1105. +       unsigned t = file_secno - n[i].file_secno;
  1106. +       if (t < n[i].length) {
  1107. +     inode->i_hpfs_file_sec = n[i].file_secno;
  1108. +     inode->i_hpfs_disk_sec = n[i].disk_secno;
  1109. +     inode->i_hpfs_n_secs = n[i].length;
  1110. +     return n[i].disk_secno + t;
  1111. +       }
  1112. +     }
  1113. +   }
  1114. +   /* A non-leaf tree gives a list of subtrees.  Find the one containing
  1115. +      the file sector we want, read it in, and recurse to search it. */
  1116. +   else {
  1117. +     struct bplus_internal_node *n = (void *) b + sizeof *b;
  1118. +     for (i = 0; i < b->n_used_nodes; i++) {
  1119. +       if (file_secno < n[i].file_secno) {
  1120. +     struct anode *anode;
  1121. +     anode_secno ano = n[i].down;
  1122. +     brelse (*bhp);
  1123. +     anode = map_anode (inode->i_dev, ano, bhp);
  1124. +     if (! anode) break;
  1125. +     return bplus_lookup (inode, &anode->btree, file_secno, bhp);
  1126. +       }
  1127. +     }
  1128. +   }
  1129. +   /* If we get here there was a hole in the file.  As far as I know
  1130. +      we never do get here, but falling off the end would be indelicate.
  1131. +      So return a pointer to a handy all-zero sector.  This is not a
  1132. +      reasonable way to handle files with holes if they really do happen. */
  1133. +   printk ("HPFS: bplus_lookup: sector not found\n");
  1134. +   return 15;
  1135. + }
  1136. + /* directory ops */
  1137. + /* lookup.  Search the directory tree for the specified name, set
  1138. +    *result to the corresponding inode.
  1139. +    lookup uses a secret code to tell read_inode whether it is reading
  1140. +    the inode of a directory or a file -- file ino's are odd, directory
  1141. +    ino's are even.  read_inode avoids i/o for file inodes; everything
  1142. +    needed is up here in the directory.  And file fnodes are out in
  1143. +    the boondocks. */
  1144. + static int hpfs_lookup (struct inode *dir, const char *name, int len,
  1145. +             struct inode **result)
  1146. + {
  1147. +   struct buffer_head *bh;
  1148. +   struct hpfs_dirent *de;
  1149. +   struct inode *inode;
  1150. +   ino_t ino;
  1151. +   /* In case of madness */
  1152. +   *result = 0;
  1153. +   if (dir == 0)
  1154. +     return -ENOENT;
  1155. +   if (! S_ISDIR (dir->i_mode))
  1156. +     goto bail;
  1157. +   
  1158. +   /* Read in the directory entry.
  1159. +      "." is there under the name ^A^A .
  1160. +      Always read the dir even for . and .. in case we need the dates. */
  1161. +   if (name[0] == '.' && len == 1)
  1162. +     de = map_dirent (dir, dir->i_hpfs_dno, "\001\001", 2, &bh);
  1163. +   else if (name[0] == '.' && name[1] == '.' && len == 2)
  1164. +     de = map_dirent (dir, fnode_dno (dir->i_dev, dir->i_hpfs_parent_dir),
  1165. +              "\001\001", 2, &bh);
  1166. +   else
  1167. +     de = map_dirent (dir, dir->i_hpfs_dno, name, len, &bh);
  1168. +   /* This is not really a bailout, just means file not found. */
  1169. +   if (! de) goto bail;
  1170. +   /* Get inode number, what we're after. */
  1171. +   if (de->directory)
  1172. +     ino = dir_ino (de->fnode);
  1173. +   else
  1174. +     ino = file_ino (de->fnode);
  1175. +   /* Go build an inode. */
  1176. +   if (! (inode = iget (dir->i_sb, ino)))
  1177. +     goto bail1;
  1178. +   /* Stuff in the info from the directory if this is a newly created inode. */
  1179. +   if (! inode->i_atime) {
  1180. +     inode->i_atime = de->read_date;
  1181. +     inode->i_mtime = de->write_date;
  1182. +     inode->i_ctime = de->creation_date;
  1183. +     if (! de->directory) {
  1184. +       inode->i_size = de->file_size;
  1185. +       inode->i_blocks = 1 + ((inode->i_size + 511) >> 9);
  1186. +     }
  1187. +   }
  1188. +   brelse (bh);
  1189. +   /* Made it. */
  1190. +   *result = inode;
  1191. +   iput (dir);
  1192. +   return 0;
  1193. +   /* Didn't. */
  1194. +  bail1:
  1195. +   brelse (bh);
  1196. +  bail:
  1197. +   iput (dir);
  1198. +   return -ENOENT;
  1199. + }
  1200. + /* Compare two counted strings ignoring case.
  1201. +    OS/2 directory order sorts letters as if they're upper case. */
  1202. + static inline int memcasecmp (unsigned char *s1, unsigned char *s2, unsigned n)
  1203. + {
  1204. +   int t;
  1205. +   if (n != 0)
  1206. +     do {
  1207. +       unsigned c1 = *s1++;
  1208. +       unsigned c2 = *s2++;
  1209. +       if (c1 - 'a' < 26) c1 -= 040;
  1210. +       if (c2 - 'a' < 26) c2 -= 040;
  1211. +       if ((t = c1 - c2) != 0)
  1212. +     return t;
  1213. +     } while (--n != 0);
  1214. +   return 0;
  1215. + }
  1216. + /* Search a directory for the given name, return a pointer to its dir entry
  1217. +    and a pointer to the buffer containing it. */
  1218. + static struct hpfs_dirent *map_dirent (struct inode *inode, dnode_secno dno,
  1219. +                        const char *name, unsigned len,
  1220. +                        struct buffer_head **bhp)
  1221. + {
  1222. +   struct dnode *dnode;
  1223. +   struct hpfs_dirent *de;
  1224. +   struct hpfs_dirent *de_end;
  1225. +   int t, l;
  1226. +   /* read the dnode at the root of our subtree */
  1227. +   dnode = map_dnode (inode->i_dev, dno, bhp);
  1228. +   if (! dnode) return 0;
  1229. +   /* get pointers to start and end+1 of dir entries */
  1230. +   de = (void *) dnode->dirent;
  1231. +   de_end = (void *) de + dnode->first_free;
  1232. +   /* look through the entries for the name we're after */
  1233. +   for ( ; de < de_end; de = (void *) de + de->length) {
  1234. +     /* compare names */
  1235. +     l = len < de->namelen ? len : de->namelen;
  1236. +     t = memcasecmp (name, de->name, l);
  1237. +     /* initial substring matches, compare lengths */
  1238. +     if (t == 0) {
  1239. +       t = len - de->namelen;
  1240. +       /* bingo */
  1241. +       if (t == 0)
  1242. +     return de;
  1243. +     }
  1244. +       
  1245. +     /* wanted name < dir name -> not present. */
  1246. +     if (t < 0) {
  1247. +       /* if there is a subtree, search it. */
  1248. +       if (de->down) {
  1249. +     dnode_secno sub_dno = *(secno *) ((void *) de + de->length - 4);
  1250. +     brelse (*bhp);
  1251. +     return map_dirent (inode, sub_dno, name, len, bhp);
  1252. +       } else
  1253. +     break;
  1254. +     }
  1255. +     /* de->last is set on the last name in the dnode (it's always a "\377"
  1256. +        pseudo entry).  de->length == 0 means we're about to infinite loop.
  1257. +        This test does nothing in a well-formed dnode. */
  1258. +     if (de->last || de->length == 0)
  1259. +       break;
  1260. +   }
  1261. +   /* name not found. */
  1262. +   return 0;
  1263. + }
  1264. + /* readdir.  Return exactly 1 dirent.  (I tried and tried, but the code
  1265. +    between libc and here is *far* too hosed to permit anything more.
  1266. +    If it ever gets fixed, throw this out and just walk the tree and
  1267. +    write records into the user buffer.)
  1268. +    We keep track of our position in the dnode tree with a sort of
  1269. +    dewey-decimal record of subtree locations.  Like so:
  1270. +    (1 (1.1 1.2 1.3) 2 3 (3.1 (3.1.1 3.1.2) 3.2 3.3 (3.3.1)) 4)
  1271. +    Subtrees appear after their file, out of lexical order,
  1272. +    which would be before their file.  It's easier.
  1273. +    A directory can't hold more than 56 files, so 6 bits are used for
  1274. +    position numbers.  If the tree is so deep that the position encoding
  1275. +    doesn't fit, I'm sure something absolutely fascinating happens.
  1276. +    The actual sequence of f_pos values is
  1277. +        0 -> .   -1 -> ..   1 1.1 ... 8.9 9 -> files  -2 -> eof
  1278. +    The directory inode caches one position-to-dnode correspondence so
  1279. +    we won't have to repeatedly scan the top levels of the tree. */
  1280. + static int hpfs_readdir (struct inode *inode, struct file *filp,
  1281. +              struct dirent *dirent, int likely_story)
  1282. + {
  1283. +   struct buffer_head *bh;
  1284. +   struct hpfs_dirent *de;
  1285. +   int namelen, lc;
  1286. +   ino_t ino;
  1287. +   if (inode == 0
  1288. +       || inode->i_sb == 0
  1289. +       || ! S_ISDIR (inode->i_mode))
  1290. +     return -EBADF;
  1291. +   lc = inode->i_sb->s_hpfs_lowercase;
  1292. +   switch (filp->f_pos) {
  1293. +   case 0:
  1294. +     write_one_dirent (dirent, ".", 1, inode->i_ino, lc);
  1295. +     filp->f_pos = -1;
  1296. +     return 1;
  1297. +   case -1:
  1298. +     write_one_dirent (dirent, "..", 2, inode->i_hpfs_parent_dir, lc);
  1299. +     filp->f_pos = 1;
  1300. +     return 2;
  1301. +     
  1302. +   case -2:
  1303. +     return 0;
  1304. +   default:
  1305. +     de = map_pos_dirent (inode, &filp->f_pos, &bh);
  1306. +     if (! de) {
  1307. +       filp->f_pos = -2;
  1308. +       return 0;
  1309. +     }
  1310. +     namelen = de->namelen;
  1311. +     if (de->directory)
  1312. +       ino = dir_ino (de->fnode);
  1313. +     else
  1314. +       ino = file_ino (de->fnode);
  1315. +     write_one_dirent (dirent, de->name, namelen, ino, lc);
  1316. +     brelse (bh);
  1317. +     return namelen;
  1318. +   }
  1319. + } 
  1320. + /* Send the given name and ino off to the user dirent struct at *dirent.
  1321. +    Blam it to lowercase if the mount option said to.
  1322. +    Note that Linux d_reclen is the length of the file name, and has nothing
  1323. +    to do with the length of the dirent record.  Why is that, do you ask?
  1324. +    I sure do.  Jeez. */
  1325. + static void write_one_dirent (struct dirent *dirent, const unsigned char *name,
  1326. +                   unsigned namelen, ino_t ino, int lowercase)
  1327. + {
  1328. +   unsigned n;
  1329. +   put_fs_long (ino, &dirent->d_ino);
  1330. +   put_fs_word (namelen, &dirent->d_reclen);
  1331. +   if (lowercase)
  1332. +     for (n = namelen; n != 0; ) {
  1333. +       unsigned t = name[--n];
  1334. +       if (t - 'A' < 26) t += 040;
  1335. +       put_fs_byte (t, &dirent->d_name[n]);
  1336. +     }
  1337. +   else
  1338. +     memcpy_tofs (dirent->d_name, name, namelen);
  1339. +   put_fs_byte (0, &dirent->d_name[namelen]);
  1340. + }
  1341. + /* Map the dir entry at subtree coordinates given by *posp, and
  1342. +    increment *posp to point to the following dir entry. */
  1343. + static struct hpfs_dirent *map_pos_dirent (struct inode *inode, off_t *posp,
  1344. +                        struct buffer_head **bhp)
  1345. + {
  1346. +   unsigned pos, q, r;
  1347. +   dnode_secno dno;
  1348. +   struct hpfs_dirent *de;
  1349. +   /* Get the position code and split off the rightmost index */
  1350. +   pos = *posp;
  1351. +   q = pos >> 6;
  1352. +   r = pos & 077;
  1353. +   /* Get the sector address of the dnode pointed to by the leading part */
  1354. +   dno = dir_subdno (inode, q);
  1355. +   if (! dno) return 0;
  1356. +   /* Get the entry at index r in dnode q */
  1357. +   de = map_nth_dirent (inode->i_dev, dno, r, bhp);
  1358. +   /* If none, we're out of files at this level.  Ascend. */
  1359. +   if (! de) {
  1360. +     if (q == 0) return 0;
  1361. +     *posp = q + 1;
  1362. +     return map_pos_dirent (inode, posp, bhp);
  1363. +   }
  1364. +   /* If a subtree is here, descend. */
  1365. +   if (de->down)
  1366. +     *posp = pos << 6 | 1;
  1367. +   else
  1368. +     *posp = pos + 1;
  1369. +   /* Don't return the ^A^A and \377 entries. */
  1370. +   if (de->first || de->last) {
  1371. +     brelse (*bhp);
  1372. +     return map_pos_dirent (inode, posp, bhp);
  1373. +   } else
  1374. +     return de;
  1375. + }
  1376. + /* Return the address of the dnode with subtree coordinates given by pos. */
  1377. + static dnode_secno dir_subdno (struct inode *inode, unsigned pos)
  1378. + {
  1379. +   struct hpfs_dirent *de;
  1380. +   struct buffer_head *bh;
  1381. +   /* 0 is the root dnode */
  1382. +   if (pos == 0)
  1383. +     return inode->i_hpfs_dno;
  1384. +   /* we have one pos->dnode translation cached in the inode */
  1385. +   else if (pos == inode->i_hpfs_dpos)
  1386. +     return inode->i_hpfs_dsubdno;
  1387. +   /* otherwise go look */
  1388. +   else {
  1389. +     unsigned q = pos >> 6;
  1390. +     unsigned r = pos & 077;
  1391. +     dnode_secno dno;
  1392. +     /* dnode at position q */
  1393. +     dno = dir_subdno (inode, q);
  1394. +     if (dno == 0) return 0;
  1395. +     /* entry at index r */
  1396. +     de = map_nth_dirent (inode->i_dev, dno, r, &bh);
  1397. +     if (! de || ! de->down) return 0;
  1398. +     /* get the dnode down pointer */
  1399. +     dno = *(dnode_secno *) ((void *) de + de->length - 4);
  1400. +     brelse (bh);
  1401. +     /* cache it for next time */
  1402. +     inode->i_hpfs_dpos = pos;
  1403. +     inode->i_hpfs_dsubdno = dno;
  1404. +     return dno;
  1405. +   }
  1406. + }
  1407. + /* Return the dir entry at index n in dnode dno, or 0 if there isn't one */
  1408. + static struct hpfs_dirent *map_nth_dirent (dev_t dev, dnode_secno dno,
  1409. +                        int n, struct buffer_head **bhp)
  1410. + {
  1411. +   int i;
  1412. +   struct hpfs_dirent *de, *de_end;
  1413. +   struct dnode *dnode = map_dnode (dev, dno, bhp);
  1414. +   de = (void *) dnode->dirent;
  1415. +   de_end = (void *) de + dnode->first_free;
  1416. +   for (i = 1; de < de_end; i++, de = (void *) de + de->length) {
  1417. +     if (i == n)
  1418. +       return de;
  1419. +     if (de->last || de->length == 0)
  1420. +       break;
  1421. +   }
  1422. +   brelse (*bhp);
  1423. +   return 0;
  1424. + }
  1425. + static int hpfs_dir_read (struct inode *inode, struct file *filp,
  1426. +               char *buf, int count)
  1427. + {
  1428. +   return -EISDIR;
  1429. + }
  1430. + static int hpfs_create (struct inode * dir, const char *name, int len,
  1431. +             int mode, struct inode **result)
  1432. + {
  1433. +   return -EROFS;
  1434. + }
  1435. + static int hpfs_unlink (struct inode *dir, const char *name, int len)
  1436. + {
  1437. +   return -EROFS;
  1438. + }
  1439. + static int hpfs_mkdir (struct inode *dir, const char *name, int len, int mode)
  1440. + {
  1441. +   return -EROFS;
  1442. + }
  1443. + static int hpfs_rmdir (struct inode *dir, const char *name, int len)
  1444. + {
  1445. +   return -EROFS;
  1446. + }
  1447. + static int hpfs_rename
  1448. +     (struct inode *old_dir, const char *old_name, int old_len,
  1449. +      struct inode *new_dir, const char *new_name, int new_len)
  1450. + {
  1451. +   return -EROFS;
  1452. + }
  1453. + /* Return the dnode pointer in a directory fnode */
  1454. + static dnode_secno fnode_dno (dev_t dev, ino_t ino)
  1455. + {
  1456. +   struct buffer_head *bh;
  1457. +   struct fnode *fnode;
  1458. +   dnode_secno dno; 
  1459. +   fnode = map_fnode (dev, ino, &bh);
  1460. +   if (! fnode) return 0;
  1461. +   dno = fnode->u.external[0].disk_secno;
  1462. +   brelse (bh);
  1463. +   return dno;
  1464. + }
  1465. + /* Map an fnode into a buffer and return pointers to it and to the buffer. */
  1466. + static void *map_fnode (dev_t dev, ino_t ino, struct buffer_head **bhp)
  1467. + {
  1468. +   struct fnode *fnode;
  1469. +   if (ino == 0)
  1470. +     { printk ("HPFS: missing fnode\n"); return 0; }
  1471. +   fnode = map_sector (dev, ino_secno (ino), bhp);
  1472. +   if (fnode)
  1473. +     if (fnode->magic != FNODE_MAGIC || fnode->huhc4 != 0xc4)
  1474. +       { printk ("HPFS: map_fnode: in the weeds\n"); brelse (*bhp); return 0; }
  1475. +   return fnode;
  1476. + }
  1477. + /* Map an anode into a buffer and return pointers to it and to the buffer. */
  1478. + static void *map_anode (dev_t dev, unsigned secno, struct buffer_head **bhp)
  1479. + {
  1480. +   struct anode *anode;
  1481. +   if (secno == 0)
  1482. +     { printk ("HPFS: missing anode\n"); return 0; }
  1483. +   anode = map_sector (dev, secno, bhp);
  1484. +   if (anode)
  1485. +     if (anode->magic != ANODE_MAGIC || anode->self != secno)
  1486. +       { printk ("HPFS: map_anode: in the weeds\n"); brelse (*bhp); return 0; }
  1487. +   return anode;
  1488. + }
  1489. + /* Map a dnode into a buffer and return pointers to it and to the buffer. */
  1490. + static void *map_dnode (dev_t dev, unsigned secno, struct buffer_head **bhp)
  1491. + {
  1492. +   struct dnode *dnode; 
  1493. +   if (secno == 0)
  1494. +     { printk ("HPFS: missing dnode\n"); return 0; }
  1495. +   dnode = map_4sectors (dev, secno, bhp);
  1496. +   if (dnode)
  1497. +     if (dnode->magic != DNODE_MAGIC || dnode->self != secno)
  1498. +       { printk ("HPFS: map_dnode: in the weeds\n"); brelse (*bhp); return 0; }
  1499. +   return dnode;
  1500. + }
  1501. + /* Map a sector into a buffer and return pointers to it and to the buffer. */
  1502. + static void *map_sector (dev_t dev, unsigned secno, struct buffer_head **bhp)
  1503. + {
  1504. +   unsigned q, r;
  1505. +   struct buffer_head *bh;
  1506. +   q = secno >> 2;
  1507. +   r = (secno & 3) << 9;
  1508. +   if ((*bhp = bh = bread (dev, q, 2048)) != 0)
  1509. +     return bh->b_data + r;
  1510. +   else
  1511. +     { printk ("HPFS: map_sector: read error\n"); return 0; }
  1512. + }
  1513. + /* Map 4 sectors into a buffer and return pointers to it and to the buffer. */
  1514. + static void *map_4sectors (dev_t dev, unsigned secno, struct buffer_head **bhp)
  1515. + {
  1516. +   struct buffer_head *bh;
  1517. +   if (secno & 3)
  1518. +     { printk ("HPFS: map_4sectors: unaligned read\n"); return 0; }
  1519. +   if ((*bhp = bh = bread (dev, secno >> 2, 2048)) != 0)
  1520. +     return bh->b_data;
  1521. +   else 
  1522. +     { printk ("HPFS: map_4sectors: read error\n"); return 0; }
  1523. + }
  1524. diff -rc2N linux-dist/include/linux/fs.h linux/include/linux/fs.h
  1525. *** linux-dist/include/linux/fs.h    Sun Sep 19 13:53:23 1993
  1526. --- linux/include/linux/fs.h    Sun Oct 10 12:17:36 1993
  1527. ***************
  1528. *** 169,172 ****
  1529. --- 169,173 ----
  1530.   #include <linux/ext_fs_i.h>
  1531.   #include <linux/ext2_fs_i.h>
  1532. + #include <linux/hpfs_fs_i.h>
  1533.   #include <linux/msdos_fs_i.h>
  1534.   #include <linux/iso_fs_i.h>
  1535. ***************
  1536. *** 209,212 ****
  1537. --- 210,214 ----
  1538.           struct ext_inode_info ext_i;
  1539.           struct ext2_inode_info ext2_i;
  1540. +         struct hpfs_inode_info hpfs_i;
  1541.           struct msdos_inode_info msdos_i;
  1542.           struct iso_inode_info isofs_i;
  1543. ***************
  1544. *** 242,245 ****
  1545. --- 244,248 ----
  1546.   #include <linux/ext_fs_sb.h>
  1547.   #include <linux/ext2_fs_sb.h>
  1548. + #include <linux/hpfs_fs_sb.h>
  1549.   #include <linux/msdos_fs_sb.h>
  1550.   #include <linux/iso_fs_sb.h>
  1551. ***************
  1552. *** 265,268 ****
  1553. --- 268,272 ----
  1554.           struct ext_sb_info ext_sb;
  1555.           struct ext2_sb_info ext2_sb;
  1556. +         struct hpfs_sb_info hpfs_sb;
  1557.           struct msdos_sb_info msdos_sb;
  1558.           struct isofs_sb_info isofs_sb;
  1559. diff -rc2N linux-dist/include/linux/hpfs_fs.h linux/include/linux/hpfs_fs.h
  1560. *** linux-dist/include/linux/hpfs_fs.h
  1561. --- linux/include/linux/hpfs_fs.h    Sun Oct 10 12:17:36 1993
  1562. ***************
  1563. *** 0 ****
  1564. --- 1,12 ----
  1565. + #ifndef _LINUX_HPFS_FS_H
  1566. + #define _LINUX_HPFS_FS_H
  1567. + /* HPFS magic number (the real thing, word 0 of block 16) */
  1568. + #define HPFS_SUPER_MAGIC 0xf995e849
  1569. + /* The entry point for a VFS */
  1570. + extern struct super_block *hpfs_read_super (struct super_block *, void *, int);
  1571. + #endif
  1572. diff -rc2N linux-dist/include/linux/hpfs_fs_i.h linux/include/linux/hpfs_fs_i.h
  1573. *** linux-dist/include/linux/hpfs_fs_i.h
  1574. --- linux/include/linux/hpfs_fs_i.h    Sun Oct 10 12:17:36 1993
  1575. ***************
  1576. *** 0 ****
  1577. --- 1,24 ----
  1578. + #ifndef _HPFS_FS_I
  1579. + #define _HPFS_FS_I
  1580. + struct hpfs_inode_info {
  1581. +   ino_t i_parent_dir;        /* (directories) gives fnode of parent dir */
  1582. +   unsigned i_dno;        /* (directories) root dnode */
  1583. +   unsigned i_dpos;        /* (directories) temp for readdir */
  1584. +   unsigned i_dsubdno;        /* (directories) temp for readdir */
  1585. +   unsigned i_file_sec;        /* (files) minimalist cache of alloc info */
  1586. +   unsigned i_disk_sec;        /* (files) minimalist cache of alloc info */
  1587. +   unsigned i_n_secs;        /* (files) minimalist cache of alloc info */
  1588. +   unsigned i_conv : 2;        /* (files) crlf->newline hackery */
  1589. + };
  1590. + #define i_hpfs_dno u.hpfs_i.i_dno
  1591. + #define i_hpfs_parent_dir u.hpfs_i.i_parent_dir
  1592. + #define i_hpfs_n_secs u.hpfs_i.i_n_secs
  1593. + #define i_hpfs_file_sec u.hpfs_i.i_file_sec
  1594. + #define i_hpfs_disk_sec u.hpfs_i.i_disk_sec
  1595. + #define i_hpfs_dpos u.hpfs_i.i_dpos
  1596. + #define i_hpfs_dsubdno u.hpfs_i.i_dsubdno
  1597. + #define i_hpfs_conv u.hpfs_i.i_conv
  1598. + #endif
  1599. diff -rc2N linux-dist/include/linux/hpfs_fs_sb.h linux/include/linux/hpfs_fs_sb.h
  1600. *** linux-dist/include/linux/hpfs_fs_sb.h
  1601. --- linux/include/linux/hpfs_fs_sb.h    Sun Oct 10 12:17:37 1993
  1602. ***************
  1603. *** 0 ****
  1604. --- 1,31 ----
  1605. + #ifndef _HPFS_FS_SB
  1606. + #define _HPFS_FS_SB
  1607. + struct hpfs_sb_info
  1608. + {
  1609. +   ino_t sb_root;        /* inode number of root dir */
  1610. +   unsigned sb_fs_size;        /* file system size, sectors */
  1611. +   unsigned sb_dirband_size;    /* directory band size, dnodes */
  1612. +   unsigned sb_dmap;        /* sector number of dnode bit map */
  1613. +   unsigned sb_n_free;        /* free blocks for statfs, or -1 */
  1614. +   unsigned sb_n_free_dnodes;    /* free dnodes for statfs, or -1 */
  1615. +   uid_t sb_uid;            /* uid from mount options */
  1616. +   gid_t sb_gid;            /* gid from mount options */
  1617. +   umode_t sb_mode;        /* mode from mount options */
  1618. +   unsigned sb_lowercase : 1;    /* downcase filenames hackery */
  1619. +   unsigned sb_conv : 2;        /* crlf->newline hackery */
  1620. + };
  1621. + #define s_hpfs_root u.hpfs_sb.sb_root
  1622. + #define s_hpfs_fs_size u.hpfs_sb.sb_fs_size
  1623. + #define s_hpfs_dirband_size u.hpfs_sb.sb_dirband_size
  1624. + #define s_hpfs_dmap u.hpfs_sb.sb_dmap
  1625. + #define s_hpfs_uid u.hpfs_sb.sb_uid
  1626. + #define s_hpfs_gid u.hpfs_sb.sb_gid
  1627. + #define s_hpfs_mode u.hpfs_sb.sb_mode
  1628. + #define s_hpfs_n_free u.hpfs_sb.sb_n_free
  1629. + #define s_hpfs_n_free_dnodes u.hpfs_sb.sb_n_free_dnodes
  1630. + #define s_hpfs_lowercase u.hpfs_sb.sb_lowercase
  1631. + #define s_hpfs_conv u.hpfs_sb.sb_conv
  1632. + #endif
  1633.