/* * NAME: vol->mkdir() * DESCRIPTION: create a new HFS directory */ int v_mkdir(hfsvol *vol, long parid, const char *name) { CatKeyRec key; CatDataRec data; long id; byte record[HFS_MAX_CATRECLEN]; int i, reclen; if (bt_space(&vol->cat, 2) == -1) goto fail; id = vol->mdb.drNxtCNID++; vol->flags |= HFS_VOL_UPDATE_MDB; /* create directory record */ data.cdrType = cdrDirRec; data.cdrResrv2 = 0; data.u.dir.dirFlags = 0; data.u.dir.dirVal = 0; data.u.dir.dirDirID = id; data.u.dir.dirCrDat = d_mtime(time(0)); data.u.dir.dirMdDat = data.u.dir.dirCrDat; data.u.dir.dirBkDat = 0; memset(&data.u.dir.dirUsrInfo, 0, sizeof(data.u.dir.dirUsrInfo)); memset(&data.u.dir.dirFndrInfo, 0, sizeof(data.u.dir.dirFndrInfo)); for (i = 0; i < 4; ++i) data.u.dir.dirResrv[i] = 0; r_makecatkey(&key, parid, name); r_packcatrec(&key, &data, record, &reclen); if (bt_insert(&vol->cat, record, reclen) == -1) goto fail; /* create thread record */ data.cdrType = cdrThdRec; data.cdrResrv2 = 0; data.u.dthd.thdResrv[0] = 0; data.u.dthd.thdResrv[1] = 0; data.u.dthd.thdParID = parid; strcpy(data.u.dthd.thdCName, name); r_makecatkey(&key, id, ""); r_packcatrec(&key, &data, record, &reclen); if (bt_insert(&vol->cat, record, reclen) == -1 || v_adjvalence(vol, parid, 1, 1) == -1) goto fail; return 0; fail: return -1; }
void BItree<Dtype>::bt_insert(TreeNode*& root, TreeNode* n) { if (root == NULL) { root = n; return; } if (n->val < root->val) { bt_insert(root->left, n); } else { bt_insert(root->right, n); } }
int main (int argc, char *argv[]) { struct node *tree = NULL; struct node *lookup; struct in_addr ip; int idx; int random; char text[64]; printf ("Binary tree test\n"); for (idx = 0; idx < 10; idx++) { sprintf (text, "chiave %d", rand() % 16); bt_insert (&tree, text, &ip, idx); } printf ("Printing\n"); print_tree (tree); for (idx = 0; idx < 16; idx++) { sprintf (text, "chiave %d", idx); lookup = bt_search (tree, text); if (lookup == NULL) printf ("%s not found\n", text); else printf ("%s has been found with idx %d\n", lookup->key, lookup->expires); } bt_delete_tree (tree); printf ("Done\n"); }
void test_bt_1(CuTest* tc) { int val; int i; bt* tree; tree = bt_new(sizeof(int), 4); printf("Empty:\n"); bt_print(tree, print_int); printf("\n"); { int vals[] = { 10, 5, 100, 10, 50, 50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 200,200,200,200,200,250,150 }; for (i=0; i<sizeof(vals)/sizeof(int); i++) { val = vals[i]; printf("Insert %i:\n", val); bt_insert(tree, &val, 0, compare_ints); //bt_print(tree, print_int); printf("\n"); } } printf("Values: "); for (i=0; i<tree->N; i++) { int val = *(int*)bt_access(tree, i); printf("%i ", val); // these tests depend on the values in the "vals" array above. if (i < 11) { CuAssertIntEquals(tc, 1, val); } else if (i < 12) { CuAssertIntEquals(tc, 5, val); } else if (i < 14) { CuAssertIntEquals(tc, 10, val); } else if (i < 16) { CuAssertIntEquals(tc, 50, val); } else if (i < 17) { CuAssertIntEquals(tc, 100, val); } else if (i < 18) { CuAssertIntEquals(tc, 150, val); } else if (i < 23) { CuAssertIntEquals(tc, 200, val); } else { CuAssertIntEquals(tc, 250, val); } } printf("\n"); { int vals[] = { 0, 1, 2, 9, 10, 11, 49, 50, 51, 99, 100, 101, 149, 150, 151, 199, 200, 201, 249, 250, 251 }; int doesit[]={ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 }; for (i=0; i<sizeof(vals)/sizeof(int); i++) { int youthink; val = vals[i]; youthink = bt_contains(tree, &val, compare_ints); printf("Contains %i: %s\n", val, (youthink ? "yes" : "no")); CuAssertIntEquals(tc, doesit[i], youthink); } } bt_free(tree); }
TREE_NODE bt_insert(element_type element, BTREE T){ TREE_NODE tmp; if(T == NULL){ return new_node(element); } else{ if(element < T->element){ tmp = bt_insert(element, T->left); T->left = tmp; } if(element > T->element){ tmp = bt_insert(element, T->right); T->right = tmp; } return T; } }
static int rdbLoadRow(FILE *fp, bt *btr) { void *UUbuf; uint32 ssize; if ((ssize = rdbLoadLen(fp, NULL)) == REDIS_RDB_LENERR) return -1; void *bt_val = UU(btr) ? &UUbuf : bt_malloc(ssize, btr); if (fread(bt_val, ssize, 1, fp) == 0) return -1; if (btr->numkeys == TRANSITION_ONE_MAX) { btr = abt_resize(btr, TRANSITION_TWO_BTREE); } if UU(btr) bt_insert(btr, UUbuf); else bt_insert(btr, bt_val);
BTREE creat_tree(element_type *array, int total, BTREE T){ int i; BTREE p; T->element = *array; p = T; for(i=1; i<total; i++) bt_insert(*(array+i), p); return T; }
/* Moves P around in BT to compensate for its key having changed. Returns a null pointer if successful. If P's new value is equal to that of some other node in BT, returns the other node after removing P from BT. This function is an optimization only if it is likely that P can actually retain its relative position in BT, e.g. its key has only been adjusted slightly. Otherwise, it is more efficient to simply remove P from BT, change its key, and re-insert P. It is not safe to update more than one node's key, then to call this function for each node. Instead, update a single node's key, call this function, update another node's key, and so on. Alternatively, remove all affected nodes from the tree, update their keys, then re-insert all of them. */ struct bt_node * bt_changed (struct bt *bt, struct bt_node *p) { struct bt_node *prev = bt_prev (bt, p); struct bt_node *next = bt_next (bt, p); if ((prev != NULL && bt->compare (prev, p, bt->aux) >= 0) || (next != NULL && bt->compare (p, next, bt->aux) >= 0)) { bt_delete (bt, p); return bt_insert (bt, p); } return NULL; }
TREE_NODE bt_insert(element_type element, BTREE T){ if(T == NULL){ T = (TREE_NODE)malloc(sizeof(struct btree_node)); if(T == NULL){ printf("insert malloc error\n"); exit(1); } else{ T->element = element; T->left = NULL; T->right = NULL; } } else if(element < T->element){ T->left = bt_insert(element, T->left); } else if(element > T->element){ T->right = bt_insert(element, T->right); } return T; }
void test_bt_many(CuTest* tc) { int val; int i; bt* tree; printf("Inserting many items...\n"); tree = bt_new(sizeof(int), 32); for (i=0; i<100000; i++) { val = rand() % 1000; bt_insert(tree, &val, 0, compare_ints); //bt_check(tree); } printf("Checking...\n"); CuAssertIntEquals(tc, 0, bt_check(tree)); printf("Done.\n"); bt_free(tree); }
int main(int argc, char *argv[]){ element_type array[20]; int i; BTREE T = NULL; for(i=0; i<20; i++){ array[i] = random(200); printf("%d ", array[i]); T = bt_insert(array[i], T); } printf("\n"); inorder(T); printf("\n"); treefree(T); return 0; }
smcp_node_t smcp_node_init( smcp_node_t self, smcp_node_t node, const char* name ) { smcp_node_t ret = NULL; require(self || (self = smcp_node_alloc()), bail); ret = (smcp_node_t)self; ret->request_handler = (void*)&smcp_default_request_handler; if (node) { require(name, bail); ret->name = name; #if SMCP_NODE_ROUTER_USE_BTREE bt_insert( (void**)&((smcp_node_t)node)->children, ret, (bt_compare_func_t)smcp_node_compare, (bt_delete_func_t)smcp_node_delete, NULL ); #else ll_prepend( (void**)&((smcp_node_t)node)->children, (void*)ret ); #endif ret->parent = node; } DEBUG_PRINTF("%s: %p",__func__,ret); bail: return ret; }
/* * NAME: hfs->rename() * DESCRIPTION: change the name of and/or move a file or directory */ int hfs_rename(hfsvol *vol, const char *srcpath, const char *dstpath) { hfsvol *srcvol; CatDataRec src, dst; unsigned long srcid, dstid; CatKeyRec key; char srcname[HFS_MAX_FLEN + 1], dstname[HFS_MAX_FLEN + 1]; byte record[HFS_MAX_CATRECLEN]; unsigned int reclen; int found, isdir, moving; node n; if (getvol(&vol) == -1 || v_resolve(&vol, srcpath, &src, &srcid, srcname, 0) <= 0) goto fail; isdir = (src.cdrType == cdrDirRec); srcvol = vol; found = v_resolve(&vol, dstpath, &dst, &dstid, dstname, 0); if (found == -1) goto fail; if (vol != srcvol) ERROR(EINVAL, "can't move across volumes"); if (dstid == 0) ERROR(ENOENT, "bad destination path"); if (found && dst.cdrType == cdrDirRec && dst.u.dir.dirDirID != src.u.dir.dirDirID) { dstid = dst.u.dir.dirDirID; strcpy(dstname, srcname); found = v_catsearch(vol, dstid, dstname, 0, 0, 0); if (found == -1) goto fail; } moving = (srcid != dstid); if (found) { const char *ptr; ptr = strrchr(dstpath, ':'); if (ptr == 0) ptr = dstpath; else ++ptr; if (*ptr) strcpy(dstname, ptr); if (! moving && strcmp(srcname, dstname) == 0) goto done; /* source and destination are identical */ if (moving || d_relstring(srcname, dstname)) ERROR(EEXIST, "can't use destination name"); } /* can't move anything into the root directory's parent */ if (moving && dstid == HFS_CNID_ROOTPAR) ERROR(EINVAL, "can't move above root directory"); if (moving && isdir) { unsigned long id; /* can't move root directory anywhere */ if (src.u.dir.dirDirID == HFS_CNID_ROOTDIR) ERROR(EINVAL, "can't move root directory"); /* make sure we aren't trying to move a directory inside itself */ for (id = dstid; id != HFS_CNID_ROOTDIR; id = dst.u.dthd.thdParID) { if (id == src.u.dir.dirDirID) ERROR(EINVAL, "can't move directory inside itself"); if (v_getdthread(vol, id, &dst, 0) <= 0) goto fail; } } if (vol->flags & HFS_VOL_READONLY) ERROR(EROFS, 0); /* change volume name */ if (dstid == HFS_CNID_ROOTPAR) { if (! validvname(dstname)) goto fail; strcpy(vol->mdb.drVN, dstname); vol->flags |= HFS_VOL_UPDATE_MDB; } /* remove source record */ r_makecatkey(&key, srcid, srcname); r_packcatkey(&key, record, 0); if (bt_delete(&vol->cat, record) == -1) goto fail; /* insert destination record */ r_makecatkey(&key, dstid, dstname); r_packcatrec(&key, &src, record, &reclen); if (bt_insert(&vol->cat, record, reclen) == -1) goto fail; /* update thread record */ if (isdir) { if (v_getdthread(vol, src.u.dir.dirDirID, &dst, &n) <= 0) goto fail; dst.u.dthd.thdParID = dstid; strcpy(dst.u.dthd.thdCName, dstname); if (v_putcatrec(&dst, &n) == -1) goto fail; } else { found = v_getfthread(vol, src.u.fil.filFlNum, &dst, &n); if (found == -1) goto fail; if (found) { dst.u.fthd.fthdParID = dstid; strcpy(dst.u.fthd.fthdCName, dstname); if (v_putcatrec(&dst, &n) == -1) goto fail; } } /* update directory valences */ if (moving) { if (v_adjvalence(vol, srcid, isdir, -1) == -1 || v_adjvalence(vol, dstid, isdir, 1) == -1) goto fail; } done: return 0; fail: return -1; }
int main() { struct bt_node *root; int i, n; root = bt_node_new(651); #if 0 n = 20; /* for(i = n; i >= 1; --i) { root = bt_insert(root, i, i+1); bt_dump(root); } printf("----------------\n"); root = bt_node_new(5); */ for(i = 1; i <= n; ++i) { root = bt_insert(root, i, i+1); } bt_dump(root); printf("----------------\n"); bt_save(root, "/tmp/large.bin"); root = bt_load("/tmp/large.bin"); bt_dump(root); return 0; #endif n = 1000*1000; //n = 20; #if 1 struct timespec t0, t1, t2, t3, t4; clock_gettime(CLOCK_MONOTONIC, &t0); //for(i = n; i >= 1; i--) { for(i = 1; i < n; i++) { struct bt_entry *e; char *key = calloc(20, 1); sprintf(key, "key-%d", i); root = bt_insert(root, key, strlen(key), i+1, 0); continue; e = bt_lookup(root, key, strlen(key)); /* immediate read-back */ if(e && e->value_offset != (uint32_t)i+1) { printf("at k=[%d]: %d\n", i, e->value_offset); } } clock_gettime(CLOCK_MONOTONIC, &t1); printf("saving index of %d elements.\n", n); bt_save(root, "/tmp/large.bin"); clock_gettime(CLOCK_MONOTONIC, &t2); // bt_dump(root); bt_free(root); printf("saved.\n"); uint32_t offset, size; char *key = malloc(40); sprintf(key, "key-%d", 1 + (rand() % (n-1))); if(0 == bt_find("/tmp/large.bin", key, strlen(key), &offset, &size)) { printf("%s: offset=%d, size=%d\n", key, (int)offset, (int)size); } else { printf("could not find %s\n", key); } return 0; // root = bt_load("/tmp/large.bin"); // clock_gettime(CLOCK_MONOTONIC, &t3); // printf("loaded.\n"); bt_dump(root); for(i = 1; i < n; i++) { char *key = calloc(20, 1); sprintf(key, "key-%d", i); struct bt_entry *e = bt_lookup(root, key, strlen(key)); /* read-back after the whole insertion */ if(!e) { printf("e=nil.\n"); } else if(e->value_offset != (uint32_t)i+1) { printf("at k=[%d]: %d\n", i, e->value_offset); } } clock_gettime(CLOCK_MONOTONIC, &t4); printf("checked.\n"); float mili0 = t0.tv_sec * 1000 + t0.tv_nsec / 1000000; float mili1 = t1.tv_sec * 1000 + t1.tv_nsec / 1000000; float mili2 = t2.tv_sec * 1000 + t2.tv_nsec / 1000000; float mili3 = t3.tv_sec * 1000 + t3.tv_nsec / 1000000; float mili4 = t4.tv_sec * 1000 + t4.tv_nsec / 1000000; printf("build time: %0.2f sec.\n", (mili1 - mili0)/1000.0); printf("dump time: %0.2f sec.\n", (mili2 - mili1)/1000.0); printf("reload time: %0.2f sec.\n", (mili3 - mili2)/1000.0); printf("check time: %0.2f sec.\n", (mili4 - mili3)/1000.0); /* root = bt_node_new(5); bt_insert(root, 706); bt_insert(root, 176); bt_insert(root, 601); bt_insert(root, 153); bt_insert(root, 513); bt_insert(root, 773); */ #endif return EXIT_SUCCESS; }
void catalog_before_commit(bool is_commit) { /* * Final journal commit. Done by single transaction at a time */ if (!is_commit) { return; } try { catalog_journal_record *r; xptr *tree; bt_key name; char * htname; catalog_validate_objects(); catalog_lock_metadata(); cs_initp(); r = local_catalog->catalog_journal; while (r != NULL) { switch (r->type) { case catalog_journal_record::add_name: tree = &(CATALOG_NAME_TREE(r->nor.object_type)); name.setnew(r->nor.name_to_save->name); if (*tree == XNULL) { *tree = bt_create(xs_string); } bt_insert(*tree, name, r->nor.name_to_save->obj->p); break; case catalog_journal_record::del_name: tree = &(CATALOG_NAME_TREE(r->nor.object_type)); name.setnew(r->nor.name_to_save->name); bt_delete(*tree, name, r->nor.name_to_save->obj->p); htname = catalog_ht_fullname_string(r->nor.object_type, r->nor.name_to_save->name, NULL); local_catalog->masterdata.htable = sbtrie_delete_str(local_catalog->masterdata.htable, htname); free(htname); break; case catalog_journal_record::add_htable_record: local_catalog->masterdata.htable = sbtrie_insert_str(local_catalog->masterdata.htable, r->htr.name, r->htr.data, strlen(r->htr.data) + 2, true); break; } r = r->next; local_catalog->masterdata_updated = true; } local_catalog->catalog_journal = NULL; if (local_catalog->masterdata_updated) { WRITEP(catalog_masterblock); memcpy( &(((catalog_master_record *) XADDR(catalog_masterblock))->masterdata), &(local_catalog->masterdata), sizeof(catalog_name_trees)); local_catalog->masterdata_updated = false; } if (!tr_globals::is_ro_mode) { WRITEP(catalog_masterblock); memcpy( &(((catalog_master_record *) XADDR(catalog_masterblock))->last_nid_size), &last_nid_size, sizeof(int)); memcpy( ((catalog_master_record *) XADDR(catalog_masterblock))->last_nid, last_nid, last_nid_size); } } catch (ANY_SE_EXCEPTION) { catalog_unlock_metadata(); throw; } }
/* * 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; }
void btTreeInsert(Dtype e) { bt_insert(root, e); }
void BItree<Dtype>::bt_insert(TreeNode*& root, Dtype e) { bt_insert(root, new TreeNode(e)); }
int hfs_callback_format(oscallback func, void* cookie, int mode, const char* vname) #endif { hfsvol vol; btree *ext = &vol.ext; btree *cat = &vol.cat; unsigned int i, *badalloc = 0; v_init(&vol, mode); if (! validvname(vname)) goto fail; #ifdef CP_NOT_USED if (v_open(&vol, path, HFS_MODE_RDWR) == -1 || v_geometry(&vol, pnum) == -1) goto fail; #else if (v_callback_open(&vol, func, cookie) != 0 || v_geometry(&vol, 0) != 0) goto fail; #endif /* initialize volume geometry */ vol.lpa = 1 + ((vol.vlen - 6) >> 16); if (vol.flags & HFS_OPT_2048) vol.lpa = (vol.lpa + 3) & ~3; vol.vbmsz = (vol.vlen / vol.lpa + 0x0fff) >> 12; vol.mdb.drSigWord = HFS_SIGWORD; vol.mdb.drCrDate = d_mtime(time(0)); vol.mdb.drLsMod = vol.mdb.drCrDate; vol.mdb.drAtrb = 0; vol.mdb.drNmFls = 0; vol.mdb.drVBMSt = 3; vol.mdb.drAllocPtr = 0; vol.mdb.drAlBlkSiz = vol.lpa << HFS_BLOCKSZ_BITS; vol.mdb.drClpSiz = vol.mdb.drAlBlkSiz << 2; vol.mdb.drAlBlSt = vol.mdb.drVBMSt + vol.vbmsz; if (vol.flags & HFS_OPT_2048) vol.mdb.drAlBlSt = ((vol.vstart & 3) + vol.mdb.drAlBlSt + 3) & ~3; vol.mdb.drNmAlBlks = (vol.vlen - 2 - vol.mdb.drAlBlSt) / vol.lpa; vol.mdb.drNxtCNID = HFS_CNID_ROOTDIR; /* modified later */ vol.mdb.drFreeBks = vol.mdb.drNmAlBlks; strcpy(vol.mdb.drVN, vname); vol.mdb.drVolBkUp = 0; vol.mdb.drVSeqNum = 0; vol.mdb.drWrCnt = 0; vol.mdb.drXTClpSiz = vol.mdb.drNmAlBlks / 128 * vol.mdb.drAlBlkSiz; vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz; vol.mdb.drNmRtDirs = 0; vol.mdb.drFilCnt = 0; vol.mdb.drDirCnt = -1; /* incremented when root directory is created */ for (i = 0; i < 8; ++i) vol.mdb.drFndrInfo[i] = 0; vol.mdb.drEmbedSigWord = 0x0000; vol.mdb.drEmbedExtent.xdrStABN = 0; vol.mdb.drEmbedExtent.xdrNumABlks = 0; /* vol.mdb.drXTFlSize */ /* vol.mdb.drCTFlSize */ /* vol.mdb.drXTExtRec[0..2] */ /* vol.mdb.drCTExtRec[0..2] */ vol.flags |= HFS_VOL_UPDATE_MDB | HFS_VOL_UPDATE_ALTMDB; /* initialize volume bitmap */ vol.vbm = ALLOC(block, vol.vbmsz); if (vol.vbm == 0) ERROR(ENOMEM, 0); memset(vol.vbm, 0, vol.vbmsz << HFS_BLOCKSZ_BITS); vol.flags |= HFS_VOL_UPDATE_VBM; /* perform initial bad block sparing */ #ifdef CP_NOT_USED if (nbadblocks > 0) { if (nbadblocks * 4 > vol.vlen) ERROR(EINVAL, "volume contains too many bad blocks"); badalloc = ALLOC(unsigned int, nbadblocks); if (badalloc == 0) ERROR(ENOMEM, 0); if (vol.mdb.drNmAlBlks == 1594) vol.mdb.drFreeBks = --vol.mdb.drNmAlBlks; for (i = 0; i < nbadblocks; ++i) { unsigned long bnum; unsigned int anum; bnum = badblocks[i]; if (bnum < vol.mdb.drAlBlSt || bnum == vol.vlen - 2) ERROR(EINVAL, "can't spare critical bad block"); else if (bnum >= vol.vlen) ERROR(EINVAL, "bad block not in volume"); anum = (bnum - vol.mdb.drAlBlSt) / vol.lpa; if (anum < vol.mdb.drNmAlBlks) BMSET(vol.vbm, anum); badalloc[i] = anum; } vol.mdb.drAtrb |= HFS_ATRB_BBSPARED; } #endif /* create extents overflow file */ n_init(&ext->hdrnd, ext, ndHdrNode, 0); ext->hdrnd.nnum = 0; ext->hdrnd.nd.ndNRecs = 3; ext->hdrnd.roff[1] = 0x078; ext->hdrnd.roff[2] = 0x0f8; ext->hdrnd.roff[3] = 0x1f8; memset(HFS_NODEREC(ext->hdrnd, 1), 0, 128); ext->hdr.bthDepth = 0; ext->hdr.bthRoot = 0; ext->hdr.bthNRecs = 0; ext->hdr.bthFNode = 0; ext->hdr.bthLNode = 0; ext->hdr.bthNodeSize = HFS_BLOCKSZ; ext->hdr.bthKeyLen = 0x07; ext->hdr.bthNNodes = 0; ext->hdr.bthFree = 0; for (i = 0; i < 76; ++i) ext->hdr.bthResv[i] = 0; ext->map = ALLOC(byte, HFS_MAP1SZ); if (ext->map == 0) ERROR(ENOMEM, 0); memset(ext->map, 0, HFS_MAP1SZ); BMSET(ext->map, 0); ext->mapsz = HFS_MAP1SZ; ext->flags = HFS_BT_UPDATE_HDR; /* create catalog file */ n_init(&cat->hdrnd, cat, ndHdrNode, 0); cat->hdrnd.nnum = 0; cat->hdrnd.nd.ndNRecs = 3; cat->hdrnd.roff[1] = 0x078; cat->hdrnd.roff[2] = 0x0f8; cat->hdrnd.roff[3] = 0x1f8; memset(HFS_NODEREC(cat->hdrnd, 1), 0, 128); cat->hdr.bthDepth = 0; cat->hdr.bthRoot = 0; cat->hdr.bthNRecs = 0; cat->hdr.bthFNode = 0; cat->hdr.bthLNode = 0; cat->hdr.bthNodeSize = HFS_BLOCKSZ; cat->hdr.bthKeyLen = 0x25; cat->hdr.bthNNodes = 0; cat->hdr.bthFree = 0; for (i = 0; i < 76; ++i) cat->hdr.bthResv[i] = 0; cat->map = ALLOC(byte, HFS_MAP1SZ); if (cat->map == 0) ERROR(ENOMEM, 0); memset(cat->map, 0, HFS_MAP1SZ); BMSET(cat->map, 0); cat->mapsz = HFS_MAP1SZ; cat->flags = HFS_BT_UPDATE_HDR; /* allocate space for header nodes (and initial extents) */ if (bt_space(ext, 1) == -1 || bt_space(cat, 1) == -1) goto fail; --ext->hdr.bthFree; --cat->hdr.bthFree; /* create extent records for bad blocks */ #ifdef CP_NOT_USED if (nbadblocks > 0) { hfsfile bbfile; ExtDescriptor extent; ExtDataRec *extrec; ExtKeyRec key; byte record[HFS_MAX_EXTRECLEN]; unsigned int reclen; f_init(&bbfile, &vol, HFS_CNID_BADALLOC, "bad blocks"); qsort(badalloc, nbadblocks, sizeof(*badalloc), (int (*)(const void *, const void *)) compare); for (i = 0; i < nbadblocks; ++i) { if (i == 0 || badalloc[i] != extent.xdrStABN) { extent.xdrStABN = badalloc[i]; extent.xdrNumABlks = 1; if (extent.xdrStABN < vol.mdb.drNmAlBlks && f_addextent(&bbfile, &extent) == -1) goto fail; } } /* flush local extents into extents overflow file */ f_getptrs(&bbfile, &extrec, 0, 0); r_makeextkey(&key, bbfile.fork, bbfile.cat.u.fil.filFlNum, 0); r_packextrec(&key, extrec, record, &reclen); if (bt_insert(&vol.ext, record, reclen) == -1) goto fail; } #endif vol.flags |= HFS_VOL_MOUNTED; /* create root directory */ if (v_mkdir(&vol, HFS_CNID_ROOTPAR, vname) == -1) goto fail; vol.mdb.drNxtCNID = 16; /* first CNID not reserved by Apple */ /* write boot blocks */ if (m_zerobb(&vol) == -1) goto fail; /* zero other unused space, if requested */ if (vol.flags & HFS_OPT_ZERO) { block b; unsigned long bnum; memset(&b, 0, sizeof(b)); /* between MDB and VBM (never) */ for (bnum = 3; bnum < vol.mdb.drVBMSt; ++bnum) b_writelb(&vol, bnum, &b); /* between VBM and first allocation block (sometimes if HFS_OPT_2048) */ for (bnum = vol.mdb.drVBMSt + vol.vbmsz; bnum < vol.mdb.drAlBlSt; ++bnum) b_writelb(&vol, bnum, &b); /* between last allocation block and alternate MDB (sometimes) */ for (bnum = vol.mdb.drAlBlSt + vol.mdb.drNmAlBlks * vol.lpa; bnum < vol.vlen - 2; ++bnum) b_writelb(&vol, bnum, &b); /* final block (always) */ b_writelb(&vol, vol.vlen - 1, &b); } /* flush remaining state and close volume */ if (v_close(&vol) == -1) goto fail; FREE(badalloc); return 0; fail: v_close(&vol); FREE(badalloc); return -1; }
/* * NAME: hfs->create() * DESCRIPTION: create and open a new file */ hfsfile *hfs_create(hfsvol *vol, const char *path, const char *type, const char *creator) { hfsfile *file = 0; unsigned long parid; char name[HFS_MAX_FLEN + 1]; CatKeyRec key; byte record[HFS_MAX_CATRECLEN]; unsigned reclen; int found; if (getvol(&vol) == -1) goto fail; file = ALLOC(hfsfile, 1); if (file == 0) ERROR(ENOMEM, 0); found = v_resolve(&vol, path, &file->cat, &parid, name, 0); if (found == -1 || parid == 0) goto fail; if (found) ERROR(EEXIST, 0); if (parid == HFS_CNID_ROOTPAR) ERROR(EINVAL, 0); if (vol->flags & HFS_VOL_READONLY) ERROR(EROFS, 0); /* create file `name' in parent `parid' */ if (bt_space(&vol->cat, 1) == -1) goto fail; f_init(file, vol, vol->mdb.drNxtCNID++, name); vol->flags |= HFS_VOL_UPDATE_MDB; file->parid = parid; /* create catalog record */ file->cat.u.fil.filUsrWds.fdType = d_getsl((const unsigned char *) type); file->cat.u.fil.filUsrWds.fdCreator = d_getsl((const unsigned char *) creator); file->cat.u.fil.filCrDat = d_mtime(time(0)); file->cat.u.fil.filMdDat = file->cat.u.fil.filCrDat; r_makecatkey(&key, file->parid, file->name); r_packcatrec(&key, &file->cat, record, &reclen); if (bt_insert(&vol->cat, record, reclen) == -1 || v_adjvalence(vol, file->parid, 0, 1) == -1) goto fail; /* package file handle for user */ file->next = vol->files; if (vol->files) vol->files->prev = file; vol->files = file; return file; fail: FREE(file); return 0; }
void rbt_insert( /*@in@*/ RBT_ROOT *root , RBT_NODE *x ) { RBT_NODE *y ; rbt_validate( root , root->node , NULL ) ; HQTRACE( rbt_debug , ( "rbt_insert: [%x] %x" , root , x->key )) ; bt_insert( root , x ) ; x->red = TRUE ; while ( x != root->node && x->p->red ) { if ( x->p == x->p->p->left ) { y = x->p->p->right ; if ( y->red ) { x->p->red = FALSE ; y->red = FALSE ; x->p->p->red = TRUE ; x = x->p->p ; } else { if ( x == x->p->right ) { x = x->p ; rbt_leftrotate( root , x ) ; } x->p->red = FALSE ; x->p->p->red = TRUE ; rbt_rightrotate( root , x->p->p ) ; } } else { y = x->p->p->left ; if ( y->red ) { x->p->red = FALSE ; y->red = FALSE ; x->p->p->red = TRUE ; x = x->p->p ; } else { if ( x == x->p->left ) { x = x->p ; rbt_rightrotate( root , x ) ; } x->p->red = FALSE ; x->p->p->red = TRUE ; rbt_leftrotate( root , x->p->p ) ; } } } root->node->red = FALSE ; root->count++ ; rbt_validate( root , root->node , NULL ) ; }
/* * NAME: vol->newfolder() * DESCRIPTION: create a new HFS folder */ int v_newfolder(hfsvol *vol, long parid, char *name) { CatKeyRec key; CatDataRec data; long id; unsigned char record[HFS_CATRECMAXLEN]; int i, reclen; if (bt_space(&vol->cat, 2) < 0) return -1; id = vol->mdb.drNxtCNID++; vol->flags |= HFS_UPDATE_MDB; /* create directory record */ data.cdrType = cdrDirRec; data.cdrResrv2 = 0; data.u.dir.dirFlags = 0; data.u.dir.dirVal = 0; data.u.dir.dirDirID = id; #ifdef UHFS data.u.dir.dirCrDat = 0; #else data.u.dir.dirCrDat = d_tomtime(time(0)); #endif data.u.dir.dirMdDat = data.u.dir.dirCrDat; data.u.dir.dirBkDat = 0; memset(&data.u.dir.dirUsrInfo, 0, sizeof(data.u.dir.dirUsrInfo)); memset(&data.u.dir.dirFndrInfo, 0, sizeof(data.u.dir.dirFndrInfo)); for (i = 0; i < 4; ++i) data.u.dir.dirResrv[i] = 0; r_makecatkey(&key, parid, name); r_packcatkey(&key, record, &reclen); r_packcatdata(&data, HFS_RECDATA(record), &reclen); if (bt_insert(&vol->cat, record, reclen) < 0) return -1; /* create thread record */ data.cdrType = cdrThdRec; data.cdrResrv2 = 0; data.u.dthd.thdResrv[0] = 0; data.u.dthd.thdResrv[1] = 0; data.u.dthd.thdParID = parid; strcpy(data.u.dthd.thdCName, name); r_makecatkey(&key, id, ""); r_packcatkey(&key, record, &reclen); r_packcatdata(&data, HFS_RECDATA(record), &reclen); if (bt_insert(&vol->cat, record, reclen) < 0 || v_adjvalence(vol, parid, 1, 1) < 0) return -1; return 0; }
/* * NAME: file->addextent() * DESCRIPTION: add an extent to a file */ int f_addextent(hfsfile *file, ExtDescriptor *blocks) { hfsvol *vol = file->vol; ExtDataRec *extrec; ULongInt *pylen; unsigned int start, end; node n; int i; f_getptrs(file, &extrec, 0, &pylen); 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) ERROR(EIO, "file extents exceed file physical length"); else if (num == 0) ERROR(EIO, "empty file extent"); } if (start == end) break; if (v_extsearch(file, start, &file->ext, &n) <= 0) goto fail; 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; byte record[HFS_MAX_EXTRECLEN]; unsigned 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_packextrec(&key, &file->ext, record, &reclen); if (bt_insert(&vol->ext, record, reclen) == -1) goto fail; 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) == -1) goto fail; } else memcpy(extrec, &file->ext, sizeof(ExtDataRec)); } *pylen += blocks->xdrNumABlks * vol->mdb.drAlBlkSiz; file->flags |= HFS_FILE_UPDATE_CATREC; return 0; fail: return -1; }
/* * NAME: hfs->create() * DESCRIPTION: create a new file */ int hfs_create(hfsvol *vol, char *path, char *type, char *creator) { CatKeyRec key; CatDataRec data; long id, parid; char name[HFS_MAX_FLEN + 1]; unsigned char record[HFS_CATRECMAXLEN]; int found, i, reclen; if (v_getvol(&vol) < 0) return -1; found = v_resolve(&vol, path, &data, &parid, name, 0); if (found < 0 || parid == 0) return -1; else if (found) { ERROR(EEXIST, 0); return -1; } if (parid == HFS_CNID_ROOTPAR) { ERROR(EINVAL, 0); return -1; } if (vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } /* create file `name' in parent `parid' */ if (bt_space(&vol->cat, 1) < 0) return -1; id = vol->mdb.drNxtCNID++; vol->flags |= HFS_UPDATE_MDB; /* create file record */ data.cdrType = cdrFilRec; data.cdrResrv2 = 0; data.u.fil.filFlags = 0; data.u.fil.filTyp = 0; memset(&data.u.fil.filUsrWds, 0, sizeof(data.u.fil.filUsrWds)); data.u.fil.filUsrWds.fdType = d_getl((unsigned char *) type); data.u.fil.filUsrWds.fdCreator = d_getl((unsigned char *) creator); data.u.fil.filFlNum = id; data.u.fil.filStBlk = 0; data.u.fil.filLgLen = 0; data.u.fil.filPyLen = 0; data.u.fil.filRStBlk = 0; data.u.fil.filRLgLen = 0; data.u.fil.filRPyLen = 0; data.u.fil.filCrDat = d_tomtime(/*time*/(0)); data.u.fil.filMdDat = data.u.fil.filCrDat; data.u.fil.filBkDat = 0; memset(&data.u.fil.filFndrInfo, 0, sizeof(data.u.fil.filFndrInfo)); data.u.fil.filClpSize = 0; for (i = 0; i < 3; ++i) { data.u.fil.filExtRec[i].xdrStABN = 0; data.u.fil.filExtRec[i].xdrNumABlks = 0; data.u.fil.filRExtRec[i].xdrStABN = 0; data.u.fil.filRExtRec[i].xdrNumABlks = 0; } data.u.fil.filResrv = 0; r_makecatkey(&key, parid, name); r_packcatkey(&key, record, &reclen); r_packcatdata(&data, HFS_RECDATA(record), &reclen); if (bt_insert(&vol->cat, record, reclen) < 0 || v_adjvalence(vol, parid, 0, 1) < 0) return -1; return 0; }