~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/hfs/mdb.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.