mdb.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/fs/hfs/mdb.c
  3.  *
  4.  * Copyright (C) 1995-1997  Paul H. Hargrove
  5.  * This file may be distributed under the terms of the GNU General Public License.
  6.  *
  7.  * This file contains functions for reading/writing the MDB.
  8.  *
  9.  * "XXX" in a comment is a note to myself to consider changing something.
  10.  *
  11.  * In function preconditions the term "valid" applied to a pointer to
  12.  * a structure means that the pointer is non-NULL and the structure it
  13.  * points to has all fields initialized to consistent values.
  14.  *
  15.  * The code in this file initializes some structures which contain
  16.  * pointers by calling memset(&foo, 0, sizeof(foo)).
  17.  * This produces the desired behavior only due to the non-ANSI
  18.  * assumption that the machine representation of NULL is all zeros.
  19.  */
  20. #include "hfs.h"
  21. /*================ File-local data types ================*/
  22. /* 
  23.  * The HFS Master Directory Block (MDB).
  24.  *
  25.  * Also known as the Volume Information Block (VIB), this structure is
  26.  * the HFS equivalent of a superblock.
  27.  *
  28.  * Reference: _Inside Macintosh: Files_ pages 2-59 through 2-62
  29.  *
  30.  * modified for HFS Extended
  31.  */
  32. struct raw_mdb {
  33. hfs_word_t drSigWord; /* Signature word indicating fs type */
  34. hfs_lword_t drCrDate; /* fs creation date/time */
  35. hfs_lword_t drLsMod; /* fs modification date/time */
  36. hfs_word_t drAtrb; /* fs attributes */
  37. hfs_word_t drNmFls; /* number of files in root directory */
  38. hfs_word_t drVBMSt; /* location (in 512-byte blocks)
  39.    of the volume bitmap */
  40. hfs_word_t drAllocPtr; /* location (in allocation blocks)
  41.    to begin next allocation search */
  42. hfs_word_t drNmAlBlks; /* number of allocation blocks */
  43. hfs_lword_t drAlBlkSiz; /* bytes in an allocation block */
  44. hfs_lword_t drClpSiz; /* clumpsize, the number of bytes to
  45.    allocate when extending a file */
  46. hfs_word_t drAlBlSt; /* location (in 512-byte blocks)
  47.    of the first allocation block */
  48. hfs_lword_t drNxtCNID; /* CNID to assign to the next
  49.    file or directory created */
  50. hfs_word_t drFreeBks; /* number of free allocation blocks */
  51. hfs_byte_t drVN[28]; /* the volume label */
  52. hfs_lword_t drVolBkUp; /* fs backup date/time */
  53. hfs_word_t drVSeqNum; /* backup sequence number */
  54. hfs_lword_t drWrCnt; /* fs write count */
  55. hfs_lword_t drXTClpSiz; /* clumpsize for the extents B-tree */
  56. hfs_lword_t drCTClpSiz; /* clumpsize for the catalog B-tree */
  57. hfs_word_t drNmRtDirs; /* number of directories in
  58.    the root directory */
  59. hfs_lword_t drFilCnt; /* number of files in the fs */
  60. hfs_lword_t drDirCnt; /* number of directories in the fs */
  61. hfs_byte_t drFndrInfo[32]; /* data used by the Finder */
  62. hfs_word_t drEmbedSigWord; /* embedded volume signature */
  63. hfs_lword_t     drEmbedExtent;  /* starting block number (xdrStABN) 
  64.    and number of allocation blocks 
  65.    (xdrNumABlks) occupied by embedded
  66.    volume */
  67. hfs_lword_t drXTFlSize; /* bytes in the extents B-tree */
  68. hfs_byte_t drXTExtRec[12]; /* extents B-tree's first 3 extents */
  69. hfs_lword_t drCTFlSize; /* bytes in the catalog B-tree */
  70. hfs_byte_t drCTExtRec[12]; /* catalog B-tree's first 3 extents */
  71. } __attribute__((packed));
  72. /*================ Global functions ================*/
  73. /*
  74.  * hfs_mdb_get()
  75.  *
  76.  * Build the in-core MDB for a filesystem, including
  77.  * the B-trees and the volume bitmap.
  78.  */
  79. struct hfs_mdb *hfs_mdb_get(hfs_sysmdb sys_mdb, int readonly,
  80.     hfs_s32 part_start)
  81. {
  82. struct hfs_mdb *mdb;
  83. hfs_buffer buf;
  84. struct raw_mdb *raw;
  85. unsigned int bs, block;
  86. int lcv, limit;
  87. hfs_buffer *bmbuf;
  88. if (!HFS_NEW(mdb)) {
  89. hfs_warn("hfs_fs: out of memoryn");
  90. return NULL;
  91. }
  92. memset(mdb, 0, sizeof(*mdb));
  93. mdb->magic = HFS_MDB_MAGIC;
  94. mdb->sys_mdb = sys_mdb;
  95. INIT_LIST_HEAD(&mdb->entry_dirty);
  96. hfs_init_waitqueue(&mdb->rename_wait);
  97. hfs_init_waitqueue(&mdb->bitmap_wait);
  98. /* See if this is an HFS filesystem */
  99. buf = hfs_buffer_get(sys_mdb, part_start + HFS_MDB_BLK, 1);
  100. if (!hfs_buffer_ok(buf)) {
  101. hfs_warn("hfs_fs: Unable to read superblockn");
  102. HFS_DELETE(mdb);
  103. goto bail2;
  104. }
  105. raw = (struct raw_mdb *)hfs_buffer_data(buf);
  106. if (hfs_get_ns(raw->drSigWord) != htons(HFS_SUPER_MAGIC)) {
  107. hfs_buffer_put(buf);
  108. HFS_DELETE(mdb);
  109. goto bail2;
  110. }
  111. mdb->buf = buf;
  112. bs = hfs_get_hl(raw->drAlBlkSiz);
  113. if (!bs || (bs & (HFS_SECTOR_SIZE-1))) {
  114. hfs_warn("hfs_fs: bad allocation block size %d != 512n", bs);
  115. hfs_buffer_put(buf);
  116. HFS_DELETE(mdb);
  117. goto bail2;
  118. }
  119. mdb->alloc_blksz = bs >> HFS_SECTOR_SIZE_BITS;
  120. /* These parameters are read from the MDB, and never written */
  121. mdb->create_date = hfs_get_hl(raw->drCrDate);
  122. mdb->fs_ablocks  = hfs_get_hs(raw->drNmAlBlks);
  123. mdb->fs_start    = hfs_get_hs(raw->drAlBlSt) + part_start;
  124. mdb->backup_date = hfs_get_hl(raw->drVolBkUp);
  125. mdb->clumpablks  = (hfs_get_hl(raw->drClpSiz) / mdb->alloc_blksz)
  126.  >> HFS_SECTOR_SIZE_BITS;
  127. memcpy(mdb->vname, raw->drVN, sizeof(raw->drVN));
  128. /* These parameters are read from and written to the MDB */
  129. mdb->modify_date  = hfs_get_nl(raw->drLsMod);
  130. mdb->attrib       = hfs_get_ns(raw->drAtrb);
  131. mdb->free_ablocks = hfs_get_hs(raw->drFreeBks);
  132. mdb->next_id      = hfs_get_hl(raw->drNxtCNID);
  133. mdb->write_count  = hfs_get_hl(raw->drWrCnt);
  134. mdb->root_files   = hfs_get_hs(raw->drNmFls);
  135. mdb->root_dirs    = hfs_get_hs(raw->drNmRtDirs);
  136. mdb->file_count   = hfs_get_hl(raw->drFilCnt);
  137. mdb->dir_count    = hfs_get_hl(raw->drDirCnt);
  138. /* TRY to get the alternate (backup) MDB. */
  139. lcv = mdb->fs_start + mdb->fs_ablocks * mdb->alloc_blksz;
  140. limit = lcv + mdb->alloc_blksz;
  141. for (; lcv < limit; ++lcv) {
  142. buf = hfs_buffer_get(sys_mdb, lcv, 1);
  143. if (hfs_buffer_ok(buf)) {
  144. struct raw_mdb *tmp =
  145. (struct raw_mdb *)hfs_buffer_data(buf);
  146. if (hfs_get_ns(tmp->drSigWord) ==
  147.     htons(HFS_SUPER_MAGIC)) {
  148. mdb->alt_buf = buf;
  149. break;
  150. }
  151. }
  152. hfs_buffer_put(buf);
  153. }
  154. if (mdb->alt_buf == NULL) {
  155. hfs_warn("hfs_fs: unable to locate alternate MDBn");
  156. hfs_warn("hfs_fs: continuing without an alternate MDBn");
  157. }
  158. /* read in the bitmap */
  159. block = hfs_get_hs(raw->drVBMSt) + part_start;
  160. bmbuf = mdb->bitmap;
  161. lcv = (mdb->fs_ablocks + 4095) / 4096;
  162. for ( ; lcv; --lcv, ++bmbuf, ++block) {
  163. if (!hfs_buffer_ok(*bmbuf =
  164.    hfs_buffer_get(sys_mdb, block, 1))) {
  165. hfs_warn("hfs_fs: unable to read volume bitmapn");
  166. goto bail1;
  167. }
  168. }
  169. if (!(mdb->ext_tree = hfs_btree_init(mdb, htonl(HFS_EXT_CNID),
  170.      raw->drXTExtRec,
  171.      hfs_get_hl(raw->drXTFlSize),
  172.      hfs_get_hl(raw->drXTClpSiz))) ||
  173.     !(mdb->cat_tree = hfs_btree_init(mdb, htonl(HFS_CAT_CNID),
  174.      raw->drCTExtRec,
  175.      hfs_get_hl(raw->drCTFlSize),
  176.      hfs_get_hl(raw->drCTClpSiz)))) {
  177. hfs_warn("hfs_fs: unable to initialize data structuresn");
  178. goto bail1;
  179. }
  180. if (!(mdb->attrib & htons(HFS_SB_ATTRIB_CLEAN))) {
  181. hfs_warn("hfs_fs: WARNING: mounting unclean filesystem.n");
  182. } else if (!readonly) {
  183. /* Mark the volume uncleanly unmounted in case we crash */
  184. hfs_put_ns(mdb->attrib & htons(~HFS_SB_ATTRIB_CLEAN),
  185.    raw->drAtrb);
  186. hfs_buffer_dirty(mdb->buf);
  187. hfs_buffer_sync(mdb->buf);
  188. }
  189. return mdb;
  190. bail1:
  191. hfs_mdb_put(mdb, readonly);
  192. bail2:
  193. return NULL;
  194. }
  195. /*
  196.  * hfs_mdb_commit()
  197.  *
  198.  * Description:
  199.  *   This updates the MDB on disk (look also at hfs_write_super()).
  200.  *   It does not check, if the superblock has been modified, or
  201.  *   if the filesystem has been mounted read-only. It is mainly
  202.  *   called by hfs_write_super() and hfs_btree_extend().
  203.  * Input Variable(s):
  204.  *   struct hfs_mdb *mdb: Pointer to the hfs MDB
  205.  *   int backup;
  206.  * Output Variable(s):
  207.  *   NONE
  208.  * Returns:
  209.  *   void
  210.  * Preconditions:
  211.  *   'mdb' points to a "valid" (struct hfs_mdb).
  212.  * Postconditions:
  213.  *   The HFS MDB and on disk will be updated, by copying the possibly
  214.  *   modified fields from the in memory MDB (in native byte order) to
  215.  *   the disk block buffer.
  216.  *   If 'backup' is non-zero then the alternate MDB is also written
  217.  *   and the function doesn't return until it is actually on disk.
  218.  */
  219. void hfs_mdb_commit(struct hfs_mdb *mdb, int backup)
  220. {
  221. struct raw_mdb *raw = (struct raw_mdb *)hfs_buffer_data(mdb->buf);
  222. /* Commit catalog entries to buffers */
  223. hfs_cat_commit(mdb);
  224. /* Commit B-tree data to buffers */
  225. hfs_btree_commit(mdb->cat_tree, raw->drCTExtRec, raw->drCTFlSize);
  226. hfs_btree_commit(mdb->ext_tree, raw->drXTExtRec, raw->drXTFlSize);
  227. /* Update write_count and modify_date */
  228. ++mdb->write_count;
  229. mdb->modify_date = hfs_time();
  230. /* These parameters may have been modified, so write them back */
  231. hfs_put_nl(mdb->modify_date,   raw->drLsMod);
  232. hfs_put_hs(mdb->free_ablocks,  raw->drFreeBks);
  233. hfs_put_hl(mdb->next_id,       raw->drNxtCNID);
  234. hfs_put_hl(mdb->write_count,   raw->drWrCnt);
  235. hfs_put_hs(mdb->root_files,    raw->drNmFls);
  236. hfs_put_hs(mdb->root_dirs,     raw->drNmRtDirs);
  237. hfs_put_hl(mdb->file_count,    raw->drFilCnt);
  238. hfs_put_hl(mdb->dir_count,     raw->drDirCnt);
  239. /* write MDB to disk */
  240. hfs_buffer_dirty(mdb->buf);
  241.         /* write the backup MDB, not returning until it is written. 
  242.          * we only do this when either the catalog or extents overflow
  243.          * files grow. */
  244.         if (backup && hfs_buffer_ok(mdb->alt_buf)) {
  245. struct raw_mdb *tmp = (struct raw_mdb *)
  246. hfs_buffer_data(mdb->alt_buf);
  247. if ((hfs_get_hl(tmp->drCTFlSize) < 
  248.      hfs_get_hl(raw->drCTFlSize)) ||
  249.     (hfs_get_hl(tmp->drXTFlSize) <
  250.      hfs_get_hl(raw->drXTFlSize))) {
  251. memcpy(hfs_buffer_data(mdb->alt_buf), 
  252.        hfs_buffer_data(mdb->buf), HFS_SECTOR_SIZE); 
  253. hfs_buffer_dirty(mdb->alt_buf);
  254. hfs_buffer_sync(mdb->alt_buf);
  255. }
  256.         }
  257. }
  258. /*
  259.  * hfs_mdb_put()
  260.  *
  261.  * Release the resources associated with the in-core MDB.  */
  262. void hfs_mdb_put(struct hfs_mdb *mdb, int readonly) {
  263. int lcv;
  264. /* invalidate cached catalog entries */
  265. hfs_cat_invalidate(mdb);
  266. /* free the B-trees */
  267. hfs_btree_free(mdb->ext_tree);
  268. hfs_btree_free(mdb->cat_tree);
  269. /* free the volume bitmap */
  270. for (lcv = 0; lcv < HFS_BM_MAXBLOCKS; ++lcv) {
  271. hfs_buffer_put(mdb->bitmap[lcv]);
  272. }
  273. /* update volume attributes */
  274. if (!readonly) {
  275. struct raw_mdb *raw = 
  276. (struct raw_mdb *)hfs_buffer_data(mdb->buf);
  277. hfs_put_ns(mdb->attrib, raw->drAtrb);
  278. hfs_buffer_dirty(mdb->buf);
  279. }
  280. /* free the buffers holding the primary and alternate MDBs */
  281. hfs_buffer_put(mdb->buf);
  282. hfs_buffer_put(mdb->alt_buf);
  283. /* free the MDB */
  284. HFS_DELETE(mdb);
  285. }