/** * Look up and return the inode for a path name. * If nameiparent is true, return the inode for the parent and copy the final * path element into name, which must have room for DIRSIZ bytes. * Returns 0 in the case of error. */ static struct inode* namex(char *path, bool nameiparent, char *name) { struct inode *ip; struct inode *next; // If path is a full path, get the pointer to the root inode. Otherwise get // the inode corresponding to the current working directory. if(*path == '/'){ ip = inode_get(ROOTDEV, ROOTINO); } else { ip = inode_dup((struct inode*) tcb_get_cwd(get_curid())); } while((path = skipelem(path, name)) != 0){ inode_lock(ip); if(ip -> type != T_DIR) { return 0; } if(nameiparent && *path == 0) { inode_unlock(ip); return ip; } next = dir_lookup(ip, name, 0); inode_unlockput(ip); ip = next; } if(nameiparent){ inode_put(ip); return 0; } return ip; }
/* * Initializes the file system manager. */ PUBLIC void fs_init(void) { binit(); inode_init(); superblock_init(); /* Sanity check. */ CHKSIZE(sizeof(struct d_dirent), sizeof(struct dirent)); rootdev = superblock_read(ROOT_DEV); /* Failed to read root super block. */ if (rootdev == NULL) kpanic("failed to mount root file system"); superblock_unlock(rootdev); root = inode_get(ROOT_DEV, 1); /* Failed to read root inode. */ if (root == NULL) kpanic("failed to read root inode"); kprintf("fs: root file system mounted"); /* Hand craft idle process. */ IDLE->pwd = root; IDLE->root = root; root->count += 2; inode_unlock(root); }
/* * "The l in the name lseek() derives from the fact that the * offset argument and the return value were both originally * typed as long. Early UNIX implementations provided a seek() * system call, which typed these values as int" --M. Kerrisk */ int64_t sys_lseek(int fd, uint64_t offset, uint whence) { struct file *file; struct inode *inode; uint64_t offset_base; int error = 0; file = unrolled_lookup(¤t->fdtable, fd); if (file == NULL) return -EBADF; assert(file->inum > 0); if (is_fifo(file->inum) || is_socket(file->inum)) return -ESPIPE; inode = inode_get(file->inum); spin_lock(&file->lock); switch (whence) { case SEEK_SET: offset_base = 0; break; case SEEK_CUR: offset_base = file->offset; break; case SEEK_END: offset_base = inode->size_low; break; default: error = -EINVAL; goto out; } if ((offset_base + offset) < offset_base) { error = -EOVERFLOW; goto out; } file->offset = offset_base + offset; out: spin_unlock(&file->lock); return error ? error : (int64_t)file->offset; }
/* * -EBADF, -EISDIR, -EFBIG, -ENOSPC */ int64_t sys_write(int fd, void *buf, uint64_t count) { struct file *file; struct inode *inode; int64_t write_len; file = unrolled_lookup(¤t->fdtable, fd); if (file == NULL) return -EBADF; if ((file->flags & O_WRONLY) == 0) return -EBADF; assert(file->inum > 0); if (is_dir(file->inum)) return -EISDIR; if (!is_regular_file(file->inum)) return -EBADF; inode = inode_get(file->inum); spin_lock(&file->lock); write_len = file_write(inode, buf, file->offset, count); if (write_len < 0) goto out; assert(file->offset + write_len <= inode->size_low); file->offset += write_len; out: spin_unlock(&file->lock); return write_len; }
/* * Removes an entry from a directory. */ PUBLIC int dir_remove(struct inode *dinode, const char *filename) { struct buffer *buf; /* Block buffer. */ struct d_dirent *d; /* Directory entry. */ struct inode *file; /* File inode. */ d = dirent_search(dinode, filename, &buf, 0); /* Not found. */ if (d == NULL) return (-ENOENT); /* Cannot remove '.' */ if (d->d_ino == dinode->num) { brelse(buf); return (-EBUSY); } file = inode_get(dinode->dev, d->d_ino); /* Failed to get file's inode. */ if (file == NULL) { brelse(buf); return (-ENOENT); } /* Unlinking directory. */ if (S_ISDIR(file->mode)) { /* Not allowed. */ if (!IS_SUPERUSER(curr_proc)) { inode_put(file); brelse(buf); return (-EPERM); } /* Directory not empty. */ if (dinode->size) { inode_put(file); brelse(buf); return (-EBUSY); } } /* Remove directory entry. */ d->d_ino = INODE_NULL; buf->flags |= BUFFER_DIRTY; inode_touch(dinode); file->nlinks--; inode_touch(file); inode_put(file); brelse(buf); return (0); }
int sys_link(const char *oldpath, const char *newpath) { int64_t inum, parent_inum; const char *child; struct inode *inode; parent_inum = path_parent_child(newpath, &child, OK_DIR); if (parent_inum < 0) return parent_inum; inum = name_i(oldpath); if (inum < 0) return inum; inode = inode_get(inum); return ext2_new_dir_entry(parent_inum, inum, child, inode_mode_to_dir_entry_type(inode->mode)); }
static void fill_statbuf(uint64_t inum, struct stat *buf) { struct inode *inode; assert(inum > 0); assert(buf != NULL); inode = inode_get(inum); memset(buf, 0, sizeof(*buf)); buf->st_ino = inum; buf->st_mode = inode->mode; buf->st_nlink = inode->links_count; buf->st_uid = inode->uid; buf->st_gid = inode->gid_low; buf->st_size = inode->size_low; buf->st_atime = inode->atime; buf->st_mtime = inode->mtime; buf->st_ctime = inode->ctime; }
int op_getattr(const char *path, struct stat *stbuf) { struct ext4_inode raw_inode; struct inode *inode; int ret = 0; uint64_t size; DEBUG("getattr(%s)", path); memset(stbuf, 0, sizeof(struct stat)); ret = inode_get_by_path(path, &raw_inode); if (ret < 0) { return ret; } inode = inode_get(0, &raw_inode); if (!inode) return -ENOMEM; size = inode_get_size(inode); inode_put(inode); DEBUG("getattr done"); stbuf->st_mode = raw_inode.i_mode; stbuf->st_nlink = raw_inode.i_links_count; stbuf->st_size = size; stbuf->st_blocks = raw_inode.i_blocks_lo; stbuf->st_uid = raw_inode.i_uid; stbuf->st_gid = raw_inode.i_gid; stbuf->st_atime = raw_inode.i_atime; stbuf->st_mtime = raw_inode.i_mtime; stbuf->st_ctime = raw_inode.i_ctime; return 0; }
int main(int argc, char *argv[]) { if (argc != 3) { printf("Usage: ext2_mkdir <virtual_disk> <virtual_path>\n"); exit(1); } int fd = open(argv[1], O_RDWR); disk = mmap(NULL, 128 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(disk == MAP_FAILED) { perror("mmap"); exit(1); } struct ext2_inode *parent = inode_get(get_parent_path(argv[2]), disk); if(!parent) { printf("No such path exists\n"); exit(ENOENT); } if(inode_get(argv[2], disk)) { printf("Directory/File with that name already exists\n"); exit(EEXIST); } //get and set inode unsigned int new_inode_num = first_free_inode(disk); add_inode_bitmap(new_inode_num, disk); struct ext2_group_desc *gd = (struct ext2_group_desc *)(disk + (2 * EXT2_BLOCK_SIZE)); struct ext2_inode *inode_table = (struct ext2_inode *)(disk + (gd->bg_inode_table * EXT2_BLOCK_SIZE)); struct ext2_inode *new_inode = &(inode_table[new_inode_num - 1]); new_inode->i_mode = EXT2_S_IFDIR; //give it a block new_inode->i_size = EXT2_BLOCK_SIZE; new_inode->i_links_count = 2; new_inode->i_blocks = 2; unsigned int new_block_num = first_free_block(disk); add_block_bitmap(new_block_num, disk); new_inode->i_block[0] = new_block_num; int i; for(i = 1; i < 15; i++) { new_inode->i_block[i] = 0; } //set first dir_entry to itself struct ext2_dir_entry_2 *new_dir_entry = (struct ext2_dir_entry_2 *)(disk + (new_block_num * EXT2_BLOCK_SIZE)); new_dir_entry->inode = new_inode_num; new_dir_entry->rec_len = sizeof(struct ext2_dir_entry_2) + 4; new_dir_entry->name_len = 1; new_dir_entry->file_type = EXT2_FT_DIR; strncpy(new_dir_entry->name, ".", 1); //set another dir_entry to = parent new_dir_entry = (struct ext2_dir_entry_2 *)((char *)new_dir_entry + new_dir_entry->rec_len); new_dir_entry->inode = ((struct ext2_dir_entry_2 *)(disk + (parent->i_block[0] * EXT2_BLOCK_SIZE)))->inode; new_dir_entry->rec_len = EXT2_BLOCK_SIZE - (sizeof(struct ext2_dir_entry_2) + 4); new_dir_entry->name_len = 2; new_dir_entry->file_type = EXT2_FT_DIR; strncpy(new_dir_entry->name, "..", 2); parent->i_links_count++; //find empty dir_entry in parent and set unsigned int total_size; struct ext2_dir_entry_2 *prev_entry; char *sourceName = &(argv[2][strlen(get_parent_path(argv[2]))]); for(i = 0; i < 12 && parent->i_block[i]; i++) { prev_entry = (struct ext2_dir_entry_2 *)(disk + (parent->i_block[i] * EXT2_BLOCK_SIZE)); total_size = EXT2_BLOCK_SIZE; while(total_size) { int rounding_error = 0; if(strlen(sourceName) % 4) { rounding_error += 4 - (strlen(sourceName) % 4); } if(prev_entry->name_len % 4) { rounding_error += 4 - (prev_entry->name_len % 4); } if(prev_entry->rec_len >= (2 * sizeof(struct ext2_dir_entry_2)) + strlen(sourceName) + prev_entry->name_len + rounding_error) { break; } total_size -= prev_entry->rec_len; prev_entry = (struct ext2_dir_entry_2 *)((char *)prev_entry + prev_entry->rec_len); } if(total_size) { break; } } if(parent->i_block[i]) { unsigned int prev_size = sizeof(struct ext2_dir_entry_2) + prev_entry->name_len; if(prev_entry->name_len % 4) { prev_size += 4 - (prev_entry->name_len % 4); } new_dir_entry = (struct ext2_dir_entry_2 *)((char *)prev_entry + prev_size); new_dir_entry->inode = new_inode_num; new_dir_entry->rec_len = prev_entry->rec_len - prev_size; new_dir_entry->name_len = strlen(sourceName); new_dir_entry->file_type = EXT2_FT_DIR; strncpy(new_dir_entry->name, sourceName, new_dir_entry->name_len); prev_entry->rec_len = prev_size; } else { parent->i_block[i] = first_free_block(disk); add_block_bitmap(parent->i_block[i], disk); new_dir_entry = (struct ext2_dir_entry_2 *)(disk + (parent->i_block[i] * EXT2_BLOCK_SIZE)); new_dir_entry->inode = new_inode_num; new_dir_entry->rec_len = EXT2_BLOCK_SIZE; new_dir_entry->name_len = strlen(sourceName); new_dir_entry->file_type = EXT2_FT_DIR; strncpy(new_dir_entry->name, sourceName, new_dir_entry->name_len); parent->i_size += EXT2_BLOCK_SIZE; parent->i_blocks += 2; } return 0; }
int splitUnicodeString(Splitter *self,PyObject *doc) { PyObject *word ; Py_UNICODE *s; int i, inside_word=0, start=0, len; register int value, next_value; s = PyUnicode_AS_UNICODE(doc); // start of unicode string len = PyUnicode_GET_SIZE(doc); for (i=0; i<len; i++,s++) { register Py_UNICODE c; c = *s; if (self->casefolding) *s = Py_UNICODE_TOLOWER(c); value = inode_get(self, c); if (value == MISS ) { // cache miss value = Py_UNICODE_ISALNUM(c) ? IS_ALNUM : IS_TRASH; inode_set(self, c, value); } if (!inside_word) { if (value != IS_TRASH ) { start = i; inside_word = 1; } } else { if (value == IS_SEPARATOR) { register Py_UNICODE next_c = *(s+1); next_value = inode_get(self, next_c); if (next_value == MISS ) { // cache miss next_value = Py_UNICODE_ISALNUM(next_c) ? IS_ALNUM : IS_TRASH; inode_set(self, next_c, next_value); } if (next_value == IS_TRASH) { if (! (i-start<2 && ! self->single_chars)) { word = Py_BuildValue("u#", s-(i-start), min(i-start, self->max_len)); PyList_Append(self->list, word); Py_XDECREF(word); } start = i; inside_word = 0; } } else if (value==IS_TRASH) { if (! (i-start<2 && ! self->single_chars)) { word = Py_BuildValue("u#", s-(i-start), min(i-start, self->max_len)); PyList_Append(self->list, word); Py_XDECREF(word); } start = i; inside_word = 0; } } } if (inside_word) { if (! (i-start<2 && ! self->single_chars)) { word = Py_BuildValue("u#", s-(i-start), min(i-start, self->max_len)); PyList_Append(self->list, word); Py_XDECREF(word); } } return 1; }
int splitString(Splitter *self,PyObject *doc) { PyObject *word ; char *s,*str; int i, inside_word=0, start=0; Py_ssize_t len; register int value, next_value; PyBytes_AsStringAndSize(doc, &str, &len); s = str; for (i=0; i<len; i++,s++) { char c = *s; if (self->casefolding) *s = tolower(c); value = inode_get(self, c); if (value == MISS ) { // cache miss value = isalnum(c) ? IS_ALNUM : IS_TRASH; inode_set(self, c, value); } if (!inside_word) { if (value != IS_TRASH && value != IS_SEPARATOR) { start = i; inside_word = 1; } } else { if (value == IS_SEPARATOR) { char next_c = *(s+1); next_value = inode_get(self, next_c); if (next_value == MISS ) { // cache miss next_value = isalnum(next_c) ? IS_ALNUM : IS_TRASH; inode_set(self, next_c, next_value); } if (next_value == IS_TRASH) { if (! (i-start<2 && ! self->single_chars)) { word = Py_BuildValue("s#", s-(i-start), min(i-start, self->max_len)); PyList_Append(self->list, word); Py_XDECREF(word); } start = i; inside_word = 0; } } else if (value == IS_TRASH) { if (! (i-start<2 && ! self->single_chars)) { word = Py_BuildValue("s#", s-(i-start), min(i-start, self->max_len)); PyList_Append(self->list, word); Py_XDECREF(word); } start = i; inside_word = 0; } } } if (inside_word) { if (! (i-start<2 && ! self->single_chars)) { word = Py_BuildValue("s#", s-(i-start), min(i-start, self->max_len)); PyList_Append(self->list, word); Py_XDECREF(word); } } return 1; }