Esempio n. 1
0
static int
sfs_create_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name, bool excl, struct inode **node_store) {
    int ret, slot;
    uint32_t ino;
    struct inode *link_node;
    if ((ret = sfs_dirent_search_nolock(sfs, sin, name, &ino, NULL, &slot)) != -E_NOENT) {
        if (ret != 0) {
            return ret;
        }
        if (!excl) {
            if ((ret = sfs_load_inode(sfs, &link_node, ino)) != 0) {
                return ret;
            }
            if (vop_info(link_node, sfs_inode)->din->type == SFS_TYPE_FILE) {
                goto out;
            }
            vop_ref_dec(link_node);
        }
        return -E_EXISTS;
    }
    else {
        if ((ret = sfs_dirent_create_inode(sfs, SFS_TYPE_FILE, &link_node)) != 0) {
            return ret;
        }
        if ((ret = sfs_dirent_link_nolock(sfs, sin, slot, vop_info(link_node, sfs_inode), name)) != 0) {
            vop_ref_dec(link_node);
            return ret;
        }
    }

out:
    *node_store = link_node;
    return 0;
}
Esempio n. 2
0
static int
sfs_namefile(struct inode *node, struct iobuf *iob) {
    struct sfs_disk_entry *entry;
    if (iob->io_resid <= 2 || (entry = kmalloc(sizeof(struct sfs_disk_entry))) == NULL) {
        return -E_NO_MEM;
    }

    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    struct sfs_inode *sin = vop_info(node, sfs_inode);

    int ret;
    uint32_t ino;
    char *ptr = iob->io_base + iob->io_resid;
    size_t alen, resid = iob->io_resid - 2;
    
    vop_ref_inc(node);
    while ((ino = sin->ino) != SFS_BLKN_ROOT) {
        struct inode *parent;
        if ((ret = sfs_load_parent(sfs, sin, &parent)) != 0) {
            goto failed;
        }
        vop_ref_dec(node);
        
        node = parent, sin = vop_info(node, sfs_inode);
        assert(ino != sin->ino && sin->din->type == SFS_TYPE_DIR);

        if ((ret = trylock_sin(sin)) != 0) {
            goto failed;
        }
        ret = sfs_dirent_findino_nolock(sfs, sin, ino, entry);
        unlock_sin(sin);

        if (ret != 0) {
            goto failed;
        }

        if ((alen = strlen(entry->name) + 1) > resid) {
            goto failed_nomem;
        }
        resid -= alen, ptr -= alen;
        memcpy(ptr, entry->name, alen - 1);
        ptr[alen - 1] = '/';
    }
    vop_ref_dec(node);
    alen = iob->io_resid - resid - 2;
    ptr = memmove(iob->io_base + 1, ptr, alen);
    ptr[-1] = '/', ptr[alen] = '\0';
    iobuf_skip(iob, alen);
    kfree(entry);
    return 0;

failed_nomem:
    ret = -E_NO_MEM;
failed:
    vop_ref_dec(node);
    kfree(entry);
    return ret;
}
Esempio n. 3
0
static int
pipe_root_create(struct inode *__node, const char *name, bool excl, struct inode **node_store) {
    assert((name[0] == 'r' || name[0] == 'w') && name[1] == '_');
    int ret = 0;
    bool readonly = (name[0] == 'r');
    name += 2;

    struct inode *node[2];
    struct fs *fs = vop_fs(__node);
    struct pipe_fs *pipe = fsop_info(fs, pipe);

    lock_pipe(pipe);

    lookup_pipe_nolock(pipe, name, &node[0], &node[1]);
    if (!readonly) {
        struct inode *tmp = node[0];
        node[0] = node[1], node[1] = tmp;
    }

    if (node[0] != NULL) {
        if (excl) {
            ret = -E_EXISTS, vop_ref_dec(node[0]);
            goto out;
        }
        *node_store = node[0];
        goto out;
    }
    ret = -E_NO_MEM;

    struct pipe_state *state;
    if (node[1] == NULL) {
        if ((state = pipe_state_create()) == NULL) {
            goto out;
        }
    }
    else {
        state = vop_info(node[1], pipe_inode)->state;
        pipe_state_acquire(state);
    }

    struct inode *new_node;
    if ((new_node = pipe_create_inode(fs, name, state, readonly)) == NULL) {
        pipe_state_release(state);
        goto out;
    }

    list_add(&(pipe->pipe_list), &(vop_info(new_node, pipe_inode)->pipe_link));
    ret = 0, *node_store = new_node;

out:
    unlock_pipe(pipe);

    if (node[1] != NULL) {
        vop_ref_dec(node[1]);
    }
    return ret;
}
Esempio n. 4
0
int
vfs_open(char *path, uint32_t open_flags, struct inode **node_store) {
    bool can_write = 0;
    switch (open_flags & O_ACCMODE) {
    case O_RDONLY:
        break;
    case O_WRONLY:
    case O_RDWR:
        can_write = 1;
        break;
    default:
        return -E_INVAL;
    }

    if (open_flags & O_TRUNC) {
        if (!can_write) {
            return -E_INVAL;
        }
    }

    int ret;
    struct inode *dir, *node;
    if (open_flags & O_CREAT) {
        char *name;
        bool excl = (open_flags & O_EXCL) != 0;
        if ((ret = vfs_lookup_parent(path, &dir, &name)) != 0) {
            return ret;
        }
        ret = vop_create(dir, name, excl, &node);
        vop_ref_dec(dir);
    }
    else {
        ret = vfs_lookup(path, &node);
    }

    if (ret != 0) {
        return ret;
    }
    assert(node != NULL);

    if ((ret = vop_open(node, open_flags)) != 0) {
        vop_ref_dec(node);
        return ret;
    }

    vop_open_inc(node);
    if (open_flags & O_TRUNC) {
        if ((ret = vop_truncate(node, 0)) != 0) {
            vop_open_dec(node);
            vop_ref_dec(node);
            return ret;
        }
    }
    *node_store = node;
    return 0;
}
Esempio n. 5
0
int
sfs_getpath(struct inode *node, char *path, int maxlen){
  int ret, namelen;
  int pos = maxlen - 2;
  uint inum;
  char *ptr = path + maxlen;
  char namebuf[DIRSIZ];
  struct sfs_inode *sin = vop_info(node, sfs_inode);
  vop_ref_inc(node);
  while(1){
    struct inode *parent;
    if((parent = sfs_dirlookup(node, "..", 0)) == 0){
      goto failed;
    }
    inum = sin->inum;
    vop_ref_dec(node);
    if(node == parent){
      vop_ref_dec(node);
      break;
    }
    node = parent;
    sin = vop_info(node, sfs_inode);
    ret = sfs_inumtoname(node, inum, namebuf);
    if(ret != 0){
      goto failed;
    }
    if((namelen = strlen(namebuf) + 1) > pos){
      return -1;
    }
    pos -= namelen;
    ptr -= namelen;
    memcpy(ptr, namebuf, namelen -1);
    ptr[namelen -1] = '/';
  }
  namelen = maxlen - pos - 2;
  ptr = memmove(path + 5, ptr, namelen);
  ptr[-1] = '/';
  ptr[-2] = ':';
  ptr[-3] = 's';
  ptr[-4] = 'f';
  ptr[-5] = 's';
  ptr[namelen] = '\0';
  
  return 0;
failed:
  vop_ref_dec(node);
  return -1;
}
Esempio n. 6
0
static int
sfs_mkdir_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name) {
    int ret, slot;
    if ((ret = sfs_dirent_search_nolock(sfs, sin, name, NULL, NULL, &slot)) != -E_NOENT) {
        return (ret != 0) ? ret : -E_EXISTS;
    }
    struct inode *link_node;
    if ((ret = sfs_dirent_create_inode(sfs, SFS_TYPE_DIR, &link_node)) != 0) {
        return ret;
    }
    struct sfs_inode *lnksin = vop_info(link_node, sfs_inode);
    if ((ret = sfs_dirent_link_nolock(sfs, sin, slot, lnksin, name)) != 0) {
        assert(lnksin->din->nlinks == 0);
        assert(inode_ref_count(link_node) == 1 && inode_open_count(link_node) == 0);
        goto out;
    }

    /* set parent */
    sfs_dirinfo_set_parent(lnksin, sin);

    /* add '.' link to itself */
    sfs_nlinks_inc_nolock(lnksin);

    /* add '..' link to parent */
    sfs_nlinks_inc_nolock(sin);

out:
    vop_ref_dec(link_node);
    return ret;
}
Esempio n. 7
0
static int
pipe_root_lookup(struct inode *__node, char *path, struct inode **node_store) {
    assert((path[0] == 'r' || path[0] == 'w') && path[1] == '_');
    struct inode *node[2];
    struct pipe_fs *pipe = fsop_info(vop_fs(__node), pipe);
    lock_pipe(pipe);
    {
        lookup_pipe_nolock(pipe, path + 2, &node[0], &node[1]);
    }
    unlock_pipe(pipe);

    if (path[0] != 'r') {
        struct inode *tmp = node[0];
        node[0] = node[1], node[1] = tmp;
    }

    if (node[1] != NULL) {
        vop_ref_dec(node[1]);
    }
    if (node[0] == NULL) {
        return -E_NOENT;
    }
    *node_store = node[0];
    return 0;
}
Esempio n. 8
0
// 设置当前的目录
int
vfs_set_curdir(struct inode *dir) {
    int ret = 0;
    lock_cfs();
    struct inode *old_dir;
    if ((old_dir = get_cwd_nolock()) != dir) { // 得到当前的工作目录的inode
        if (dir != NULL) {
            uint32_t type;
            if ((ret = vop_gettype(dir, &type)) != 0) {
                goto out;
            }
            if (!S_ISDIR(type)) {
                ret = -E_NOTDIR;
                goto out;
            }
            vop_ref_inc(dir);
        }
        set_cwd_nolock(dir);
        if (old_dir != NULL) {
            vop_ref_dec(old_dir);
        }
    }
out:
    unlock_cfs();
    return ret;
}
Esempio n. 9
0
/*
 * Get current directory, as a pathname.
 * Use vop_namefile to get the pathname.
 */
int vfs_getcwd(struct iobuf *iob)
{
    int ret;
    struct inode *node;
    if ((ret = vfs_get_curdir(&node)) != 0) {
        return ret;
    }
    /* The current dir must be a directory, and thus it is not a device. */
    assert(node->in_fs != NULL);

    const char *devname = vfs_get_devname(node->in_fs);
    if ((ret =
                iobuf_move(iob, (char *)devname, strlen(devname), 1, NULL)) != 0) {
        goto out;
    }
    char colon = ':';
    if ((ret = iobuf_move(iob, &colon, sizeof(colon), 1, NULL)) != 0) {
        goto out;
    }
    ret = vop_namefile(node, iob);

out:
    vop_ref_dec(node);
    return ret;
}
Esempio n. 10
0
/*
 * Common code to pull the device name, if any, off the front of a
 * path and choose the inode to begin the name lookup relative to.
 */
static int
get_device(char *path, char **subpath, struct inode **node_store) {
    int i, slash = -1, colon = -1;
    /*
     * Locate the first colon or slash.
     */
    for (i = 0; path[i] != '\0'; i ++) {
        if (path[i] == ':') { colon = i; break; }
        if (path[i] == '/') { slash = i; break; }
    }
    if (colon < 0 && slash != 0) {
        /* *
         * No colon before a slash, so no device name specified, and the slash isn't leading
         * or is also absent, so this is a relative path or just a bare filename. Start from
         * the current directory, and use the whole thing as the subpath.
         * */
        *subpath = path;
        return vfs_get_curdir(node_store);
    }
    if (colon > 0) {
        /* device:path - get root of device's filesystem */
        path[colon] = '\0';

        /* device:/path - skip slash, treat as device:path */
        while (path[++ colon] == '/');

        *subpath = path + colon;
        return vfs_get_root(path, node_store);
    }

    /* *
     * we have either /path or :path
     * /path is a path relative to the root of the "boot filesystem"
     * :path is a path relative to the root of the current filesystem
     * */
    int ret;
    if (*path == '/') {
        if ((ret = vfs_get_bootfs(node_store)) != 0) {
            return ret;
        }
    }
    else {
        assert(*path == ':');
        struct inode *node;
        if ((ret = vfs_get_curdir(&node)) != 0) {
            return ret;
        }
        /* The current directory may not be a device, so it must have a fs. */
        assert(node->in_fs != NULL);
        *node_store = fsop_get_root(node->in_fs);
        vop_ref_dec(node);
    }

    /* ///... or :/... */
    while (*(++ path) == '/');
    *subpath = path;
    return 0;
}
Esempio n. 11
0
static int
sfs_lookup(struct inode *node, char *path, struct inode **node_store) {
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    assert(*path != '\0' && *path != '/');
    vop_ref_inc(node);
    do {
        struct sfs_inode *sin = vop_info(node, sfs_inode);
        if (sin->din->type != SFS_TYPE_DIR) {
            vop_ref_dec(node);
            return -E_NOTDIR;
        }

        char *subpath;
  next:
        subpath = sfs_lookup_subpath(path);
        if (strcmp(path, ".") == 0) {
            if ((path = subpath) != NULL) {
                goto next;
            }
            break;
        }

        int ret;
        struct inode *subnode;
        if (strcmp(path, "..") == 0) {
            ret = sfs_load_parent(sfs, sin, &subnode);
        }
        else {
            if (strlen(path) > SFS_MAX_FNAME_LEN) {
                vop_ref_dec(node);
                return -E_TOO_BIG;
            }
            ret = sfs_lookup_once(sfs, sin, path, &subnode, NULL);
        }

        vop_ref_dec(node);
        if (ret != 0) {
            return ret;
        }
        node = subnode, path = subpath;
    } while (path != NULL);
    *node_store = node;
    return 0;
}
Esempio n. 12
0
/*
 * vfs_chdir - Set current directory, as a pathname. Use vfs_lookup to translate
 *             it to a inode.
 */
int
vfs_chdir(char *path) { // 改变当前的路径-
    int ret;
    struct inode *node;
    if ((ret = vfs_lookup(path, &node)) == 0) {
        ret = vfs_set_curdir(node); // 设置当前的目录
        vop_ref_dec(node);
    }
    return ret;
}
Esempio n. 13
0
int
vfs_readlink(char *path, struct iobuf *iob) {
    int ret;
    struct inode *node;
    if ((ret = vfs_lookup(path, &node)) != 0) {
        return ret;
    }
    ret = vop_readlink(node, iob);
    vop_ref_dec(node);
    return ret;
}
Esempio n. 14
0
int
vfs_lookup_parent(char *path, struct inode **node_store, char **endp) {
    int ret;
    struct inode *node;
    if ((ret = get_device(path, &path, &node)) != 0) {
        return ret;
    }
    ret = (*path != '\0') ? vop_lookup_parent(node, path, node_store, endp) : -E_INVAL;
    vop_ref_dec(node);
    return ret;
}
Esempio n. 15
0
/*
 * sfs_lookup - Parse path relative to the passed directory
 *              DIR, and hand back the inode for the file it
 *              refers to.
 */
static int
sfs_lookup(struct inode *node, char *path, struct inode **node_store) {
    struct sfs_fs *sfs = fsop_info(vop_fs(node), sfs);
    assert(*path != '\0' && *path != '/');
    vop_ref_inc(node);
    struct sfs_inode *sin = vop_info(node, sfs_inode);
    if (sin->din->type != SFS_TYPE_DIR) {
        vop_ref_dec(node);
        return -E_NOTDIR;
    }
    struct inode *subnode;
    int ret = sfs_lookup_once(sfs, sin, path, &subnode, NULL);

    vop_ref_dec(node);
    if (ret != 0) {
        return ret;
    }
    *node_store = subnode;
    return 0;
}
Esempio n. 16
0
int pipe_open(struct inode **rnode_store, struct inode **wnode_store)
{
	int ret;
	struct inode *root;
	if ((ret = vfs_get_root("pipe", &root)) != 0) {
		return ret;
	}
	ret = -E_NO_MEM;

	struct pipe_state *state;
	if ((state = pipe_state_create()) == NULL) {
		goto out;
	}

	struct fs *fs = vop_fs(root);
	struct inode *node[2] = { NULL, NULL };
	if ((node[0] = pipe_create_inode(fs, NULL, state, 1)) == NULL) {
		goto failed_cleanup_state;
	}

	pipe_state_acquire(state);
	if ((node[1] = pipe_create_inode(fs, NULL, state, 0)) == NULL) {
		goto failed_cleanup_node0;
	}

	vop_open_inc(node[0]), vop_open_inc(node[1]);

	*rnode_store = node[0];
	*wnode_store = node[1];
	ret = 0;

out:
	vop_ref_dec(root);
	return ret;

failed_cleanup_node0:
	vop_ref_dec(node[0]);
failed_cleanup_state:
	pipe_state_release(state);
	goto out;
}
Esempio n. 17
0
static void
change_bootfs(struct inode *node) {
    struct inode *old;
    lock_bootfs();
    {
        old = bootfs_node, bootfs_node = node;
    }
    unlock_bootfs();
    if (old != NULL) {
        vop_ref_dec(old);
    }
}
Esempio n. 18
0
int
vfs_unlink(char *path) {
    int ret;
    char *name;
    struct inode *dir;
    if ((ret = vfs_lookup_parent(path, &dir, &name)) != 0) {
        return ret;
    }
    ret = vop_unlink(dir, name);
    vop_ref_dec(dir);
    return ret;
}
Esempio n. 19
0
int
vfs_symlink(char *old_path, char *new_path) {
    int ret;
    char *new_name;
    struct inode *new_dir;
    if ((ret = vfs_lookup_parent(new_path, &new_dir, &new_name)) != 0) {
        return ret;
    }
    ret = vop_symlink(new_dir, new_name, old_path);
    vop_ref_dec(new_dir);
    return ret;
}
Esempio n. 20
0
int
vfs_rename(char *old_path, char *new_path) {
    int ret;
    char *old_name, *new_name;
    struct inode *old_dir, *new_dir;
    if ((ret = vfs_lookup_parent(old_path, &old_dir, &old_name)) != 0) {
        return ret;
    }
    if ((ret = vfs_lookup_parent(new_path, &new_dir, &new_name)) != 0) {
        vop_ref_dec(old_dir);
        return ret;
    }

    if (old_dir->in_fs == NULL || old_dir->in_fs != new_dir->in_fs) {
        ret = -E_XDEV;
    }
    else {
        ret = vop_rename(old_dir, old_name, new_dir, new_name);
    }
    vop_ref_dec(old_dir);
    vop_ref_dec(new_dir);
    return ret;
}
Esempio n. 21
0
static int
sfs_rename2_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name, struct sfs_inode *newsin, const char *new_name) {
    uint32_t ino;
    int ret, slot1, slot2;
    if ((ret = sfs_dirent_search_nolock(sfs, sin, name, &ino, &slot1, NULL)) != 0) {
        return ret;
    }
    if ((ret = sfs_dirent_search_nolock(sfs, newsin, new_name, NULL, NULL, &slot2)) != -E_NOENT) {
        return (ret != 0) ? ret : -E_EXISTS;
    }

    struct inode *link_node;
    if ((ret = sfs_load_inode(sfs, &link_node, ino)) != 0) {
        return ret;
    }

    struct sfs_inode *lnksin = vop_info(link_node, sfs_inode);
    if ((ret = sfs_dirent_unlink_nolock(sfs, sin, slot1, lnksin)) != 0) {
        goto out;
    }

    int isdir = (lnksin->din->type == SFS_TYPE_DIR);

    /* remove '..' link from old parent */
    if (isdir) {
        sfs_nlinks_dec_nolock(sin);
    }

    /* if link fails try to recover its old link */
    if ((ret = sfs_dirent_link_nolock(sfs, newsin, slot2, lnksin, new_name)) != 0) {
        if (sfs_dirent_link_nolock_check(sfs, sin, slot1, lnksin, name) == 0) {
            if (isdir) {
                sfs_nlinks_inc_nolock(sin);
            }
        }
        goto out;
    }
    
    if (isdir) {
        /* set '..' link to new directory */
        sfs_nlinks_inc_nolock(newsin);

        /* update parent relationship */
        sfs_dirinfo_set_parent(lnksin, newsin);
    }

out:
    vop_ref_dec(link_node);
    return ret;
}
Esempio n. 22
0
/*
 * vfs_lookup - get the inode according to the path filename
 */
