/* 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 file * filesys_open (const char *name) { if (strnlen (name, FULLPATH_MAX_LEN) == 0) return NULL; if (strcmp (".", name) == 0) { block_sector_t cwd = thread_current ()->cwd_sector; struct inode *curr = NULL; curr = inode_open (cwd); struct dir *p; p = dir_open (inode_open (curr->data.parent_dir_sector)); struct dir_entry e; size_t ofs; ASSERT (p != NULL); for (ofs = 0; inode_read_at (p->inode, &e, sizeof e, ofs) == sizeof e; ofs += sizeof e) { if (e.inode_sector == cwd && e.in_use) { return filesys_open (e.name); } } return NULL; } struct inode *crr = NULL; crr = inode_open (thread_current ()->cwd_sector); struct dir *parent_dir = dir_reopen(dir_get_parent_dir (name)); //if (crr->data.is_dir) //parent_dir = dir_open (inode_open (crr->data.parent_dir_sector)); //else if (parent_dir == NULL) return NULL; struct inode *inode = NULL; char leaf_name[NAME_MAX + 1]; if (!dir_get_leaf_name (name, leaf_name) && strnlen(leaf_name, NAME_MAX) == 0) { inode = inode_reopen (dir_get_inode (parent_dir)); dir_close (parent_dir); return file_open (inode); } if (parent_dir != NULL) dir_lookup (parent_dir, leaf_name, &inode); dir_close (parent_dir); return file_open (inode); }
// 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; }
bool dir_get_parent (struct dir *dir, struct inode **inode) { block_sector_t sector = inode_get_parent (dir_get_inode(dir)); *inode = inode_open(sector); return *inode != NULL; }
/* Searches DIR for a file with the given NAME and returns true if one exists, false otherwise. On success, sets *INODE to an inode for the file, otherwise to a null pointer. The caller must close *INODE. */ bool dir_lookup (const struct dir *dir, const char *name, struct inode **inode) { struct dir_entry e; ASSERT (dir != NULL); ASSERT (name != NULL); //we have to stop / lookup in / if( strcmp(name,"/") == 0 && inode_id(dir->inode) == ROOT_DIR_SECTOR) *inode = inode_reopen(dir->inode); else { //lock the directory for the rest of the lookup operation inode_lock(dir->inode); name = getfilename(name); if (lookup (dir, name, &e, NULL)) *inode = inode_open (e.inode_sector); else *inode = NULL; //unlock the dir again inode_unlock(dir->inode); } return *inode != NULL; }
/* 打开编号为inode_no的inode对应的文件,若成功则返回文件描述符,否则返回-1 */ int32_t file_open(uint32_t inode_no, uint8_t flag) { int fd_idx = get_free_slot_in_global(); if (fd_idx == -1) { printk("exceed max open files\n"); return -1; } file_table[fd_idx].fd_inode = inode_open(cur_part, inode_no); file_table[fd_idx].fd_pos = 0; // 每次打开文件,要将fd_pos还原为0,即让文件内的指针指向开头 file_table[fd_idx].fd_flag = flag; bool* write_deny = &file_table[fd_idx].fd_inode->write_deny; if (flag & O_WRONLY || flag & O_RDWR) { // 只要是关于写文件,判断是否有其它进程正写此文件 // 若是读文件,不考虑write_deny /* 以下进入临界区前先关中断 */ enum intr_status old_status = intr_disable(); if (!(*write_deny)) { // 若当前没有其它进程写该文件,将其占用. *write_deny = true; // 置为true,避免多个进程同时写此文件 intr_set_status(old_status); // 恢复中断 } else { // 直接失败返回 intr_set_status(old_status); printk("file can`t be write now, try again later\n"); return -1; } } // 若是读文件或创建文件,不用理会write_deny,保持默认 return pcb_fd_install(fd_idx); }
/* Initializes an inode with LENGTH bytes of data and writes the new inode to sector SECTOR on the file system disk. Returns true if successful. Returns false if memory or disk allocation fails. */ bool inode_create (disk_sector_t sector, off_t length, bool is_dir) { struct inode_disk *disk_inode = NULL; struct inode *inode; bool success = false; ASSERT (length >= 0); /* If this assertion fails, the inode structure is not exactly one sector in size, and you should fix that. */ ASSERT (sizeof *disk_inode == DISK_SECTOR_SIZE); disk_inode = calloc (1, sizeof *disk_inode); if (disk_inode != NULL) { disk_inode->length = 0; disk_inode->sector_count = 0; disk_inode->is_dir = is_dir; disk_inode->parent = dir_get_inode (thread_current ()->dir)->sector; disk_inode->magic = INODE_MAGIC; cache_write (sector, disk_inode, 0, DISK_SECTOR_SIZE); inode = inode_open (sector); success = inode_extend (inode, length); free (disk_inode); } return success; }
/* 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 file * filesys_open (const char *name) { char s[100]; char *save_ptr; // printf("%s \n",name); memcpy(s,name,strlen(name)+1); struct inode *inode = NULL; char *file_name = get_file_name(name); // printf("file name : %s\n",file_name); if( strtok_r(s,"/",&save_ptr) ==NULL&&strlen(name)>0 ) { // printf("aaa\n"); free(file_name); return file_open(inode_open(1)); } if( strcmp(file_name,"")==0 ) return NULL; struct dir *dir = get_directory(name); // printf("sector of dir : %d\n", inode_get_inumber(dir_get_inode(dir))); // printf("lookup start\n"); if (dir != NULL) { // printf("here?\n"); if(strcmp(file_name,".")==0) { // printf("here\n"); inode = dir_get_inode(dir); // printf("ohhhhhh\n"); // dir_close (dir); free(file_name); if(inode_is_removed(inode)) return NULL; else return file_open (inode); } else if( strcmp(file_name,"..")==0) { inode = dir_get_inode(inode); // dir_close (dir); free(file_name); return file_open (inode); } else dir_lookup (dir, file_name, &inode); dir_close (dir); if(inode==NULL) return NULL; free(file_name); return file_open (inode); } else { // printf("here\n"); return NULL; } // if(inode_is_removed(inode)) // return NULL; // return file_open (inode); }
int fs_rmdir(const char *path) { struct inode *dir; struct dirent *dent; uint32_t nblock, i, j; char *blk; int r; if ((r = inode_open(path, &dir)) < 0) return r; if (dir == diskaddr(super->s_root)) return -EPERM; if (!S_ISDIR(dir->i_mode)) return -ENOTDIR; nblock = dir->i_size / BLKSIZE; for (i = 0; i < nblock; i++) { if ((r = inode_get_block(dir, i, &blk)) < 0) return r; dent = (struct dirent *)blk; for (j = 0; j < BLKDIRENTS; ++j) if (dent[j].d_name[0] != '\0') return -ENOTEMPTY; } return inode_unlink(path); }
bool dir_lookup (const struct dir *directory, struct inode **inode, const char *file) { struct dir_entry directory_element; size_t offset; ASSERT(directory != NULL); ASSERT(file != NULL); acquire_inode_lock (directory->inode); for (offset = 0; inode_read_at (directory->inode, &directory_element, sizeof directory_element, offset) == sizeof directory_element; offset += sizeof directory_element) if (directory_element.in_use && !strcmp (file, directory_element.name)) { *inode = inode_open (directory_element.inode_sector); release_inode_lock (directory->inode); return *inode != NULL; } *inode = NULL; release_inode_lock (directory->inode); return *inode != NULL; }
/* 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; } }
// 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; }
/* 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; }
/* 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 file * filesys_open (const char *name) { struct inode *inode = NULL; /* Null file name not allowed. */ if (name[0] == '\0') { return NULL; } /* Root directory is special case. */ if (!strcmp (name, "/")) { return (struct file *) dir_open (inode_open (ROOT_DIR_SECTOR)); } /* Lookup file name and get its inode. */ if (!(recursive_dir_lookup (name, &inode))) { return NULL; } /* Check if it is file or directory and open accordingly. */ if (get_is_file (name)) { return file_open (inode); } else { return (struct file *) dir_open (inode); } }
/* Searches DIR for a file with the given NAME and returns true if one exists, false otherwise. On success, sets *INODE to an inode for the file, otherwise to a null pointer. The caller must close *INODE. */ bool dir_lookup (const struct dir *dir, const char *name, struct inode **inode) { struct dir_entry e; ASSERT (dir != NULL); if (name == NULL) *inode = inode_open (inode_get_inumber (dir->inode)); else if (lookup (dir, name, &e, NULL)) *inode = inode_open (e.inode_sector); else *inode = NULL; return *inode != NULL; }
/* 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; }
/* Deletes NAME from 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_acquire (&dir->l); /* 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 directory, make sure it's empty */ if (inode_is_directory (inode)) { struct dir *inner = dir_open (inode_open (e.inode_sector)); int size = dir_size (inner); dir_close (inner); if (size != 0) 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. */ success = inode_remove (inode); done: lock_release (&dir->l); inode_close (inode); return success; }
bool filesys_chdir(const char *name) { bool success=false; struct inode *inode = NULL; struct thread *t = thread_current(); char *file_name = get_file_name(name); struct dir *dir = get_directory(name); // printf("lookup start\n"); if (dir != NULL) { if( strcmp(file_name,".")==0) { t->curr_dir = dir_reopen(dir); free(file_name); return true; } else if(strcmp(file_name,"..")==0) { if( inode_get_inumber(dir_get_inode(dir))==1 ) { t->curr_dir = dir_open(inode_open(1)); free(file_name); dir_close(dir); return true; } else { t->curr_dir = dir_open( inode_open(inode_get_parent(dir_get_inode(dir)))); free(file_name); dir_close(dir); return true; } } success=dir_lookup (dir, file_name, &inode); } dir_close (dir); if(success) { t->curr_dir = dir_open(inode); } free(file_name); /* printf("changed dir sector: %d\n",inode_get_inumber(dir_get_inode(t->curr_dir))); printf("value %d\n",inode_get_data(dir_get_inode(t->curr_dir),0));*/ return success; }
/* Opens the free map file and reads it from disk. */ void free_map_open (void) { free_map_file = file_open (inode_open (FREE_MAP_SECTOR)); if (free_map_file == NULL) PANIC ("can't open free map"); if (!bitmap_read (free_map, free_map_file)) PANIC ("can't read free map"); }
/* Opens the directory for the given path. If the path is null, opens the * CWD */ struct dir * dir_open_path (const char *path) { block_sector_t sector = path_traverse (path, NULL); if (sector == INODE_INVALID_BLOCK_SECTOR) return NULL; struct dir *d = dir_open (inode_open (sector)); if (inode_is_removed (d->inode)) return NULL; return d; }
// 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; }
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; }
/* 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; }
/* 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; }
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; }
/* 回收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); }
/* Searches DIR for a file with the given NAME and returns true if one exists, false otherwise. On success, sets *INODE to an inode for the file, otherwise to a null pointer. The caller must close *INODE. */ bool dir_lookup (const struct dir *dir, const char *name, struct inode **inode) { struct dir_entry e; ASSERT (dir != NULL); ASSERT (name != NULL); if (strcmp(name, ".") == 0) *inode = inode_reopen(dir->inode); else if(strcmp(name, "..") == 0) *inode = inode_open(inode_parent_number(dir->inode)); else if (lookup (dir, name, &e, NULL)) *inode = inode_open (e.inode_sector); else *inode = NULL; return *inode != NULL; }
int fs_truncate(const char *path, off_t size) { struct inode *ino; int r; if ((r = inode_open(path, &ino)) < 0) return r; ino->i_mtime = time(NULL); return inode_set_size(ino, size); }
int fs_open(const char *path, struct fuse_file_info *fi) { struct inode *ino; int r; if ((r = inode_open(path, &ino)) < 0) return r; fi->fh = (uint64_t)ino; return 0; }
int aos_open(const char *path, int flags) { file_t *file; inode_t *node; size_t len = 0; int ret = VFS_SUCCESS; if (path == NULL) { return -EINVAL; } len = strlen(path); if (len > PATH_MAX) { return -ENAMETOOLONG; } if ((ret = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) { return ret; } node = inode_open(path); if (node == NULL) { aos_mutex_unlock(&g_vfs_mutex); return trap_open(path, flags); } node->i_flags = flags; file = new_file(node); aos_mutex_unlock(&g_vfs_mutex); if (file == NULL) { return -ENFILE; } if (INODE_IS_FS(node)) { if ((node->ops.i_fops->open) != NULL) { ret = (node->ops.i_fops->open)(file, path, flags); } } else { if ((node->ops.i_ops->open) != NULL) { ret = (node->ops.i_ops->open)(node, file); } } if (ret != VFS_SUCCESS) { del_file(file); return ret; } return get_fd(file); }
int fs_link(const char *srcpath, const char *dstpath) { struct inode *ino; int r; if ((r = inode_open(srcpath, &ino)) < 0) return r; if (S_ISDIR(ino->i_mode)) return -EPERM; ino->i_ctime = time(NULL); return inode_link(srcpath, dstpath); }