📄 core.c
字号:
tw(tr(TR_BEGIN, TrObject, "object_rename(%d, '%s', %d) {\n",
oldi, newname, newdir));
oldip = inode_addr(oldi);
oldsize = segment_datasize(oldip);
// Make sure that there is enough space to make the rename without
// object_create() trigger a data_reclaim() (awoid relocate oldi/data
// source)
namelength = is_filename(newname);
realsize = namelength + 1 + oldsize + (oldsize > 0 ? 1 : 0);
realsize = atomalign(realsize);
// Save newdir in fs.xx because it will be updated if it is relocated.
fs.i_backup = newdir;
if ((offset = data_prealloc(realsize)) <= 0)
return EFFS_NOSPACE;
// Use fs.journal.oldi because i would have been updated if
// data_reclaim() relocate oldi
oldip = inode_addr(fs.journal.oldi);
olddata = offset2addr(location2offset(oldip->location));
olddata = addr2data(olddata, oldip);
newi = object_create(newname, olddata, oldsize, fs.i_backup);
tw(tr(TR_END, TrObject, "} %d\n", newi));
return newi;
}
/******************************************************************************
* Object Lookup
******************************************************************************/
// We can *not* use global variables, only local --- we must be re-entrant!
#if 0
// NEW CODE!
iref_t ffs_object_lookup_do(const char **path, iref_t *dir, int readlink);
iref_t ffs_object_lookup_once(const char *path, char **leaf, iref_t *dir)
{
iref_t i, mydir;
const char *mypath;
tw(tr(TR_BEGIN, TrLookup, "object_lookup_once('%s', ?, ?) {\n", path));
ttw(ttr(TTrInode, "olu(%s){" NL, path));
mypath = path;
mydir = 0;
i = object_lookup_do(&mypath, &mydir, 0);
if (leaf) *leaf = (char *) mypath;
if (dir) *dir = mydir;
tw(tr(TR_END, TrLookup, "} (%d, '%s') %d\n",
(dir ? *dir : 0), (leaf ? *leaf : ""), i));
ttw(ttr(TTrInode, "} %d" NL, i));
return i;
}
// Lookup an object. Symlinks are followed.
iref_t ffs_object_lookup(const char *path, char **leaf, iref_t *dir)
{
iref_t i, mydir;
const char *mypath;
tw(tr(TR_BEGIN, TrLookup, "object_lookup('%s', ?, ?) {\n", path));
ttw(ttr(TTrInode, "olu(%s){" NL, path));
mypath = path;
mydir = 0;
i = object_lookup_do(&mypath, &mydir, 1);
if (is_object(ip, OT_LINK)) {
// If it is a link, we unconditionally follow it
mypath = offset2addr(location2offset(ip->location));
mypath += ffs_strlen(mypath) + 1; // point to data
if (*mypath == '/') {
mypath++;
depth = 0;
d = fs.root;
}
i = d;
ip = inode_addr(d);
}
if (leaf) *leaf = (char *) mypath;
if (dir) *dir = mydir;
tw(tr(TR_END, TrLookup, "} (%d, '%s') %d\n",
(dir ? *dir : 0), (leaf ? *leaf : ""), i));
ttw(ttr(TTrInode, "} %d" NL, i));
return i;
}
// NEW CODE!
// Ignore all occurrences of two successive slashes. Accept trailing slash
// in directory name.
iref_t ffs_object_lookup_do(const char **path, iref_t *dir, int followlink)
{
// int lookup_followed; // number of symlinks followed
iref_t i, j, d;
struct inode_s *ip;
const char *p, *q, *mypath = *path;
uint8 depth = 1;
tw(tr(TR_FUNC, TrLookup, "object_lookup_do('%s', ?, %d) {\n",
*path, followlink));
d = fs.root;
if (*mypath == '/') {
mypath++; // silently ignore and skip prefix slash
// root directory is a special case
if (*mypath == 0) {
j = d;
if (path) *path = mypath;
if (dir) *dir = 0;
tw(tr(TR_NULL, TrLookup, "} ('%s', %d) %d\n", mypath, 0, j));
return j;
}
}
// set default return value if root dir is empty (child link empty)
j = EFFS_NOTFOUND;
ip = inode_addr(d);
tw(tr(TR_FUNC, TrLookup, ""));
while ((i = ip->child) != (iref_t) IREF_NULL)
{
j = 0; // default to not found
do {
tw(tr(TR_NULL, TrLookup, " %d", (int) i));
p = mypath;
ip = inode_addr(i);
if (is_object_valid(ip) && !is_object(ip, OT_SEGMENT)) {
q = addr2name(offset2addr(location2offset(ip->location)));
tw(tr(TR_NULL, TrLookup, ":%s", q));
while (*p == *q && *p != 0 && *q != 0) {
p++;
q++;
}
if (*q == 0 && (*p == 0 || *p == '/')) {
j = i;
break;
}
}
} while ((i = ip->sibling) != (iref_t) IREF_NULL);
if (j == 0) {
// we did not find this component of the mypath. Let's see if this
// was the leafname component or not...
while (*p != 0 && *p != '/')
p++;
if (*p == 0)
// The mypath component was indeed the leafname
j = EFFS_NOTFOUND;
else
// The path component was not the last, so it obviously
// contained an object that was not a directory.
j = EFFS_NOTADIR;
break;
}
if (*p == '/') {
// if there are more path components, the object found must be a
// directory or a symlink...
if (is_object(ip, OT_LINK)) {
// If it is a link, we unconditionally follow it
mypath = offset2addr(location2offset(ip->location));
mypath += ffs_strlen(mypath) + 1; // point to data
if (*mypath == '/') {
mypath++;
depth = 0;
d = fs.root;
}
i = d;
ip = inode_addr(d);
}
else if (is_object(ip, OT_DIR)) {
mypath = p + 1;
d = i;
}
else {
j = EFFS_NOTADIR;
break;
}
if (++depth > fs.path_depth_max) {
j = EFFS_PATHTOODEEP;
break;
}
// if this dir inode has no children, we will leave the while
// loop, so we preset the return error code. NOTEME: Not
// strictly correct because if we still have a lot of the
// pathname left, it should return the error EFFS_NOTADIR
j = EFFS_NOTFOUND;
tw(tr(TR_NULL, TrLookup, " /"));
}
else {
// It is a fact that *p == 0. So we found the object
if (is_object(ip, OT_LINK) && followlink) {
// If object is a link, we conditionally follow it...
mypath = offset2addr(location2offset(ip->location));
mypath += ffs_strlen(mypath) + 1; // point to data
if (*mypath == '/') {
mypath++;
depth = 0;
d = fs.root;
i = fs.root;
}
else
i = d;
ip = inode_addr(d);
tw(tr(TR_NULL, TrLookup, " -%d->", d));
}
else {
break; // Success, we found the object!
}
}
}
if (path) *path = (char *) mypath;
if (dir) *dir = d;
tw(tr(TR_NULL, TrLookup, "} (%d, '%s') %d\n", d, mypath, j));
return j;
}
#else
// Lookup an object. Symlinks are followed.
iref_t object_lookup(const char *path, char **leaf, iref_t *dir)
{
iref_t i;
struct inode_s *ip;
tw(tr(TR_BEGIN, TrLookup, "object_lookup('%s', ?, ?) {\n", path));
ttw(ttr(TTrInode, "olu(%s){" NL, path));
i = object_lookup_once(path, leaf, dir);
ip = inode_addr(i);
if (i > 0 && is_object(ip, OT_LINK)) {
path = offset2addr(location2offset(ip->location));
path += ffs_strlen(path) + 1; // point to data portion
i = object_lookup_once(path, leaf, dir);
// Links may only point to regular files...
ip = inode_addr(i);
if (+i > 0 && !is_object(ip, OT_FILE))
i = EFFS_NOTAFILE;
}
else {
leaf = 0;
dir = 0;
}
tw(tr(TR_END, TrLookup, "} (%d, '%s') %d\n",
(dir ? *dir : 0), (leaf ? *leaf : ""), i));
ttw(ttr(TTrInode, "} %d" NL, i));
return i;
}
// Lookup an object. If object is found: Return iref of object and
// directory of object in <dir>. If object is not found: Return
// EFFS_NOTFOUND and last directory component of path in <dir> and leafname
// of pathname in <leaf>
iref_t object_lookup_once(const char *path, char **leaf, iref_t *dir)
{
iref_t i, j, d;
struct inode_s *ip;
const char *p, *q;
uint8 depth = 1;
tw(tr(TR_FUNC, TrLookup, "object_lookup_once('%s', ?, ?) { ", path));
if (path == NULL)
return EFFS_BADNAME;
d = fs.root;
if (*path == '/') {
path++; // silently ignore and skip prefix slash
// root directory is a special case
if (*path == 0) {
j = d;
if (leaf) *leaf = (char *) path;
if (dir) *dir = 0;
tw(tr(TR_NULL, TrLookup, "} ('%s', %d) %d\n", path, 0, j));
return j;
}
}
else
return EFFS_BADNAME;
// set default return value if root dir is completely empty
// (child link empty)
j = EFFS_NOTFOUND;
ip = inode_addr(d);
while ((i = ip->child) != (iref_t) IREF_NULL)
{
j = 0; // default to not found
do {
tw(tr(TR_NULL, TrLookup, "i%d ", (int) i));
p = path;
ip = inode_addr(i);
if (is_object_valid(ip) && !is_object(ip, OT_SEGMENT)) {
q = addr2name(offset2addr(location2offset(ip->location)));
tw(tr(TR_NULL, TrLookup, "%s ", q));
while (*p == *q && *p != 0 && *q != 0) {
p++;
q++;
}
if (*q == 0 && (*p == 0 || *p == '/')) {
j = i;
break;
}
}
} while ((i = ip->sibling) != (iref_t) IREF_NULL);
if (j == 0) {
// we did not find this component of the path. Let's
// see if this was the leafname component or not...
while (*p != 0 && *p != '/')
p++;
if (*p == 0)
// The path component was indeed the leafname
j = EFFS_NOTFOUND;
else
// The path component was not the last, so it
// obviously contained an object that was not a
// directory.
j = EFFS_NOTADIR;
break;
}
if (*p == '/') {
// if there are more path components, the object found
// must be a directory...
if (!is_object(ip, OT_DIR)) {
j = EFFS_NOTADIR;
break;
}
if (++depth > fs.path_depth_max) {
j = EFFS_PATHTOODEEP;
break;
}
path = p + 1;
d = i;
// if this dir inode has no children, we will leave the
// while loop, so we preset the return error code. NOTEME:
// Not strictly correct because if we still have a lot of
// the pathname left, it should return the error
// EFFS_NOTADIR
j = EFFS_NOTFOUND;
tw(tr(TR_NULL, TrLookup, "/ "));
}
else {
// It is a fact that *p == 0. So we found the object!
break;
}
}
if (leaf) *leaf = (char *) path;
if (dir) *dir = d;
tw(tr(TR_NULL, TrLookup, "} (%d, '%s') %d\n", d, path, j));
return j;
}
#endif
/******************************************************************************
* Directory Operations
******************************************************************************/
// Open a directory, returning the iref of the directory's inode.
iref_t dir_open(const char *name)
{
iref_t i;
struct inode_s *ip;
tw(tr(TR_BEGIN, TrDirHigh, "dir_open('%s') {\n", name));
if ((i = object_lookup(name, 0, 0)) < 0) {
tw(tr(TR_END, TrDirHigh, "} %d\n", i));
return i;
}
ip = inode_addr(i);
if (!is_object(ip, OT_DIR))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -