⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 core.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -