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_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_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 errval_t write_file(struct dirent *root, const char *path, uint8_t *data, size_t len) { errval_t err; assert(path != NULL); assert(root != NULL); // walk path, creating/locating directories as we go struct dirent *d = root; while (true) { // remove any leading / while (path[0] == '/') { path++; } char *nextsep = strchr(path, '/'); // no more /, we have the filename if (nextsep == NULL) { break; } // extract dirname, advance path size_t namelen = nextsep - path; char *dirname = malloc(namelen + 1); assert(dirname != NULL); memcpy(dirname, path, namelen); dirname[namelen] = '\0'; path += namelen; // does this directory exist? struct dirent *next; err = ramfs_lookup(d, dirname, &next); if (err_is_ok(err)) { free(dirname); d = next; continue; } else if (err_no(err) != FS_ERR_NOTFOUND) { free(dirname); return err; } // create the directory err = ramfs_mkdir(d, dirname, &next); if (err_is_fail(err)) { free(dirname); return err; } d = next; } // create the file! struct dirent *f; char *path_copy = strdup(path); assert(path_copy != NULL); err = ramfs_create(d, path_copy, &f); if (err_is_fail(err)) { free(path_copy); return err; } // allocate storage uint8_t *buf; err = ramfs_grow(f, 0, len, &buf); if (err_is_fail(err)) { ramfs_delete(f); return err; } // copy the payload memcpy(buf, data, len); return SYS_ERR_OK; }