/* readdir returns '..', then '.', then the directory entries in sequence As the root directory contains a entry for itself, '.' is not emulated for the root directory */ static int ntfs_readdir(struct file* filp, void *dirent, filldir_t filldir) { struct ntfs_filldir cb; int error; struct inode *dir=filp->f_dentry->d_inode; ntfs_debug(DEBUG_OTHER, "ntfs_readdir ino %x mode %x\n", (unsigned)dir->i_ino,(unsigned int)dir->i_mode); ntfs_debug(DEBUG_OTHER, "readdir: Looking for file %x dircount %d\n", (unsigned)filp->f_pos,atomic_read(&dir->i_count)); cb.pl=filp->f_pos & 0xFFFF; cb.ph=filp->f_pos >> 16; /* end of directory */ if(cb.ph==0xFFFF){ /* FIXME: Maybe we can return those with the previous call */ switch(cb.pl){ case 0: filldir(dirent,".",1,filp->f_pos,dir->i_ino,DT_DIR); filp->f_pos=0xFFFF0001; return 0; /* FIXME: parent directory */ case 1: filldir(dirent,"..",2,filp->f_pos,0,DT_DIR); filp->f_pos=0xFFFF0002; return 0; } ntfs_debug(DEBUG_OTHER, "readdir: EOD\n"); return 0; } cb.dir=dir; cb.filldir=filldir; cb.dirent=dirent; cb.type=NTFS_INO2VOL(dir)->ngt; do{ ntfs_debug(DEBUG_OTHER,"looking for next file\n"); error=ntfs_getdir_unsorted(NTFS_LINO2NINO(dir),&cb.ph,&cb.pl, ntfs_printcb,&cb); }while(!error && cb.ph!=0xFFFFFFFF); filp->f_pos=(cb.ph<<16)|cb.pl; ntfs_debug(DEBUG_OTHER, "new position %x\n",(unsigned)filp->f_pos); /* -EINVAL is on user buffer full. This is not considered as an error by sys_getdents */ if(error<0) error=0; /* Otherwise (device error, inconsistent data), switch the sign */ return -error; }
/* * readdir returns '.', then '..', then the directory entries in sequence. * As the root directory contains an entry for itself, '.' is not emulated for * the root directory. */ static int ntfs_readdir(struct file* filp, void *dirent, filldir_t filldir) { struct inode *dir = filp->f_dentry->d_inode; int err; struct ntfs_filldir cb; cb.ret_code = 0; cb.pl = filp->f_pos & 0xffff; cb.ph = (filp->f_pos >> 16) & 0x7fff; filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Entering for inode %lu, " "f_pos 0x%Lx, i_mode 0x%x, i_count %lu.\n", dir->i_ino, filp->f_pos, (unsigned int)dir->i_mode, atomic_read(&dir->i_count)); if (!cb.ph) { /* Start of directory. Emulate "." and "..". */ if (!cb.pl) { ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Calling " "filldir for . with len 1, f_pos 0x%Lx, " "inode %lu, DT_DIR.\n", filp->f_pos, dir->i_ino); cb.ret_code = filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR); if (cb.ret_code) goto done; cb.pl++; filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl; } if (cb.pl == (u32)1) { ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Calling " "filldir for .. with len 2, f_pos 0x%Lx, " "inode %lu, DT_DIR.\n", filp->f_pos, filp->f_dentry->d_parent->d_inode->i_ino); cb.ret_code = filldir(dirent, "..", 2, filp->f_pos, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR); if (cb.ret_code) goto done; cb.pl++; filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl; } } else if (cb.ph >= 0x7fff) /* End of directory. */ goto done; cb.dir = dir; cb.filldir = filldir; cb.dirent = dirent; cb.type = NTFS_INO2VOL(dir)->ngt; do { ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Looking for next " "file using ntfs_getdir_unsorted(), f_pos " "0x%Lx.\n", (loff_t)(cb.ph << 16) | cb.pl); err = ntfs_getdir_unsorted(NTFS_LINO2NINO(dir), &cb.ph, &cb.pl, ntfs_printcb, &cb); } while (!err && !cb.ret_code && cb.ph < 0x7fff); filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): After ntfs_getdir_unsorted()" " calls, f_pos 0x%Lx.\n", filp->f_pos); if (!err) { done: #ifdef DEBUG if (!cb.ret_code) ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): EOD, f_pos " "0x%Lx, returning 0.\n", filp->f_pos); else ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): filldir " "returned %i, returning 0, f_pos " "0x%Lx.\n", cb.ret_code, filp->f_pos); #endif return 0; } ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Returning %i, f_pos 0x%Lx.\n", err, filp->f_pos); return err; }