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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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); } }
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; }
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; }
static int ramfs_query_vnode(vnode_t *vn) { return VNODE_TO_RAMFSINODE(vn)->rf_linkcount > 1; }