static int sysv_rmdir(struct inode * dir, struct dentry * dentry) { int retval; struct inode * inode; struct buffer_head * bh; struct sysv_dir_entry * de; inode = dentry->d_inode; bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); retval = -ENOENT; if (!bh || de->inode != inode->i_ino) goto end_rmdir; if (!empty_dir(inode)) { retval = -ENOTEMPTY; goto end_rmdir; } if (inode->i_nlink != 2) printk("empty directory has nlink!=2 (%d)\n", inode->i_nlink); de->inode = 0; mark_buffer_dirty(bh); inode->i_nlink=0; dir->i_nlink--; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); mark_inode_dirty(dir); retval = 0; end_rmdir: brelse(bh); return retval; }
int minix_rmdir(register struct inode *dir, char *name, size_t len) { int retval; register struct inode *inode; struct buffer_head *bh; struct minix_dir_entry *de; inode = NULL; bh = minix_find_entry(dir, name, len, &de); retval = -ENOENT; if (!bh) goto end_rmdir; retval = -EPERM; if (!(inode = iget(dir->i_sb, (ino_t) de->inode))) goto end_rmdir; if ((dir->i_mode & S_ISVTX) && !suser() && current->euid != inode->i_uid && current->euid != dir->i_uid) goto end_rmdir; if (inode->i_dev != dir->i_dev) goto end_rmdir; if (inode == dir) /* we may not delete ".", but "../dir" is ok */ goto end_rmdir; if (!S_ISDIR(inode->i_mode)) { retval = -ENOTDIR; goto end_rmdir; } if (!empty_dir(inode)) { retval = -ENOTEMPTY; goto end_rmdir; } if (de->inode != inode->i_ino) { retval = -ENOENT; goto end_rmdir; } if (inode->i_count > 1) { retval = -EBUSY; goto end_rmdir; } if (inode->i_nlink != 2) printk("empty directory has nlink!=2 (%u)\n", inode->i_nlink); de->inode = 0; #ifdef BLOAT_FS dir->i_version = ++event; #endif mark_buffer_dirty(bh, 1); inode->i_nlink = 0; inode->i_dirt = 1; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_nlink--; dir->i_dirt = 1; retval = 0; end_rmdir: iput(dir); iput(inode); unmap_brelse(bh); return retval; }
//handling symlink request void symlink_handler(Msg *msg, int sender_pid) { char oldname[MAXPATHNAMELEN], newname[MAXPATHNAMELEN]; memset(oldname,'\0',MAXPATHNAMELEN); memset(newname,'\0',MAXPATHNAMELEN); CopyFrom(sender_pid,oldname,msg->ptr1,msg->num2+1); CopyFrom(sender_pid,newname,msg->ptr2,msg->num3+1); int dir_len=msg->num3; char *dir_newname=newname+msg->num3; while((*dir_newname)!='/'&&dir_newname!=newname){ dir_len--; dir_newname--; } if((*dir_newname)=='/'){ dir_len++; dir_newname++; } int parent_inum=path_to_inum(newname,dir_len,msg->num1,0); int sym_inum=alloc_inode(INODE_SYMLINK,parent_inum); if(sym_inum<=0){ msg->type=-1; return; } inode_cache *parent_inode=read_inode(parent_inum); inode_cache *sym_inode=read_inode(sym_inum); int sym_bnum=alloc_block(); block_cache *sym_block=read_block(sym_bnum); struct dir_entry *sym_dir_entry=search_dir_entry(parent_inum,dir_newname); if(sym_dir_entry!=NULL){ msg->type=-1; return; } if((sym_dir_entry=empty_dir(msg->num1))==NULL){ msg->type=-1; return; } sym_dir_entry->inum=sym_inum; memcpy(sym_dir_entry->name,dir_newname,msg->num3-dir_len); sym_inode->data.size=msg->num2; sym_inode->data.nlink=1; sym_inode->data.direct[0]=sym_bnum; sym_block->dirty=1; memcpy(sym_block->data,oldname,msg->num2); parent_inode->data.size+=sizeof(struct dir_entry); parent_inode->dirty=1; }
//handling mkdir request void mkdir_handler(Msg *msg, int sender_pid) { char pathname[MAXPATHNAMELEN]; CopyFrom(sender_pid,pathname,msg->ptr1,msg->num1+1); char* dir_name = pathname+msg->num1; int direct_len = msg->num1; while ((*dir_name)!='/' && dir_name!=pathname) { dir_name--; direct_len--; } if ((*dir_name)=='/') { direct_len++; dir_name++; } if (strlen(dir_name)==0) { perror("invalid pathname when creating file!"); msg->type = ERROR; return; } int direct_inum = path_to_inum(pathname,direct_len,msg->num2,0); if (direct_inum<=0) { perror("invalid pathname when creating file!"); msg->type = ERROR; return; } int new_inum = check_dir(direct_inum,dir_name); if (new_inum<0) { perror("invalid pathname when creating file!"); msg->type = ERROR; return; } //exist same file name in the directory else if (new_inum>0) { perror("exist a directory with same name"); msg->type = ERROR; return; } else if (new_inum==0) { new_inum = alloc_inode(INODE_DIRECTORY,direct_inum); struct dir_entry *d = empty_dir(direct_inum); if (d==NULL) { perror("no empty space for new directory"); msg->type = ERROR; return; } d->inum = new_inum; memcpy(d->name,dir_name,strlen(dir_name)); inode_cache *n = read_inode(direct_inum); n->data.nlink++; n->data.size+=sizeof(struct dir_entry); n->dirty = 1; msg->num1 = 0; } }
/* * Empty a local directory */ static void empty_dir(VMG_ const char *dir) { /* open the directory search */ osdirhdl_t dirhdl; if (os_open_dir(dir, &dirhdl)) { err_try { /* keep going until we're out of files */ char fname[OSFNMAX]; while (os_read_dir(dirhdl, fname, sizeof(fname))) { /* get the full path */ char path[OSFNMAX]; os_build_full_path(path, sizeof(path), dir, fname); /* get the mode */ unsigned long fmode; unsigned long fattr; if (osfmode(path, FALSE, &fmode, &fattr)) { /* check whether it's a directory or an ordinary file */ if ((fmode & OSFMODE_DIR) != 0) { /* * directory - skip the special '.' and '..' links, * since they'd get us stuck in a loop */ os_specfile_t st = os_is_special_file(fname); if (st != OS_SPECFILE_SELF && st != OS_SPECFILE_PARENT) { /* recursively empty the directory */ empty_dir(vmg_ path); /* remove this directory */ if (!os_rmdir(path)) err_throw(VMERR_DELETE_FILE); } } else { /* ordinary file - delete it */ if (osfdel(path)) err_throw(VMERR_DELETE_FILE); } } } } err_finally { /* close the directory search handle */ os_close_dir(dirhdl); } err_end; }
int xiafs_rmdir(struct inode * dir, const char * name, int len) { int retval; struct inode * inode; struct buffer_head * bh; struct xiafs_direct * de, * de_pre; inode = NULL; bh = xiafs_find_entry(dir, name, len, &de, &de_pre); retval = -ENOENT; if (!bh) goto end_rmdir; retval = -EPERM; if (!(inode = iget(dir->i_sb, de->d_ino))) goto end_rmdir; if ((dir->i_mode & S_ISVTX) && !fsuser() && current->fsuid != inode->i_uid && current->fsuid != dir->i_uid) goto end_rmdir; if (inode->i_dev != dir->i_dev) goto end_rmdir; if (inode == dir) /* we may not delete ".", but "../dir" is ok */ goto end_rmdir; if (!S_ISDIR(inode->i_mode)) { retval = -ENOTDIR; goto end_rmdir; } if (!empty_dir(inode)) { retval = -ENOTEMPTY; goto end_rmdir; } if (inode->i_count > 1) { retval = -EBUSY; goto end_rmdir; } if (inode->i_nlink != 2) printk("XIA-FS: empty directory has nlink!=2 (%s %d)\n", WHERE_ERR); xiafs_rm_entry(de, de_pre); mark_buffer_dirty(bh, 1); inode->i_nlink=0; inode->i_dirt=1; dir->i_nlink--; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_dirt=1; retval = 0; end_rmdir: iput(dir); iput(inode); brelse(bh); return retval; }
int qnx4_rmdir(struct inode *dir, struct dentry *dentry) { struct buffer_head *bh; struct qnx4_inode_entry *de; struct inode *inode; int retval; int ino; QNX4DEBUG(("qnx4: qnx4_rmdir [%s]\n", dentry->d_name.name)); lock_kernel(); bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name, &de, &ino); if (bh == NULL) { unlock_kernel(); return -ENOENT; } inode = dentry->d_inode; if (inode->i_ino != ino) { retval = -EIO; goto end_rmdir; } #if 0 if (!empty_dir(inode)) { retval = -ENOTEMPTY; goto end_rmdir; } #endif if (inode->i_nlink != 2) { QNX4DEBUG(("empty directory has nlink!=2 (%d)\n", inode->i_nlink)); } QNX4DEBUG(("qnx4: deleting directory\n")); de->di_status = 0; memset(de->di_fname, 0, sizeof de->di_fname); de->di_mode = 0; mark_buffer_dirty(bh); inode->i_nlink = 0; mark_inode_dirty(inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; dir->i_nlink--; mark_inode_dirty(dir); retval = 0; end_rmdir: brelse(bh); unlock_kernel(); return retval; }
int minix_rmdir(struct inode * dir, struct dentry *dentry) { int retval; struct inode * inode; struct buffer_head * bh; struct minix_dir_entry * de; inode = NULL; bh = minix_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de); retval = -ENOENT; if (!bh) goto end_rmdir; inode = dentry->d_inode; if (!empty_dir(inode)) { retval = -ENOTEMPTY; goto end_rmdir; } if (de->inode != inode->i_ino) { retval = -ENOENT; goto end_rmdir; } if (!list_empty(&dentry->d_hash)) { retval = -EBUSY; goto end_rmdir; } if (inode->i_nlink != 2) printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink); de->inode = 0; dir->i_version = ++event; mark_buffer_dirty(bh, 1); inode->i_nlink=0; mark_inode_dirty(inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_nlink--; mark_inode_dirty(dir); d_delete(dentry); retval = 0; end_rmdir: brelse(bh); return retval; }
int affs_rmdir(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; int retval; unsigned long ino; struct buffer_head *bh; pr_debug("AFFS: rmdir(dir=%lu,\"%.*s\")\n",dir->i_ino, (int)dentry->d_name.len,dentry->d_name.name); retval = -ENOENT; if (!(bh = affs_find_entry(dir,dentry,&ino))) goto rmdir_done; /* * Make sure the directory is empty and the dentry isn't busy. */ retval = -ENOTEMPTY; if (!empty_dir(bh,AFFS_I2HSIZE(inode))) goto rmdir_done; retval = -EBUSY; if (!list_empty(&dentry->d_hash)) goto rmdir_done; if ((retval = affs_remove_header(bh,inode)) < 0) goto rmdir_done; inode->i_nlink = retval; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; retval = 0; dir->i_version = ++event; mark_inode_dirty(dir); mark_inode_dirty(inode); d_delete(dentry); rmdir_done: affs_brelse(bh); return retval; }
int mario_rmdir(struct inode *dir, char *name, int len) { int ino, ret = 0; struct inode *inode; down(&dir->i_sem); if (!(ino = mario_find_entry(dir, name, len))) { ret = -ENOENT; goto tail; } inode = iget(dir->i_sb, ino); if (!S_ISDIR(inode->i_mode)) { ret = -ENOTDIR; goto tail; } /* * We can not remove the root directory */ if (inode->i_rdev == MARIO_ROOT) { ret = -EBUSY; goto tail; } if (inode->i_count > 1) { ret = -EBUSY; goto tail; } if (!empty_dir(inode)) { ret = -ENOTEMPTY; goto tail; } mario_del_entry(inode, 1); iput(inode); /* This inode would not be got any more */ tail: up(&dir->i_sem); iput(dir); return ret; }
/* * rename uses retrying to avoid race-conditions: at least they should be minimal. * it tries to allocate all the blocks, then sanity-checks, and if the sanity- * checks fail, it tries to restart itself again. Very practical - no changes * are done until we know everything works ok.. and then all the changes can be * done in one fell swoop when we have claimed all the buffers needed. * * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */ static int do_minix_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir, struct dentry *new_dentry) { struct inode * old_inode, * new_inode; struct buffer_head * old_bh, * new_bh, * dir_bh; struct minix_dir_entry * old_de, * new_de; struct minix_sb_info * info; int retval; info = &old_dir->i_sb->u.minix_sb; goto start_up; try_again: brelse(old_bh); brelse(new_bh); brelse(dir_bh); current->counter = 0; schedule(); start_up: old_inode = new_inode = NULL; old_bh = new_bh = dir_bh = NULL; old_bh = minix_find_entry(old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de); retval = -ENOENT; if (!old_bh) goto end_rename; old_inode = old_dentry->d_inode; retval = -EPERM; new_inode = new_dentry->d_inode; new_bh = minix_find_entry(new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de); if (new_bh) { if (!new_inode) { brelse(new_bh); new_bh = NULL; } } if (new_inode == old_inode) { retval = 0; goto end_rename; } if (S_ISDIR(old_inode->i_mode)) { retval = -EINVAL; if (is_subdir(new_dentry, old_dentry)) goto end_rename; if (new_inode) { /* Prune any children before testing for busy */ if (new_dentry->d_count > 1) shrink_dcache_parent(new_dentry); retval = -EBUSY; if (new_dentry->d_count > 1) retval = -ENOTEMPTY; if (!empty_dir(new_inode)) goto end_rename; retval = -EBUSY; } retval = -EIO; dir_bh = minix_bread(old_inode,0,0); if (!dir_bh) goto end_rename; if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino) goto end_rename; retval = -EMLINK; if (!new_inode && new_dir->i_nlink >= info->s_link_max) goto end_rename; } if (!new_bh) { retval = minix_add_entry(new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_bh, &new_de); if (retval) goto end_rename; } /* sanity checking before doing the rename - avoid races */ if (new_inode && (new_de->inode != new_inode->i_ino)) goto try_again; if (new_de->inode && !new_inode) goto try_again; if (old_de->inode != old_inode->i_ino) goto try_again; /* ok, that's it */ old_de->inode = 0; new_de->inode = old_inode->i_ino; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; mark_inode_dirty(old_dir); old_dir->i_version = ++event; new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME; mark_inode_dirty(new_dir); new_dir->i_version = ++event; if (new_inode) { new_inode->i_nlink--; new_inode->i_ctime = CURRENT_TIME; mark_inode_dirty(new_inode); } mark_buffer_dirty(old_bh, 1); mark_buffer_dirty(new_bh, 1); if (dir_bh) { PARENT_INO(dir_bh->b_data) = new_dir->i_ino; mark_buffer_dirty(dir_bh, 1); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { new_inode->i_nlink--; mark_inode_dirty(new_inode); } else { new_dir->i_nlink++; mark_inode_dirty(new_dir); } } /* Update the dcache */ d_move(old_dentry, new_dentry); retval = 0; end_rename: brelse(dir_bh); brelse(old_bh); brelse(new_bh); return retval; }
/* * rename uses retrying to avoid race-conditions: at least they should be minimal. * it tries to allocate all the blocks, then sanity-checks, and if the sanity- * checks fail, it tries to restart itself again. Very practical - no changes * are done until we know everything works ok.. and then all the changes can be * done in one fell swoop when we have claimed all the buffers needed. * * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */ static int do_sysv_rename(struct inode * old_dir, struct dentry * old_dentry, struct inode * new_dir, struct dentry * new_dentry) { struct inode * old_inode, * new_inode; struct buffer_head * old_bh, * new_bh, * dir_bh; struct sysv_dir_entry * old_de, * new_de; int retval; goto start_up; try_again: brelse(old_bh); brelse(new_bh); brelse(dir_bh); current->counter = 0; schedule(); start_up: old_inode = new_inode = NULL; old_bh = new_bh = dir_bh = NULL; old_bh = sysv_find_entry(old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de); retval = -ENOENT; if (!old_bh) goto end_rename; old_inode = old_dentry->d_inode; /* don't cross mnt-points */ retval = -EPERM; new_inode = new_dentry->d_inode; new_bh = sysv_find_entry(new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de); if (new_bh) { if (!new_inode) { brelse(new_bh); new_bh = NULL; } } if (new_inode == old_inode) { retval = 0; goto end_rename; } if (S_ISDIR(old_inode->i_mode)) { retval = -EINVAL; if (is_subdir(new_dentry, old_dentry)) goto end_rename; if (new_inode) { if (new_dentry->d_count > 1) shrink_dcache_parent(new_dentry); retval = -EBUSY; if (new_dentry->d_count > 1) goto end_rename; retval = -ENOTEMPTY; if (!empty_dir(new_inode)) goto end_rename; } retval = -EIO; dir_bh = sysv_file_bread(old_inode, 0, 0); if (!dir_bh) goto end_rename; if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino) goto end_rename; retval = -EMLINK; if (!new_inode && new_dir->i_nlink >= new_dir->i_sb->sv_link_max) goto end_rename; } if (!new_bh) { retval = sysv_add_entry(new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_bh, &new_de); if (retval) goto end_rename; } /* sanity checking before doing the rename - avoid races */ if (new_inode && (new_de->inode != new_inode->i_ino)) goto try_again; if (new_de->inode && !new_inode) goto try_again; if (old_de->inode != old_inode->i_ino) goto try_again; /* ok, that's it */ old_de->inode = 0; new_de->inode = old_inode->i_ino; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; mark_inode_dirty(old_dir); new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME; mark_inode_dirty(new_dir); if (new_inode) { new_inode->i_nlink--; new_inode->i_ctime = CURRENT_TIME; mark_inode_dirty(new_inode); } mark_buffer_dirty(old_bh, 1); mark_buffer_dirty(new_bh, 1); if (dir_bh) { PARENT_INO(dir_bh->b_data) = new_dir->i_ino; mark_buffer_dirty(dir_bh, 1); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { new_inode->i_nlink--; mark_inode_dirty(new_inode); } else { new_dir->i_nlink++; mark_inode_dirty(new_dir); } } d_move(old_dentry, new_dentry); retval = 0; end_rename: brelse(dir_bh); brelse(old_bh); brelse(new_bh); return retval; }
int affs_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) { struct inode *old_inode = old_dentry->d_inode; struct inode *new_inode = new_dentry->d_inode; struct buffer_head *old_bh; struct buffer_head *new_bh; unsigned long old_ino; unsigned long new_ino; int retval; pr_debug("AFFS: rename(old=%lu,\"%*s\" (inode=%p) to new=%lu,\"%*s\" (inode=%p))\n", old_dir->i_ino,old_dentry->d_name.len,old_dentry->d_name.name,old_inode, new_dir->i_ino,new_dentry->d_name.len,new_dentry->d_name.name,new_inode); if ((retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len))) goto out; new_bh = NULL; retval = -ENOENT; old_bh = affs_find_entry(old_dir,old_dentry,&old_ino); if (!old_bh) goto end_rename; new_bh = affs_find_entry(new_dir,new_dentry,&new_ino); if (new_bh && !new_inode) { affs_error(old_inode->i_sb,"affs_rename", "No inode for entry found (key=%lu)\n",new_ino); goto end_rename; } if (S_ISDIR(old_inode->i_mode)) { if (new_inode) { retval = -ENOTEMPTY; if (!empty_dir(new_bh,AFFS_I2HSIZE(new_inode))) goto end_rename; } retval = -ENOENT; if (affs_parent_ino(old_inode) != old_dir->i_ino) goto end_rename; } /* Unlink destination if it already exists */ if (new_inode) { if ((retval = affs_remove_header(new_bh,new_dir)) < 0) goto end_rename; new_inode->i_nlink = retval; mark_inode_dirty(new_inode); if (new_inode->i_ino == new_ino) new_inode->i_nlink = 0; } /* Remove header from its parent directory. */ if ((retval = affs_remove_hash(old_bh,old_dir))) goto end_rename; /* And insert it into the new directory with the new name. */ affs_copy_name(FILE_END(old_bh->b_data,old_inode)->file_name,new_dentry->d_name.name); if ((retval = affs_insert_hash(new_dir->i_ino,old_bh,new_dir))) goto end_rename; affs_fix_checksum(AFFS_I2BSIZE(new_dir),old_bh->b_data,5); new_dir->i_ctime = new_dir->i_mtime = old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; new_dir->i_version = ++event; old_dir->i_version = ++event; retval = 0; mark_inode_dirty(new_dir); mark_inode_dirty(old_dir); mark_buffer_dirty(old_bh,1); end_rename: affs_brelse(old_bh); affs_brelse(new_bh); out: return retval; }
/* * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry, struct inode * new_dir, struct dentry * new_dentry) { struct inode * old_inode, * new_inode; struct buffer_head * old_bh, * new_bh, * dir_bh; struct sysv_dir_entry * old_de, * new_de; int retval; old_inode = old_dentry->d_inode; new_inode = new_dentry->d_inode; new_bh = dir_bh = NULL; old_bh = sysv_find_entry(old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de); retval = -ENOENT; if (!old_bh || old_de->inode != old_inode->i_ino) goto end_rename; retval = -EPERM; new_bh = sysv_find_entry(new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de); if (new_bh) { if (!new_inode) { brelse(new_bh); new_bh = NULL; } } if (S_ISDIR(old_inode->i_mode)) { if (new_inode) { retval = -ENOTEMPTY; if (!empty_dir(new_inode)) goto end_rename; } retval = -EIO; dir_bh = sysv_file_bread(old_inode, 0, 0); if (!dir_bh) goto end_rename; if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino) goto end_rename; retval = -EMLINK; if (!new_inode && new_dir != old_dir && new_dir->i_nlink >= new_dir->i_sb->sv_link_max) goto end_rename; } if (!new_bh) { retval = sysv_add_entry(new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_bh, &new_de); if (retval) goto end_rename; } new_de->inode = old_inode->i_ino; old_de->inode = 0; old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; mark_inode_dirty(old_dir); new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME; mark_inode_dirty(new_dir); if (new_inode) { new_inode->i_nlink--; new_inode->i_ctime = CURRENT_TIME; mark_inode_dirty(new_inode); } mark_buffer_dirty(old_bh); mark_buffer_dirty(new_bh); if (dir_bh) { PARENT_INO(dir_bh->b_data) = new_dir->i_ino; mark_buffer_dirty(dir_bh); old_dir->i_nlink--; mark_inode_dirty(old_dir); if (new_inode) { new_inode->i_nlink--; mark_inode_dirty(new_inode); } else { new_dir->i_nlink++; mark_inode_dirty(new_dir); } } retval = 0; end_rename: brelse(dir_bh); brelse(old_bh); brelse(new_bh); return retval; }
//handling link request void link_handler(Msg *msg, int sender_pid) { char oldname[MAXPATHNAMELEN], newname[MAXPATHNAMELEN]; if(path_to_inum(newname,msg->num3,msg->num1,0)>0){ /*newname exists*/ msg->type=-1; return; } memset(oldname,'\0',MAXPATHNAMELEN); memset(newname,'\0',MAXPATHNAMELEN); CopyFrom(sender_pid,oldname,msg->ptr1,msg->num2+1); CopyFrom(sender_pid,newname,msg->ptr2,msg->num3+1); int dir_len=msg->num3; char *dir_newname=newname+msg->num3; while((*dir_newname)!='/'&&dir_newname!=newname){ dir_len--; dir_newname--; } if((*dir_newname)=='/'){ dir_len++; dir_newname++; } int parent_inum=path_to_inum(newname,dir_len,msg->num1,0); int dir_len_old=msg->num2; char *dir_oldname=oldname+msg->num2; while((*dir_oldname)!='/'&&dir_oldname!=oldname){ dir_len_old--; dir_oldname--; } if((*dir_oldname)=='/'){ dir_len_old++; dir_oldname++; } int parent_old_inum=path_to_inum(oldname,dir_len_old,msg->num1,0); int old_inum=check_dir(parent_old_inum,dir_oldname); if(old_inum<=0){ msg->type=-1; return; } inode_cache *old_inode=read_inode(old_inum); if(old_inode->data.type==INODE_DIRECTORY){ msg->type=-1; return; } struct dir_entry *newlink=search_dir_entry(parent_inum,dir_newname); if(newlink!=NULL){ msg->type=-1; return; } if((newlink=empty_dir(parent_inum))==NULL){ msg->type=-1; return; } inode_cache *parent_inode=read_inode(parent_inum); parent_inode->data.size+=sizeof(struct dir_entry); parent_inode->dirty=1; newlink->inum=old_inum; memcpy(newlink->name,dir_newname,msg->num3-dir_len); old_inode->data.nlink++; old_inode->dirty=1; }
static int do_mario_rename(struct inode *old_dir, char *old_name, int old_len, struct inode *new_dir, char *new_name, int new_len) { int ino, error = 0; struct inode *old_inode, *new_inode; struct mario_dir_entry entry; if (old_len > MARIO_NAME_LEN - 1 || new_len > MARIO_NAME_LEN - 1) return -ENAMETOOLONG; if (!(ino = mario_find_entry(old_dir, old_name, old_len))) return -ENOENT; old_inode = iget(old_dir->i_sb, ino); if (!(ino = mario_find_entry(new_dir, new_name, new_len))) goto next_1; new_inode = iget(new_dir->i_sb, ino); if (new_inode == old_inode) { iput(new_inode); iput(old_inode); return 0; } /* do some check */ if (S_ISDIR(new_inode->i_mode)) { if (!S_ISDIR(old_inode->i_mode)) return -EISDIR; if (!empty_dir(new_inode)) return -ENOTEMPTY; } else { if (S_ISDIR(old_inode->i_mode)) return -ENOTDIR; } /* delete new_inode */ down(&new_dir->i_sem); if (new_inode->i_count > 1) { error = -EBUSY; goto next_2; } mario_del_entry(new_inode, 1); next_2: iput(new_inode); up(&new_dir->i_sem); if (error) { iput(old_inode); return error; } next_1: /* delete old_inode but not free blocks occupied */ down(&old_dir->i_sem); if (old_inode->i_count > 1) { error = -EBUSY; goto next_3; } mario_del_entry(old_inode, 0); /* add old_inode to new_dir */ entry.data = old_inode->i_rdev; entry.mode = old_inode->i_mode; entry.size = old_inode->i_size; entry.blocks = old_inode->i_nr_block; strncpy(entry.name, new_name, new_len); entry.name[new_len] = '\0'; /* * If old_inode is a directory we need to change its parent */ if (S_ISDIR(old_inode->i_mode) && old_dir != new_dir) { struct buffer_head *bh; struct mario_dir_entry *tmp; bh = bread(old_inode->i_dev, old_inode->i_rdev); if (!bh) { error = -EIO; goto next_3; } tmp = (struct mario_dir_entry *)bh->b_data; tmp[1].data = new_dir->i_rdev; /* .. */ set_dirty(bh); brelse(bh); } mario_add_entry(new_dir, &entry, NULL); next_3: iput(old_inode); up(&old_dir->i_sem); return error; }
int syscall_rename(const char *a_oldpath, const char *a_newpath) { int ohandle, nhandle; int drive1, drive2; char dir_path1[512], dir_path2[512]; char name_comp1[13], name_comp2[13], conv_name1[11], conv_name2[11]; char oldpath[512], newpath[512]; struct dir_entry dent1, dent2; int exist1, exist2; struct DIR_FILE *dirf; int len1, len2; int i,t; len1 = strlen(a_oldpath); len2 = strlen(a_newpath); if (len1 > 512 || len2 > 512) return ELONGPATH; strcpy(oldpath,a_oldpath); strcpy(newpath,a_newpath); if (oldpath[len1-1] == '/' || oldpath[len1-1] == '\\') oldpath[len1-1] = '\0'; if (newpath[len2-1] == '/' || newpath[len2-1] == '\\') newpath[len2-1] = '\0'; parse_path(oldpath, &drive1, dir_path1, name_comp1); parse_path(newpath, &drive2, dir_path2, name_comp2); if (drive1 != drive2) return EDEVICE_DIFFERENT; nhandle = open_path(drive2, dir_path2); if (nhandle < 0) return nhandle; if (name_comp2[0] !='\0') { if (convert_name(name_comp2, conv_name2) < 0) { close_dir(nhandle); return EINVALIDNAME; // Error } exist2 = find_entry(nhandle, conv_name2, &dent2); } ohandle = open_path(drive1, dir_path1); if (ohandle < 0) { close_dir(nhandle); return ohandle; } if (name_comp1[0] != '\0') { if (convert_name(name_comp1, conv_name1) < 0) { close_dir(nhandle); close_dir(ohandle); return EINVALIDNAME; // Error } exist1 = find_entry(ohandle, conv_name1, &dent1); } // Check whether new path exists and is removable if ((exist2 == 1) && ((dent2.attrib & FTYPE_READONLY) || ((dent2.attrib & FTYPE_DIR) && (empty_dir(nhandle, &dent2) != 1)))) { close_dir(nhandle); close_dir(ohandle); return ETARGET_EXISTS; } // Check if source exists and is movable if (exist1 != 1) { close_dir(nhandle); close_dir(ohandle); return EPATH_NOT_EXISTS; } if ((dent1.attrib & FTYPE_READONLY) != 0) { close_dir(nhandle); close_dir(ohandle); return EREADONLY; } // Check whether oldpath is not a subpath of newpath if ((dent1.attrib & FTYPE_DIR) && (ohandle != nhandle)) { t = nhandle; dirf = &dir_file_list[t]; while (dirf->parent_index >= 0 && dirf->parent_index != ohandle) { t = dirf->parent_index; dirf = &dir_file_list[t]; } if (dirf->parent_index == ohandle) { close_dir(nhandle); close_dir(ohandle); return EOLDPATH_PARENT_OF_NEWPATH; } } // Check if newpath already exists whether it is compatible or not if ((exist2 == 1) && (((dent1.attrib & FTYPE_DIR) != 0 && (dent2.attrib & FTYPE_DIR) == 0) || ((dent1.attrib & FTYPE_DIR) == 0 && (dent2.attrib & FTYPE_DIR) != 0))) { close_dir(nhandle); close_dir(ohandle); return ESRC_DEST_NOT_SAME_TYPE; } // Remove destination entry if exists if (exist2 == 1) { if (dent2.attrib & FTYPE_DIR) syscall_rmdir(newpath); else syscall_unlink(newpath); } // Add the source dir entry after changing the name // to destination directory bcopy( (char *)&dent1, (char *)&dent2, sizeof(struct dir_entry)); for (i=0; i<11; i++) // Both name and extension dent2.name[i] = conv_name2[i]; t = add_dir_entry(nhandle, &dent2); if (t == 1) { delete_dir_entry(ohandle, dent1.name); } // Close the handles of parent directories close_dir(ohandle); close_dir(nhandle); if (t == 1) return 0; else return t; }