📄 dir40.c
字号:
/* Copyright (C) 2001-2005 by Hans Reiser, licensing governed by reiser4progs/COPYING. dir40.c -- reiser4 directory object plugin. */#ifndef ENABLE_MINIMAL# include <unistd.h>#endif#include "dir40.h"#include "dir40_repair.h"/* Return current position in directory into passed @offset. */static errno_t dir40_telldir(reiser4_object_t *dir, reiser4_key_t *position){ aal_assert("umka-1985", dir != NULL); aal_assert("umka-1986", position != NULL); /* Getting current dir key and adjust. */ aal_memcpy(position, &dir->position, sizeof(*position));#ifndef ENABLE_MINIMAL /* Adjust is offset inside collided keys arrays and needed for positioning right in such a case. In normal case it is zero. */ position->adjust = dir->position.adjust;#endif return 0;}/* Positioning inside directory by passed @position key. Normally, user should use key got from telldir() function. But, this is possible to generate directory key by himself and pass here. */static errno_t dir40_seekdir(reiser4_object_t *dir, reiser4_key_t *position){ aal_assert("umka-1983", dir != NULL); aal_assert("umka-1984", position != NULL); /* Set directory position to the given one. */ aal_memcpy(&dir->position, position, sizeof(*position)); return 0;}/* Resets current direntry position to zero. */errno_t dir40_reset(reiser4_object_t *dir) { aal_assert("umka-864", dir != NULL); /* Preparing key of the first entry in directory and set directory adjust to zero. */#ifndef ENABLE_MINIMAL dir->position.adjust = 0;#endif /* Building key itself. */ plugcall(dir->info.object.plug, build_hashed, &dir->position, reiser4_pshash(dir), reiser4_psfibre(dir), objcall(&dir->info.object, get_locality), objcall(&dir->info.object, get_objectid), "."); return 0;}/* Fetches current unit to passed @entry */errno_t dir40_fetch(reiser4_object_t *dir, entry_hint_t *entry) { trans_hint_t hint; aal_memset(&hint, 0, sizeof(hint)); hint.count = 1; hint.specific = entry; hint.shift_flags = SF_DEFAULT; /* Reading entry to passed @entry */ if (objcall(&dir->body, object->fetch_units, &hint) != 1) return -EIO; /* Copying entry place. */ aal_memcpy(&entry->place, &dir->body, sizeof(reiser4_place_t)); return 0;}#ifndef ENABLE_MINIMALstatic void dir40_entry_type(entry_hint_t *entry) { entry->type = ET_NAME; if (aal_strlen(entry->name) == 1 && !aal_strncmp(entry->name, ".", 1)) { entry->type = ET_SPCL; } if (aal_strlen(entry->name) == 2 && !aal_strncmp(entry->name, "..",2)) { entry->type = ET_SPCL; }}#else#define dir40_entry_type(entry) do{;} while(0)#endiferrno_t dir40_entry_comp(reiser4_object_t *dir, void *data) { entry_hint_t entry; reiser4_key_t *key; aal_assert("vpf-1834", dir != NULL); if (!dir->body.plug) return -EINVAL;#ifndef EINVAL if (dir->body.plug->id.group != DIR_ITEM) return -ESTRUCT;#endif if (dir40_fetch(dir, &entry)) return -EIO; if (!data) { key = &dir->position; } else { key = (reiser4_key_t *)data; } /* If greater key is reached, return PRESENT. */ return objcall(&entry.offset, compfull, key) ? 1 : 0;}/* Reads one current directory entry to passed @entry hint. Returns count of read entries, zero for the case directory is over and nagtive values fopr errors. */static int32_t dir40_readdir(reiser4_object_t *dir, entry_hint_t *entry){ uint32_t units; errno_t res; aal_assert("umka-845", entry != NULL); aal_assert("umka-844", dir != NULL); /* Getting place of current unit */ if ((res = obj40_update_body(dir, dir40_entry_comp)) != PRESENT) return res == ABSENT ? 0 : res; /* Reading next entry */ if ((res = dir40_fetch(dir, entry))) return res; /* Setting up the entry type. It is essential for fsck to know what is the NAME -- that needs to be traversed semantically to be recovered completely -- and what is not -- that needs some other special actions, e.g. check_attach for ".." (and even "..." if it is needed one day), etc. */ dir40_entry_type(entry); units = objcall(&dir->body, balance->units); /* Getting next entry in odrer to set up @dir->position correctly. */ if (++dir->body.pos.unit >= units) { /* Switching to the next directory item */ if ((res = obj40_next_item(dir)) < 0) return res; if (res == ABSENT) { uint64_t offset; /* Set offset to non-existent value. */ offset = objcall(&dir->position, get_offset); objcall(&dir->position, set_offset, offset + 1); } } else { /* There is no need to switch */ res = 1; } if (res == 1) { entry_hint_t temp; if ((res = dir40_fetch(dir, &temp))) return res;#ifndef ENABLE_MINIMAL /* Taking care about adjust */ if (!objcall(&temp.offset, compfull, &dir->position)) temp.offset.adjust = dir->position.adjust + 1; else temp.offset.adjust = 0;#endif dir40_seekdir(dir, &temp.offset); } return 1;}/* Makes lookup inside directory. This is needed to be used in add_entry() for two reasons: for make sure, that passed entry does not exists and to use lookup result for consequent insert. */static lookup_t dir40_search(reiser4_object_t *dir, char *name, lookup_bias_t bias, entry_hint_t *entry){ lookup_t res;#ifndef ENABLE_MINIMAL coll_hint_t hint; coll_func_t func;#endif aal_assert("umka-1118", name != NULL); aal_assert("umka-1117", dir != NULL); /* Preparing key to be used for lookup. It is generating from the directory oid, locality and name by menas of using hash plugin. */ plugcall(dir->info.object.plug, build_hashed, &dir->body.key, reiser4_pshash(dir), reiser4_psfibre(dir), objcall(&dir->info.object, get_locality), objcall(&dir->info.object, get_objectid), name);#ifndef ENABLE_MINIMAL hint.specific = name; hint.type = DIR_ITEM; func = obj40_core->tree_ops.collision;#endif if ((res = obj40_find_item(dir, &dir->body.key, bias, #ifndef ENABLE_MINIMAL func, &hint,#else NULL, NULL,#endif &dir->body)) < 0) { return res; } if (entry) { aal_memset(entry, 0, sizeof(*entry)); aal_memcpy(&entry->place, &dir->body, sizeof(reiser4_place_t)); aal_memcpy(&entry->offset, &dir->body.key, sizeof(reiser4_key_t)); if (res == PRESENT) { if (dir40_fetch(dir, entry)) return -EIO; dir40_entry_type(entry); } } return res;}/* Makes lookup inside @dir by passed @name. Saves found entry in passed @entry hint. */lookup_t dir40_lookup(reiser4_object_t *dir, char *name, entry_hint_t *entry) { return dir40_search(dir, name, FIND_EXACT, entry);}#ifndef ENABLE_MINIMAL/* Creates dir40 instance. Creates its stat data item, and body item with one "." unit. Yet another unit ".." will be inserted latter, then directiry will be attached to a parent object. */static errno_t dir40_create(reiser4_object_t *dir, object_hint_t *hint) { trans_hint_t body_hint; entry_hint_t entry; reiser4_key_t *key; uint32_t mode; errno_t res; aal_assert("vpf-1816", dir != NULL); aal_assert("vpf-1095", dir->info.tree != NULL); aal_memset(&body_hint, 0, sizeof(body_hint)); /* Initializing direntry item hint. This should be done before the stat data item hint, because we will need size of direntry item during stat data initialization. */ body_hint.count = 1; body_hint.plug = reiser4_psdiren(dir); key = &dir->info.object; plugcall(key->plug, build_hashed, &body_hint.offset, reiser4_pshash(dir), reiser4_psfibre(dir), objcall(&dir->info.object, get_locality), objcall(&dir->info.object, get_objectid), "."); /* Preparing hint for the empty directory. It consists only "." for unlinked directories. */ aal_strncpy(entry.name, ".", 1); /* Initializing entry stat data key. */ aal_memcpy(&entry.object, key, sizeof(*key)); /* Initializing entry hash key. */ aal_memcpy(&entry.offset, &body_hint.offset, sizeof(entry.offset)); body_hint.specific = &entry; body_hint.shift_flags = SF_DEFAULT; dir40_reset(dir); /* Looking for place to insert directory body */ switch (obj40_find_item(dir, &body_hint.offset, FIND_CONV, NULL, NULL, &dir->body)) { case ABSENT: /* Inserting the direntry body item into the tree. */ if ((res = obj40_insert(dir, &dir->body, &body_hint, LEAF_LEVEL)) < 0) { return res; } break; default: return -EIO; } mode = (hint ? hint->mode : 0) | S_IFDIR | 0755; /* Create stat data item. */ if ((res = obj40_create_stat(dir, 1, body_hint.len, 0, 1, mode, NULL)))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -