// Deletes a file. // int unlink(const char *path) { int r; struct Inode *dirino, *ino; struct Direntry *de; if ((r = path_walk(path, &dirino, &de, 0)) < 0) goto done; if ((r = inode_open(de->de_inum, &ino)) < 0) goto closedirino; if (ino->i_ftype == FTYPE_DIR) { r = -E_IS_DIR; goto closeino; } // clear directory entry de->de_inum = 0; --ino->i_refcount; bcache_ipc(de, BCREQ_FLUSH); bcache_ipc(ino, BCREQ_FLUSH); r = 0; closeino: inode_close(ino); closedirino: inode_close(dirino); done: return r; }
/* Traverse -- if thread is non-NULL, update the path of the thread */ block_sector_t path_traverse (char *path, struct thread *t) { char *token, *save_ptr; bool found; struct dir dir; struct dir_entry entry; block_sector_t sector; if (path == NULL) return thread_get_cwd (); /* Check if absolute path */ if (path[0] == '/') { sector = free_map_root_sector (); path++; if (t != NULL) thread_clear_dirs (t); } else { sector = thread_get_cwd (); } for (token = strtok_r (path, "/", &save_ptr); token != NULL; token = strtok_r (NULL, "/", &save_ptr)) { /* Open the inode for this directory */ dir.inode = inode_open (sector); dir.pos = 0; if (dir.inode == NULL || !inode_is_directory (dir.inode)) { sector = INODE_INVALID_BLOCK_SECTOR; inode_close (dir.inode); break; } /* Make the thread leave the directory if applicable */ if (t != NULL) thread_leave_dir (t, dir.inode); /* Look up in current directory */ found = lookup (&dir, token, &entry, NULL); if (found) { sector = entry.inode_sector; /* Make thread enter the directory if applicable */ if (t != NULL) thread_enter_dir (t, dir.inode); inode_close (dir.inode); } else { sector = INODE_INVALID_BLOCK_SECTOR; inode_close (dir.inode); break; } } return sector; }
// Walks 'path' down the file system. // Stores the rightmost directory inode in '*dirino_store', // and a pointer to the directory entry in '*de_store'. // For instance, if path == "/a/b/c/hello", // then '*dirino_store' is the inode for "/a/b/c" // and '*de_store' points to the embedded directory entry for "hello". // If 'create != 0', the final directory entry is created if necessary. // A newly created entry will have 'de_inum == 0'. (All real entries have // 'de_inum != 0'.) // On success, '*dirino_store' is locked and must be closed with // inode_close(). // // Returns 0 on success, < 0 on error. // Error codes: See dir_find(). // static int path_walk(const char *path, struct Inode **dirino_store, struct Direntry **de_store, int create) { int r; struct Inode *ino, *next_ino; struct Direntry *de; const char *component; int component_len; *dirino_store = 0; *de_store = 0; if ((r = inode_open(1, &ino)) < 0) return r; while (1) { // Find next path component path = path_next_component(path, &component, &component_len); // Special case: root directory if (component_len == 0) { *dirino_store = ino; *de_store = &super->s_root; return 0; } // Look up directory component // (This is the last path component iff *path == 0.) if ((r = dir_find(ino, component, component_len, &de, create && *path == 0)) < 0) goto fail; // If done, return this direntry if (*path == 0) { *dirino_store = ino; *de_store = de; return 0; } // Otherwise, walk into subdirectory. // Always open the next inode before closing the current one. if ((r = inode_open(de->de_inum, &next_ino)) < 0) goto fail; inode_close(ino); ino = next_ino; } fail: inode_close(ino); return r; }
/* Opens a file for the given INODE, of which it takes ownership, and returns the new file. Returns a null pointer if an allocation fails or if INODE is null. */ struct file * file_open (struct inode *inode) { struct file *file = calloc (1, sizeof *file); if (inode != NULL && file != NULL) { /* Open the directory if possible. */ if (inode->data.is_dir) { struct dir *opened_dir = dir_open (inode); ASSERT (opened_dir != NULL); file->opened_dir = opened_dir; } else { file->opened_dir = NULL; } file->inode = inode; file->pos = 0; file->deny_write = false; return file; } else { inode_close (inode); free (file); return NULL; } }
/*! Closes FILE. */ void file_close(struct file *file) { if (file != NULL) { file_allow_write(file); inode_close(file->inode); free(file); } }
/* Removes any entry for NAME in DIR. Returns true if successful, false on failure, which occurs only if there is no file with the given NAME. */ bool dir_remove (struct dir *dir, const char *name) { struct dir_entry e; struct inode *inode = NULL; bool success = false; off_t ofs; ASSERT (dir != NULL); ASSERT (name != NULL); /* Find directory entry. */ if (!lookup (dir, name, &e, &ofs)) goto done; /* Open inode. */ inode = inode_open (e.inode_sector); if (inode == NULL) goto done; /* Erase directory entry. */ e.in_use = false; if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e) goto done; /* Remove inode. */ inode_remove (inode); success = true; done: inode_close (inode); return success; }
/* Open system call. */ static int sys_open (const char *ufile) { char *kfile = copy_in_string (ufile); struct file_descriptor *fd; int handle = -1; fd = calloc (1, sizeof *fd); if (fd != NULL) { struct inode *inode = filesys_open (kfile); if (inode != NULL) { if (inode_get_type (inode) == FILE_INODE) fd->file = file_open (inode); else fd->dir = dir_open (inode); if (fd->file != NULL || fd->dir != NULL) { struct thread *cur = thread_current (); handle = fd->handle = cur->next_handle++; list_push_front (&cur->fds, &fd->elem); } else { free (fd); inode_close (inode); } } } palloc_free_page (kfile); return handle; }
/* Opens a directory */ struct dir *dir_open (size_t count, struct inode *inode, struct dir *directory_) { struct dir *dir = calloc (1, sizeof *dir); //open root directory if (count == 0) inode = inode_open (ROOT_DIR_SECTOR); //reopen a directory if (count == 1) inode = inode_reopen (directory_->inode); if (dir == NULL && inode == NULL) { inode_close (inode); free (dir); return NULL; } else { dir->pos = 0; dir->inode = inode; return dir; } }
/* Closes the directory and frees it */ void dir_close (struct dir* directory) { if (directory != NULL) { inode_close (directory->inode); free (directory); } }
/* Destroys DIR and frees associated resources. */ void dir_close (struct dir *dir) { if (dir != NULL) { inode_close (dir->inode); free (dir); } }
/* 关闭文件 */ int32_t file_close(struct file* file) { if (file == NULL) { return -1; } file->fd_inode->write_deny = false; inode_close(file->fd_inode); file->fd_inode = NULL; // 使文件结构可用 return 0; }
// Write at most 'n' bytes from 'buf' to 'fd' at the current seek position. // Advance 'fd->f_offset' by the number of bytes written. // // Returns: // The number of bytes successfully written. // < 0 on error. static ssize_t devfile_write(struct Fd *fd, const void *buf, size_t n) { // Use inode_open, inode_close, maybe inode_set_size, and inode_data. // Be careful of block boundaries! // Flush any blocks you change using BCREQ_FLUSH. // // LAB 5: Your code here. int r; size_t orig_offset = fd->fd_offset; struct Inode *ino; if((r = inode_open(fd->fd_file.inum, &ino)) < 0) return r; void *data; size_t n2 = ROUNDUP(fd->fd_offset, PGSIZE) - fd->fd_offset; if (n2 > n) n2 = n; if(n2) { n -= n2; if(fd->fd_offset + n2 > (size_t)ino->i_size && inode_set_size(ino, fd->fd_offset + n2) < 0) goto wrapup; data = inode_data(ino, fd->fd_offset); memcpy(data, buf, n2); fd->fd_offset += n2; bcache_ipc(data, BCREQ_FLUSH); buf = (void *)((char *)buf + n2); } while (n / PGSIZE) { if(fd->fd_offset + PGSIZE > (size_t)ino->i_size && inode_set_size(ino, fd->fd_offset + PGSIZE) < 0) goto wrapup; data = inode_data(ino, fd->fd_offset); memcpy(data, buf, PGSIZE); bcache_ipc(data, BCREQ_FLUSH); n -= PGSIZE; buf = (void *)((char *)buf + PGSIZE); fd->fd_offset += PGSIZE; } if (n > 0) { if(fd->fd_offset + n > (size_t)ino->i_size && inode_set_size(ino, fd->fd_offset + n) < 0) goto wrapup; data = inode_data(ino, fd->fd_offset); memcpy(data, buf, n); bcache_ipc(data, BCREQ_FLUSH); fd->fd_offset += n; } wrapup: inode_close(ino); return fd->fd_offset - orig_offset; }
/* Removes any entry for NAME in DIR. Returns true if successful, false on failure, which occurs only if there is no file with the given NAME. */ bool dir_remove (struct dir *dir, const char *name) { struct dir_entry e; struct inode *inode = NULL; bool success = false; off_t ofs; ASSERT (dir != NULL); ASSERT (name != NULL); //lock the directory for the rest of the lookup operation inode_lock(dir->inode); name = getfilename(name); /* Find directory entry. */ if (!lookup (dir, name, &e, &ofs)) goto done; /* Open inode. */ inode = inode_open (e.inode_sector); if (inode == NULL) goto done; //if it is still open don't allow deletion if(inode_type(inode) == FILE_DIR) { //is file in use? if(inode_opencnt(inode) > 1) goto done; char * temp = (char *)malloc(sizeof(char) * (NAME_MAX + 1) ); struct dir * dirtemp = dir_open(inode); //is dir empty? if (dir_readdir(dirtemp,temp)) { free(temp); dir_close(dirtemp); goto done; } free(temp); dir_close(dirtemp); } /* Erase directory entry. */ e.in_use = false; if (inode_write_at (dir->inode, &e, sizeof e, ofs) != sizeof e) goto done; /* Remove inode. */ inode_remove (inode); success = true; done: //unlock the directory inode_unlock(dir->inode); inode_close (inode); return success; }
struct dir *get_directory(const char *path, bool flag){ if(strlen(path)==0) return NULL; struct dir *curr; char *word, *brkt, *buffer = malloc(strlen(path)+1), *save, *last; struct inode *inode; memcpy(buffer, path, strlen(path)+1); save = buffer; if(buffer[0]=='/'){ curr = dir_open_root(); last = strtok_r(buffer+1, "/", &brkt); } else{ if(thread_current()->dir) curr = dir_reopen(thread_current()->dir); else curr = dir_open_root(); last = strtok_r(buffer, "/", &brkt); } while(1){ word = last; if(word == NULL) break; last = strtok_r(NULL, "/", &brkt); if(last == NULL && flag) break; if(strcmp(word,"")==0); else if(strcmp(word,".")==0); else if(strcmp(word,"..")==0){ inode = inode_open(inode_parent_number(dir_get_inode(curr))); dir_close(curr); curr = dir_open(inode); } else{ inode = NULL; if(dir_lookup(curr, word, &inode)){ dir_close(curr); if(inode_is_dir(inode)) curr = dir_open(inode); else{ inode_close(inode); free(save); return NULL; } } else{ dir_close(curr); free(save); return NULL; } } } free(save); if(inode_removed(curr->inode)) return NULL; return curr; }
bool isdirectory(block_sector_t sector) { bool a; struct inode * inode; ASSERT(sector < 20000); inode = inode_open(sector); a = inode->data.is_dir; inode_close(inode); return a; }
/* Creates a directory with space for ENTRY_CNT entries in the given SECTOR. Returns true if successful, false on failure. */ bool dir_create (disk_sector_t sector, size_t entry_cnt, disk_sector_t parent_sector) { if(!inode_create (sector, entry_cnt * sizeof (struct dir_entry), INODE_MAX_LEVEL, true)) return false; struct inode *inode = inode_open(sector); inode_set_parent(inode, parent_sector); inode_close(inode); return true; }
struct dir* get_containing_dir (const char* path) { char s[strlen(path)+1]; memcpy(s, path, strlen(path)+1); char *save_ptr, *next_token = NULL, *token = strtok_r(s, "/", &save_ptr); struct dir* dir; if (s[0] == 47 || !thread_current ()->cwd) { dir = dir_open_root (); } else { dir = dir_reopen (thread_current()->cwd); } if (token) { next_token = strtok_r (NULL, "/", &save_ptr); } while (next_token != NULL) { if (strcmp(token, ".") != 0) { struct inode *inode; if (strcmp(token, "..") == 0) { if (!dir_get_parent (dir, &inode)) { return NULL; } } else { if (!dir_lookup (dir, token, &inode)) { return NULL; } } if (inode_is_dir (inode)) { dir_close (dir); dir = dir_open (inode); } else { inode_close (inode); } } token = next_token; next_token = strtok_r (NULL, "/", &save_ptr); } return dir; }
/* 回收inode的数据块和inode本身 */ void inode_release(struct partition* part, uint32_t inode_no) { struct inode* inode_to_del = inode_open(part, inode_no); ASSERT(inode_to_del->i_no == inode_no); /* 1 回收inode占用的所有块 */ uint8_t block_idx = 0, block_cnt = 12; uint32_t block_bitmap_idx; uint32_t all_blocks[140] = {0}; //12个直接块+128个间接块 /* a 先将前12个直接块存入all_blocks */ while (block_idx < 12) { all_blocks[block_idx] = inode_to_del->i_sectors[block_idx]; block_idx++; } /* b 如果一级间接块表存在,将其128个间接块读到all_blocks[12~], 并释放一级间接块表所占的扇区 */ if (inode_to_del->i_sectors[12] != 0) { ide_read(part->my_disk, inode_to_del->i_sectors[12], all_blocks + 12, 1); block_cnt = 140; /* 回收一级间接块表占用的扇区 */ block_bitmap_idx = inode_to_del->i_sectors[12] - part->sb->data_start_lba; ASSERT(block_bitmap_idx > 0); bitmap_set(&part->block_bitmap, block_bitmap_idx, 0); bitmap_sync(cur_part, block_bitmap_idx, BLOCK_BITMAP); } /* c inode所有的块地址已经收集到all_blocks中,下面逐个回收 */ block_idx = 0; while (block_idx < block_cnt) { if (all_blocks[block_idx] != 0) { block_bitmap_idx = 0; block_bitmap_idx = all_blocks[block_idx] - part->sb->data_start_lba; ASSERT(block_bitmap_idx > 0); bitmap_set(&part->block_bitmap, block_bitmap_idx, 0); bitmap_sync(cur_part, block_bitmap_idx, BLOCK_BITMAP); } block_idx++; } /*2 回收该inode所占用的inode */ bitmap_set(&part->inode_bitmap, inode_no, 0); bitmap_sync(cur_part, inode_no, INODE_BITMAP); /****** 以下inode_delete是调试用的 ****** * 此函数会在inode_table中将此inode清0, * 但实际上是不需要的,inode分配是由inode位图控制的, * 硬盘上的数据不需要清0,可以直接覆盖*/ void* io_buf = sys_malloc(1024); inode_delete(part, inode_no, io_buf); sys_free(io_buf); /***********************************************/ inode_close(inode_to_del); }
/* Destroys DIR and frees associated resources. */ void dir_close (struct dir *dir) { // lock_acquire(&directory_lock); if (dir != NULL) { inode_close (dir->inode); free (dir); } // lock_release(&directory_lock); }
/* Opens the file with the given NAME. Returns the new file if successful or a null pointer otherwise. Fails if no file named NAME exists, if directory was there, or if an internal memory allocation fails. */ struct file * filesys_open (const char *path) { bool is_directory; struct inode *inode = filesys_open_inode (path, &is_directory); if (inode != NULL && !is_directory) return file_open (inode); else inode_close (inode); return NULL; }
/* 关闭目录 */ void dir_close(struct dir* dir) { /************* 根目录不能关闭 *************** *1 根目录自打开后就不应该关闭,否则还需要再次open_root_dir(); *2 root_dir所在的内存是低端1M之内,并非在堆中,free会出问题 */ if (dir == &root_dir) { /* 不做任何处理直接返回*/ return; } inode_close(dir->inode); sys_free(dir); }
/* Opens the file with the given NAME. Returns the new file if successful or a null pointer otherwise. Fails if no file named NAME exists, or if an internal memory allocation fails. */ struct inode * filesys_open (const char *name) { struct dir *search_dir = get_cwd(name); if (search_dir == NULL) { return NULL; } struct inode *inode = NULL; if (name[0] == '/') { inode = dir_get_inode(search_dir); } char *part = malloc(NAME_MAX + 1); if (part == NULL) { return false; } memset(part, 0, NAME_MAX + 1); int retrieved_next_part; for (retrieved_next_part = get_next_part(part, &name); retrieved_next_part > 0; retrieved_next_part = get_next_part(part, &name)) { if (dir_lookup (search_dir, part, &inode)) { if (!inode_is_dir(inode)) { break; } else { dir_close(search_dir); search_dir = dir_open(inode); if (search_dir == NULL) { free(part); return false; } } } else { inode = NULL; break; } } if (inode != NULL && inode_is_dir(inode) && get_next_part(part, &name) == 0) { inode = inode_reopen(inode); } dir_close(search_dir); if (inode != NULL && get_next_part(part, &name) != 0) { inode_close(inode); inode = NULL; } free(part); return inode; }
// Truncate or extend an open file to 'size' bytes static int devfile_trunc(struct Fd *fd, off_t newsize) { int r; struct Inode *ino; if ((r = inode_open(fd->fd_file.inum, &ino)) < 0) return r; r = inode_set_size(ino, newsize); inode_close(ino); return r; }
/*! Opens a file for the given INODE, of which it takes ownership, and returns the new file. Returns a null pointer if an allocation fails or if INODE is null. */ struct file * file_open(struct inode *inode) { struct file *file = calloc(1, sizeof *file); if (inode != NULL && file != NULL) { file->inode = inode; file->pos = 0; file->deny_write = false; return file; } else { inode_close(inode); free(file); return NULL; } }
static int devfile_stat(struct Fd *fd, struct Stat *stat) { int r; struct Inode *ino; if ((r = inode_open(fd->fd_file.inum, &ino)) < 0) return r; strcpy(stat->st_name, fd->fd_file.open_path); stat_base(ino, stat); inode_close(ino); return 0; }
int istat(inum_t inum, struct Stat *stat) { int r; struct Inode *ino; if ((r = inode_open(inum, &ino)) < 0) return r; strcpy(stat->st_name, "<inode>"); stat_base(ino, stat); inode_close(ino); return 0; }
/* Closes FILE. */ void file_close (struct file *file) { if (file != NULL) { /* Close the directory if possible. */ if (file->inode->data.is_dir) { dir_close (file->opened_dir); } file_allow_write (file); inode_close (file->inode); free (file); } }
/* Opens and returns the directory for the given INODE, of which it takes ownership. Returns a null pointer on failure. */ struct dir * dir_open (struct inode *inode) { struct dir *dir = calloc (1, sizeof *dir); if (inode != NULL && dir != NULL) { dir->inode = inode; dir->pos = 0; return dir; } else { inode_close (inode); free (dir); return NULL; } }
/* Creates a file named NAME with the given INITIAL_SIZE.*/ bool filesys_create (const char *name, off_t initial_size, bool isdir) { if (strlen(name) == 0) return false; block_sector_t inode_sector = 0; struct dir *dir_ = filesys_get_dir(name); char *name_ = filesys_get_name(name); bool success = false; if (strcmp (name_, "") == 0) goto done; success = (dir_ && free_map_allocate (1, &inode_sector) && inode_create (inode_sector, initial_size) && dir_add (dir_, name_, inode_sector, isdir)); struct inode *ninode = NULL; struct dir *ndir = NULL; bool success1 = true; if (success && isdir){ success1 = ((ninode = inode_open (inode_sector)) && (ndir = dir_open (ninode)) && dir_add (ndir, ".", inode_sector, true) && dir_add (ndir, "..",inode_get_inumber (dir_get_inode (dir_)), true)); } if (inode_sector != 0 && !success) free_map_release (inode_sector, 1); if (success && !success1) { success = false; printf("Failure: create dir: %s\n", name); dir_remove (dir_, name_); } done: dir_close (dir_); free(name_); if (!ndir && ninode){ inode_close(ninode); } else if (ndir) { dir_close(ndir); } return success; }
gfarm_error_t process_close_file(struct process *process, struct peer *peer, int fd) { int is_file; struct file_opening *fo; gfarm_error_t e = process_get_file_opening(process, fd, &fo); if (e != GFARM_ERR_NO_ERROR) return (e); is_file = inode_is_file(fo->inode); if (fo->opener != peer) { if (!is_file) /* i.e. is a directory */ return (GFARM_ERR_OPERATION_NOT_PERMITTED); if (fo->u.f.spool_opener != peer) return (GFARM_ERR_OPERATION_NOT_PERMITTED); /* i.e. REOPENed file, and I am a gfsd. */ if (fo->opener != NULL) { /* * a gfsd is closing a REOPENed file, * but the client is still opening it. */ fo->u.f.spool_opener = NULL; fo->u.f.spool_host = NULL; return (GFARM_ERR_NO_ERROR); } } else { if (is_file && fo->u.f.spool_opener != NULL && fo->u.f.spool_opener != peer) { /* * a client is closing a file, * but the gfsd is still opening it. */ fo->opener = NULL; return (GFARM_ERR_NO_ERROR); } } inode_close(fo); file_opening_free(fo, is_file); process->filetab[fd] = NULL; return (GFARM_ERR_NO_ERROR); }