static int msdos_readdir(struct inode *inode,struct file *filp, struct dirent *dirent,int count) { int ino,i,i2,last; char c,*walk; struct buffer_head *bh; struct msdos_dir_entry *de; if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; if (inode->i_ino == MSDOS_ROOT_INO) { /* Fake . and .. for the root directory. */ if (filp->f_pos == 2) filp->f_pos = 0; else if (filp->f_pos < 2) { walk = filp->f_pos++ ? ".." : "."; for (i = 0; *walk; walk++) put_fs_byte(*walk,dirent->d_name+i++); put_fs_long(MSDOS_ROOT_INO,&dirent->d_ino); put_fs_byte(0,dirent->d_name+i); put_fs_word(i,&dirent->d_reclen); return i; } } if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1)) return -ENOENT; bh = NULL; while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) { if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) { for (i = last = 0; i < 8; i++) { if (!(c = de->name[i])) break; if (c >= 'A' && c <= 'Z') c += 32; if (c != ' ') last = i+1; put_fs_byte(c,i+dirent->d_name); } i = last; put_fs_byte('.',i+dirent->d_name); i++; for (i2 = 0; i2 < 3; i2++) { if (!(c = de->ext[i2])) break; if (c >= 'A' && c <= 'Z') c += 32; if (c != ' ') last = i+1; put_fs_byte(c,i+dirent->d_name); i++; } if ((i = last) != 0) { if (!strcmp(de->name,MSDOS_DOT)) ino = inode->i_ino; else if (!strcmp(de->name,MSDOS_DOTDOT)) ino = msdos_parent_ino(inode,0); put_fs_long(ino,&dirent->d_ino); put_fs_byte(0,i+dirent->d_name); put_fs_word(i,&dirent->d_reclen); brelse(bh); return i; } } } if (bh) brelse(bh); return 0; }
int msdos_rmdir(struct inode *dir,const char *name,int len) { int res,ino,pos; struct buffer_head *bh,*dbh; struct msdos_dir_entry *de,*dde; struct inode *inode; bh = NULL; inode = NULL; res = -EINVAL; if (get_fs_byte(name) == '.' && (len == 1 || (len == 2 && get_fs_byte(name+1) == '.'))) goto rmdir_done; if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) goto rmdir_done; res = -ENOENT; if (!(inode = iget(dir->i_dev,ino))) goto rmdir_done; res = -ENOTDIR; if (!S_ISDIR(inode->i_mode)) goto rmdir_done; res = -EBUSY; if (dir->i_dev != inode->i_dev || dir == inode) goto rmdir_done; if (inode->i_count > 1) goto rmdir_done; if (MSDOS_I(inode)->i_start) { /* may be zero in mkdir */ res = -ENOTEMPTY; pos = 0; dbh = NULL; while (msdos_get_entry(inode,&pos,&dbh,&dde) > -1) if (dde->name[0] && ((unsigned char *) dde->name)[0] != DELETED_FLAG && strncmp(dde->name,MSDOS_DOT, MSDOS_NAME) && strncmp(dde->name,MSDOS_DOTDOT, MSDOS_NAME)) goto rmdir_done; if (dbh) brelse(dbh); } inode->i_nlink = 0; dir->i_mtime = CURRENT_TIME; dir->i_nlink--; inode->i_dirt = dir->i_dirt = 1; de->name[0] = DELETED_FLAG; bh->b_dirt = 1; res = 0; rmdir_done: brelse(bh); iput(dir); iput(inode); return res; }