int
vfs_lookup(char *path, struct inode **node_store) {
    int ret;
    struct inode *node;
    if ((ret = get_device(path, &path, &node)) != 0) {
        return ret;
    }
    if (*path != '\0') {
        ret = vop_lookup(node, path, node_store);
        vop_ref_dec(node);
        return ret;
    }
    *node_store = node;
    return 0;
}
Esempio n. 23
0
void
dev_init(void) {
    init_device(null);
    init_device(stdin);
    init_device(stdout);
    init_device(disk0);
    /* for Nand flash */
    init_device(disk1);

    init_device(tty);

	//init_device(ashmem);

// link such as stdout
    int ret;
    char *new_name;
    struct inode *old_node, *new_dir; 
    if ((ret = vfs_lookup("stdout:", &old_node)) != 0) {
	kprintf("erho");
        return;// ret;
    }
    if ((ret = vfs_lookup_parent("/dev", &new_dir, &new_name)) != 0) {
        vop_ref_dec(old_node);
        return;// ret;
    }

//    if (old_node->in_fs == NULL || old_node->in_fs != new_dir->in_fs) {
//        ret = -E_XDEV;
//    }
//    else {
        ret = vop_link(new_dir, new_name, old_node);
	kprintf("odife%d\n", ret);
//    }
    vop_ref_dec(old_node);
    vop_ref_dec(new_dir);
}
Esempio n. 24
0
void
fs_destroy(struct fs_struct *fs_struct) {
    assert(fs_struct != NULL && fs_count(fs_struct) == 0);
    if (fs_struct->pwd != NULL) {
        vop_ref_dec(fs_struct->pwd);
    }
    int i;
    struct file *file = fs_struct->filemap;
    for (i = 0; i < FS_STRUCT_NENTRY; i ++, file ++) {
        if (file->status == FD_OPENED) {
            filemap_close(file);
        }
        assert(file->status == FD_NONE);
    }
    kfree(fs_struct);
}
Esempio n. 25
0
File: fs.c Progetto: lishuhuakai/CS
//Called when a proc exit
void
files_destroy(struct files_struct *filesp) { // 用于销毁文件
//    cprintf("[files_destroy]\n");
    assert(filesp != NULL && files_count(filesp) == 0);
    if (filesp->pwd != NULL) { // 如果当前目录不为空
        vop_ref_dec(filesp->pwd);
    }
    int i;
    struct file *file = filesp->fd_array;
    for (i = 0; i < FILES_STRUCT_NENTRY; i ++, file ++) {
        if (file->status == FD_OPENED) {
            fd_array_close(file); // 关闭每一个文件
        }
        assert(file->status == FD_NONE);
    }
    kfree(filesp);
}
Esempio n. 26
0
static int
sfs_unlink_nolock(struct sfs_fs *sfs, struct sfs_inode *sin, const char *name) {
    int ret, slot;
    uint32_t ino;
    if ((ret = sfs_dirent_search_nolock(sfs, sin, name, &ino, &slot, NULL)) != 0) {
        return ret;
    }
    struct inode *link_node;
    if ((ret = sfs_load_inode(sfs, &link_node, ino)) != 0) {
        return ret;
    }
    struct sfs_inode *lnksin = vop_info(link_node, sfs_inode);
    if (lnksin->din->type != SFS_TYPE_DIR) {
        ret = sfs_dirent_unlink_nolock(sfs, sin, slot, lnksin);
    }
    else {
        if ((ret = trylock_sin(lnksin)) == 0) {
            if (lnksin->din->dirinfo.slots != 0) {
                ret = -E_NOTEMPTY;
            }
            else if ((ret = sfs_dirent_unlink_nolock(sfs, sin, slot, lnksin)) == 0) {
                /* lnksin must be empty, so set SFS_removed bit to invalidate further trylock opts */
                SetSFSInodeRemoved(lnksin);

                /* remove '.' link */
                sfs_nlinks_dec_nolock(lnksin);

                /* remove '..' link */
                sfs_nlinks_dec_nolock(sin);
            }
            unlock_sin(lnksin);
        }
    }
    vop_ref_dec(link_node);
    return ret;
}
Esempio n. 27
0
int
vfs_close(struct inode *node) {
    vop_open_dec(node);
    vop_ref_dec(node);
    return 0;
}