/* * NAME: file->alloc() * DESCRIPTION: reserve allocation blocks for a file */ long f_alloc(hfsfile *file) { hfsvol *vol = file->vol; unsigned long clumpsz; ExtDescriptor blocks; clumpsz = file->cat.u.fil.filClpSize; if (clumpsz == 0) { if (file == &vol->ext.f) clumpsz = vol->mdb.drXTClpSiz; else if (file == &vol->cat.f) clumpsz = vol->mdb.drCTClpSiz; else clumpsz = vol->mdb.drClpSiz; } blocks.xdrNumABlks = clumpsz / vol->mdb.drAlBlkSiz; if (v_allocblocks(vol, &blocks) == -1) goto fail; if (f_addextent(file, &blocks) == -1) { v_freeblocks(vol, &blocks); goto fail; } return blocks.xdrNumABlks; fail: return -1; }
/* * NAME: file->alloc() * DESCRIPTION: reserve disk blocks for a file */ int f_alloc(hfsfile *file) { hfsvol *vol = file->vol; ExtDescriptor blocks; ExtDataRec *extrec; unsigned long *pylen, clumpsz; unsigned int start, end; node n; int i; clumpsz = file->clump; if (clumpsz == 0) clumpsz = vol->mdb.drClpSiz; blocks.xdrNumABlks = clumpsz / vol->mdb.drAlBlkSiz; if (v_allocblocks(vol, &blocks) < 0) return -1; /* update the file's extents */ f_getptrs(file, 0, &pylen, &extrec); start = file->fabn; end = *pylen / vol->mdb.drAlBlkSiz; n.nnum = 0; i = -1; while (start < end) { for (i = 0; i < 3; ++i) { unsigned int num; num = file->ext[i].xdrNumABlks; start += num; if (start == end) break; else if (start > end) { v_freeblocks(vol, &blocks); ERROR(EIO, "file extents exceed file physical length"); return -1; } else if (num == 0) { v_freeblocks(vol, &blocks); ERROR(EIO, "empty file extent"); return -1; } } if (start == end) break; if (v_extsearch(file, start, &file->ext, &n) <= 0) { v_freeblocks(vol, &blocks); return -1; } file->fabn = start; } if (i >= 0 && file->ext[i].xdrStABN + file->ext[i].xdrNumABlks == blocks.xdrStABN) file->ext[i].xdrNumABlks += blocks.xdrNumABlks; else { /* create a new extent descriptor */ if (++i < 3) file->ext[i] = blocks; else { ExtKeyRec key; unsigned char record[HFS_EXTRECMAXLEN]; int reclen; /* record is full; create a new one */ file->ext[0] = blocks; for (i = 1; i < 3; ++i) { file->ext[i].xdrStABN = 0; file->ext[i].xdrNumABlks = 0; } file->fabn = start; r_makeextkey(&key, file->fork, file->cat.u.fil.filFlNum, end); r_packextkey(&key, record, &reclen); r_packextdata(&file->ext, HFS_RECDATA(record), &reclen); if (bt_insert(&vol->ext, record, reclen) < 0) { v_freeblocks(vol, &blocks); return -1; } i = -1; } } if (i >= 0) { /* store the modified extent record */ if (file->fabn) { if ((n.nnum == 0 && v_extsearch(file, file->fabn, 0, &n) <= 0) || v_putextrec(&file->ext, &n) < 0) { v_freeblocks(vol, &blocks); return -1; } } else memcpy(extrec, file->ext, sizeof(ExtDataRec)); } *pylen += blocks.xdrNumABlks * vol->mdb.drAlBlkSiz; file->flags |= HFS_UPDATE_CATREC; return blocks.xdrNumABlks; }