예제 #1
0
static int
ramfs_unlink(vnode_t *dir, const char *name, size_t namelen)
{
        vnode_t *vn;
        int ret;
        off_t i;
        ramfs_dirent_t *entry;

        ret = ramfs_lookup(dir, name, namelen, &vn);
        KASSERT(0 == ret);
        KASSERT(!S_ISDIR(vn->vn_mode));

        /* And then remove the entry from the directory */
        entry = VNODE_TO_DIRENT(dir);
        for (i = 0; i < RAMFS_MAX_DIRENT; i++, entry++) {
                if (name_match(entry->rd_name, name, namelen)) {
                        entry->rd_name[0] = '\0';
                        break;
                }
        }

        VNODE_TO_RAMFSINODE(dir)->rf_size -= sizeof(ramfs_dirent_t);

        VNODE_TO_RAMFSINODE(vn)->rf_linkcount--;
        vput(vn);

        return 0;
}
예제 #2
0
static int
ramfs_link(vnode_t *oldvnode, vnode_t *dir,
           const char *name, size_t name_len)
{
        vnode_t *vn;
        off_t i;
        ramfs_dirent_t *entry;

        KASSERT(oldvnode->vn_fs == dir->vn_fs);
        KASSERT(0 != ramfs_lookup(dir, name, name_len, &vn));

        /* Look for space in the directory */
        entry = VNODE_TO_DIRENT(dir);
        for (i = 0; i < RAMFS_MAX_DIRENT; i++, entry++) {
                if (!entry->rd_name[0])
                        break;
        }

        if (i == RAMFS_MAX_DIRENT) {
                return -ENOSPC;
        }

        /* Set entry in parent */
        entry->rd_ino = oldvnode->vn_vno;
        strncpy(entry->rd_name, name, MIN(name_len, NAME_LEN - 1));
        entry->rd_name[MIN(name_len, NAME_LEN - 1)] = '\0';

        VNODE_TO_RAMFSINODE(dir)->rf_size += sizeof(ramfs_dirent_t);

        /* Increase linkcount */
        VNODE_TO_RAMFSINODE(oldvnode)->rf_linkcount++;
        return 0;
}
예제 #3
0
static int
ramfs_rmdir(vnode_t *dir, const char *name, size_t name_len)
{
        vnode_t *vn;
        int ret;
        off_t i;
        ramfs_dirent_t *entry;

        KASSERT(!name_match(".", name, name_len) &&
                !name_match("..", name, name_len));

        if ((ret = ramfs_lookup(dir, name, name_len, &vn)) != 0)
                return ret;

        if (!S_ISDIR(vn->vn_mode)) {
                vput(vn);
                return -ENOTDIR;
        }

        /* We have to make sure that this directory is empty */
        entry = VNODE_TO_DIRENT(vn);
        for (i = 0; i < RAMFS_MAX_DIRENT; i++, entry++) {
                if (!strcmp(entry->rd_name, ".") ||
                    !strcmp(entry->rd_name, ".."))
                        continue;

                if (entry->rd_name[0]) {
                        vput(vn);
                        return -ENOTEMPTY;
                }
        }

        /* Finally, remove the entry from the parent directory */
        entry = VNODE_TO_DIRENT(dir);
        for (i = 0; i < RAMFS_MAX_DIRENT; i++, entry++) {
                if (name_match(entry->rd_name, name, name_len)) {
                        entry->rd_name[0] = '\0';
                        break;
                }
        }
        VNODE_TO_RAMFSINODE(dir)->rf_size -= sizeof(ramfs_dirent_t);

        VNODE_TO_RAMFSINODE(vn)->rf_linkcount--;
        vput(vn);

        return 0;
}
예제 #4
0
static int
ramfs_read(vnode_t *file, off_t offset, void *buf, size_t count)
{
        int ret;
        ramfs_inode_t *inode = VNODE_TO_RAMFSINODE(file);

        KASSERT(!S_ISDIR(file->vn_mode));

        ret = MAX(0, MIN((off_t)count, inode->rf_size - offset));
        memcpy(buf, inode->rf_mem + offset, ret);

        return ret;
}
예제 #5
0
static int
ramfs_lookup(vnode_t *dir, const char *name, size_t namelen, vnode_t **result)
{
        off_t i;
        ramfs_inode_t *inode = VNODE_TO_RAMFSINODE(dir);
        ramfs_dirent_t *entry = (ramfs_dirent_t *)inode->rf_mem;

        for (i = 0; i < RAMFS_MAX_DIRENT; i++, entry++) {
                if (name_match(entry->rd_name, name, namelen)) {
                        *result = vget(dir->vn_fs, entry->rd_ino);
                        return 0;
                }
        }

        return -ENOENT;
}
예제 #6
0
파일: ramfs.c 프로젝트: dan-boa/kernel2
static int
ramfs_mkdir(vnode_t *dir, const char *name, size_t name_len)
{
        vnode_t *vn;
        off_t i;
        ramfs_dirent_t *entry;
	
	 dbg(DBG_INIT,"RAMFS_MKDIR before KASSERT %s\n",name);
        KASSERT(0 != ramfs_lookup(dir, name, name_len, &vn));

        /* Look for space in the directory */
        entry = VNODE_TO_DIRENT(dir);
        for (i = 0; i < RAMFS_MAX_DIRENT; i++, entry++) {
                if (!entry->rd_name[0])
                        break;
        }

        if (i == RAMFS_MAX_DIRENT) {
                return -ENOSPC;
        }

        /* Allocate an inode */
        int ino;
        if (0 > (ino = ramfs_alloc_inode(dir->vn_fs, RAMFS_TYPE_DIR, 0))) {
                return ino;
        }

        /* Set entry in parent */
        entry->rd_ino = ino;
        strncpy(entry->rd_name, name, MIN(name_len, NAME_LEN - 1));
        entry->rd_name[MIN(name_len, NAME_LEN - 1)] = '\0';

        VNODE_TO_RAMFSINODE(dir)->rf_size += sizeof(ramfs_dirent_t);

        /* Set up '.' and '..' in the directory */
        entry = (ramfs_dirent_t *) VNODE_TO_RAMFS(dir)->rfs_inodes[ino]->rf_mem;
        entry->rd_ino = ino;
        strcpy(entry->rd_name, ".");
        entry++;
        entry->rd_ino = dir->vn_vno;
        strcpy(entry->rd_name, "..");

        /* Increase inode size accordingly */
        VNODE_TO_RAMFS(dir)->rfs_inodes[ino]->rf_size = 2 * sizeof(ramfs_dirent_t);

        return 0;
}
예제 #7
0
static int
ramfs_write(vnode_t *file, off_t offset, const void *buf, size_t count)
{
        int ret;
        ramfs_inode_t *inode = VNODE_TO_RAMFSINODE(file);

        KASSERT(!S_ISDIR(file->vn_mode));

        ret = MIN((off_t)count, (off_t)PAGE_SIZE - offset);
        memcpy(inode->rf_mem + offset, buf, ret);

        KASSERT(file->vn_len == inode->rf_size);
        file->vn_len = MAX(file->vn_len, offset + ret);
        inode->rf_size = file->vn_len;

        return ret;
}
예제 #8
0
static int
ramfs_stat(vnode_t *file, struct stat *buf)
{
        ramfs_inode_t *i = VNODE_TO_RAMFSINODE(file);
        memset(buf, 0, sizeof(struct stat));
        buf->st_mode    = file->vn_mode;
        buf->st_ino     = (int) file->vn_vno;
        buf->st_dev     = 0;
        if (file->vn_mode == S_IFCHR || file->vn_mode == S_IFBLK) {
                buf->st_rdev  = (int) i->rf_mem;
        }
        buf->st_nlink   = i->rf_linkcount - 1;
        buf->st_size    = (int) i->rf_size;
        buf->st_blksize = (int) PAGE_SIZE;
        buf->st_blocks  = 1;

        return 0;
}
예제 #9
0
static void
ramfs_delete_vnode(vnode_t *vn)
{
        ramfs_inode_t *inode = VNODE_TO_RAMFSINODE(vn);
        ramfs_t *rfs = VNODE_TO_RAMFS(vn);

        if (0 == --inode->rf_linkcount) {
                KASSERT(rfs->rfs_inodes[vn->vn_vno] == inode);

                rfs->rfs_inodes[vn->vn_vno] = NULL;
                if (inode->rf_mode == RAMFS_TYPE_DATA
                    || inode->rf_mode == RAMFS_TYPE_DIR) {
                        page_free(inode->rf_mem);
                }
                /* otherwise, inode->rf_mem is a devid */

                kfree(inode);
        }
}
예제 #10
0
static int
ramfs_mknod(struct vnode *dir, const char *name, size_t name_len, int mode, devid_t devid)
{
        vnode_t *vn;
        off_t i;
        ramfs_dirent_t *entry;

        KASSERT(0 != ramfs_lookup(dir, name, name_len, &vn));

        /* Look for space in the directory */
        entry = VNODE_TO_DIRENT(dir);
        for (i = 0; i < RAMFS_MAX_DIRENT; i++, entry++) {
                if (!entry->rd_name[0])
                        break;
        }

        if (i == RAMFS_MAX_DIRENT) {
                return -ENOSPC;
        }

        int ino;
        if (S_ISCHR(mode)) {
                if (0 > (ino = ramfs_alloc_inode(dir->vn_fs, RAMFS_TYPE_CHR, devid))) {
                        return ino;
                }
        } else if (S_ISBLK(mode)) {
                if (0 > (ino = ramfs_alloc_inode(dir->vn_fs, RAMFS_TYPE_BLK, devid))) {
                        return ino;
                }
        } else {
                panic("Invalid mode!\n");
        }

        /* Set entry in directory */
        entry->rd_ino = ino;
        strncpy(entry->rd_name, name, MIN(name_len, NAME_LEN - 1));
        entry->rd_name[MIN(name_len, NAME_LEN - 1)] = '\0';

        VNODE_TO_RAMFSINODE(dir)->rf_size += sizeof(ramfs_dirent_t);

        return 0;
}
예제 #11
0
static int
ramfs_create(vnode_t *dir, const char *name, size_t name_len, vnode_t **result)
{
        vnode_t *vn;
        off_t i;
        ramfs_dirent_t *entry;

        KASSERT(0 != ramfs_lookup(dir, name, name_len, &vn));

        /* Look for space in the directory */
        entry = VNODE_TO_DIRENT(dir);
        for (i = 0; i < RAMFS_MAX_DIRENT; i++, entry++) {
                if (!entry->rd_name[0])
                        break;
        }

        if (i == RAMFS_MAX_DIRENT) {
                return -ENOSPC;
        }

        /* Allocate an inode */
        int ino;
        if (0 > (ino = ramfs_alloc_inode(dir->vn_fs, RAMFS_TYPE_DATA, 0))) {
                return ino;
        }

        /* Get a vnode, set entry in directory */
        vn = vget(dir->vn_fs, (ino_t) ino);

        entry->rd_ino = vn->vn_vno;
        strncpy(entry->rd_name, name, MIN(name_len, NAME_LEN - 1));
        entry->rd_name[MIN(name_len, NAME_LEN - 1)] = '\0';

        VNODE_TO_RAMFSINODE(dir)->rf_size += sizeof(ramfs_dirent_t);

        *result = vn;

        return 0;
}
예제 #12
0
static int
ramfs_query_vnode(vnode_t *vn)
{
        return VNODE_TO_RAMFSINODE(vn)->rf_linkcount > 1;
}