Date: Mon, 6 Mar 2000 02:57:01 +0100 From: Jamie Lokier To: torvalds@transmeta.com, linux-kernel@vger.rutgers.edu, linux-fsdevel@vger.rutgers.edu Subject: [PATCH] Return file types from readdir() Message-ID: <20000306025701.A4104@pcep-jamie.cern.ch> With the addition of type info to ext2 a few months ago, I decided to let the kernel return d_type info and see if it makes "find" faster. It does: about twice as fast, with my own version of find that's also optimised in other ways. The Glibc struct dirent, derived from BSD, looks like this: ino_t d_ino; off_t d_off; unsigned short d_reclen; unsigned char d_type; <-- The interesting part char d_name [256]; The d_type field is used by some BSD programs, mainly to tell when an entry is not a directory so that "find" style searches don't have to call stat(). Therefore fewer inodes are read from disk. Glibc currently always stores DT_UNKNOWN in d_type. The obvious change is to the readdir callback the kernel. While updating every filesystem's readdir function, I was surprised to find that most filesystems can generate useful d_type info. The attached patch for 2.3.49: - adds a "type" parameter to readdir() callbacks. - updates all filesystems. Most of the patch is this. - makes sys_getdents() return the info in a way which Glibc and applications can use, while being binary backward compatible. (I don't like new syscalls). You might prefer a new syscall or open() flag to the method I use for returning the info. If that's the case, ask and I'll write. Search for "By storing a 0" to see how it's returned at the moment. You can see the information using my treescan program like this: `treescan -silent -d_type'. It's found at http://www.tantalophile.demon.co.uk/treescan/treescan-0.6.tar.gz http://www.tantalophile.demon.co.uk/treescan/treescan-0.6-1.i686.rpm Here's a summary of the level of support in filesystem. I've tested the ones I can test with various file types. They've all been compiled. autofs [FULL SUPPORT, TESTED] autofs4 [FULL SUPPORT, TESTED] cramfs [FULL SUPPORT, TESTED] devpts [FULL SUPPORT, TESTED] devfs [FULL SUPPORT, TESTED] ext2 [FULL SUPPORT, TESTED] isofs/norock [FULL SUPPORT, TESTED] isofs/rock [FULL SUPPORT, TESTED] msdos [FULL SUPPORT, TESTED] procfs [FULL SUPPORT, TESTED] vfat [FULL SUPPORT, TESTED] umsdos [FULL SUPPORT, TESTED] usbdevfs [FULL SUPPORT, TESTED] adfs [FULL SUPPORT, compiled] coda [FULL SUPPORT, compiled] ncpfs [FULL SUPPORT, compiled] qnx4 [FULL SUPPORT, compiled] romfs [FULL SUPPORT, compiled] ufs [FULL SUPPORT, compiled] hpfs [DIR and REG only, compiled] # More support may be possible. udf [DIR only, compiled] # More support may be possible. hfs [some, compiled] # More support may be possible. affs [return DT_UNKNOWN, compiled] # More support may be possible. bfs [return DT_UNKNOWN, compiled] # No support possible. efs [return DT_UNKNOWN, compiled] # No support possible. minix [return DT_UNKNOWN, compiled] # No support possible. nfs [return DT_UNKNOWN, compiled] # No support possible. nfsd [return DT_UNKNOWN, compiled] # filldir() extra argument. ntfs [return DT_UNKNOWN, compiled] # Code too scary to add support. openpromfs [return DT_UNKNOWN, compiled] # More support may be possible. smbfs [return DT_UNKNOWN, compiled] # More support may be possible. sysv [return DT_UNKNOWN, compiled] # No support possible. IMO the patch is ready for inclusion in the kernel, if you are happy with the method for returning the data to user space. Enjoy, -- Jamie diff -u linux-2.3/arch/alpha/kernel/osf_sys.c.d_type linux-2.3/arch/alpha/kernel/osf_sys.c --- linux-2.3/arch/alpha/kernel/osf_sys.c.d_type Fri Feb 11 23:55:37 2000 +++ linux-2.3/arch/alpha/kernel/osf_sys.c Sun Mar 5 23:13:57 2000 @@ -105,7 +105,7 @@ int error; }; -static int osf_filldir(void *__buf, const char *name, int namlen, off_t offset, ino_t ino) +static int osf_filldir(void *__buf, unsigned char type, const char *name, int namlen, off_t offset, ino_t ino) { struct osf_dirent *dirent; struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf; diff -u linux-2.3/arch/mips/kernel/sysirix.c.d_type linux-2.3/arch/mips/kernel/sysirix.c --- linux-2.3/arch/mips/kernel/sysirix.c.d_type Sun Mar 5 18:30:45 2000 +++ linux-2.3/arch/mips/kernel/sysirix.c Sun Mar 5 23:17:32 2000 @@ -1991,8 +1991,8 @@ #define NAME_OFFSET32(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP32(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1)) -static int irix_filldir32(void *__buf, const char *name, int namlen, - off_t offset, ino_t ino) +static int irix_filldir32(void *__buf, unsigned char type, const char *name, + int namlen, off_t offset, ino_t ino) { struct irix_dirent32 *dirent; struct irix_dirent32_callback *buf = @@ -2104,8 +2104,8 @@ #define NAME_OFFSET64(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1)) -static int irix_filldir64(void * __buf, const char * name, int namlen, - off_t offset, ino_t ino) +static int irix_filldir64(void * __buf, unsigned char type, const char * name, + int namlen, off_t offset, ino_t ino) { struct irix_dirent64 *dirent; struct irix_dirent64_callback * buf = diff -u linux-2.3/arch/sparc/kernel/sys_sunos.c.d_type linux-2.3/arch/sparc/kernel/sys_sunos.c --- linux-2.3/arch/sparc/kernel/sys_sunos.c.d_type Sun Mar 5 18:30:06 2000 +++ linux-2.3/arch/sparc/kernel/sys_sunos.c Sun Mar 5 23:15:40 2000 @@ -403,8 +403,8 @@ #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1)) -static int sunos_filldir(void * __buf, const char * name, int namlen, - off_t offset, ino_t ino) +static int sunos_filldir(void * __buf, unsigned char type, const char * name, + int namlen, off_t offset, ino_t ino) { struct sunos_dirent * dirent; struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf; @@ -494,7 +494,8 @@ int error; }; -static int sunos_filldirentry(void * __buf, const char * name, int namlen, +static int sunos_filldirentry(void * __buf, unsigned char type, + const char * name, int namlen, off_t offset, ino_t ino) { struct sunos_direntry * dirent; diff -u linux-2.3/arch/sparc64/kernel/sys_sparc32.c.d_type linux-2.3/arch/sparc64/kernel/sys_sparc32.c --- linux-2.3/arch/sparc64/kernel/sys_sparc32.c.d_type Sun Mar 5 21:01:52 2000 +++ linux-2.3/arch/sparc64/kernel/sys_sparc32.c Sun Mar 5 23:18:58 2000 @@ -1235,8 +1235,8 @@ int count; }; -static int fillonedir(void * __buf, const char * name, int namlen, - off_t offset, ino_t ino) +static int fillonedir(void * __buf, unsigned char type, const char * name, + int namlen, off_t offset, ino_t ino) { struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf; struct old_linux_dirent32 * dirent; @@ -1301,7 +1301,7 @@ int error; }; -static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino) +static int filldir(void * __buf, unsigned char type, const char * name, int namlen, off_t offset, ino_t ino) { struct linux_dirent32 * dirent; struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf; diff -u linux-2.3/arch/sparc64/kernel/sys_sunos32.c.d_type linux-2.3/arch/sparc64/kernel/sys_sunos32.c --- linux-2.3/arch/sparc64/kernel/sys_sunos32.c.d_type Sun Mar 5 18:30:07 2000 +++ linux-2.3/arch/sparc64/kernel/sys_sunos32.c Sun Mar 5 23:19:30 2000 @@ -359,8 +359,8 @@ #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP(x) (((x)+sizeof(s32)-1) & ~(sizeof(s32)-1)) -static int sunos_filldir(void * __buf, const char * name, int namlen, - off_t offset, ino_t ino) +static int sunos_filldir(void * __buf, unsigned char type, const char * name, + int namlen, off_t offset, ino_t ino) { struct sunos_dirent * dirent; struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf; @@ -451,7 +451,8 @@ int error; }; -static int sunos_filldirentry(void * __buf, const char * name, int namlen, +static int sunos_filldirentry(void * __buf, unsigned char type, + const char * name, int namlen, off_t offset, ino_t ino) { struct sunos_direntry * dirent; diff -u linux-2.3/drivers/usb/inode.c.d_type linux-2.3/drivers/usb/inode.c --- linux-2.3/drivers/usb/inode.c.d_type Sun Mar 5 21:01:57 2000 +++ linux-2.3/drivers/usb/inode.c Sun Mar 5 23:04:28 2000 @@ -24,6 +24,7 @@ * * History: * 0.1 04.01.2000 Created + * 05.03.2000 Filldir requires DT_REG/DT_DIR */ /*****************************************************************************/ @@ -31,6 +32,7 @@ #define __NO_VERSION__ #include #include +#include #include #include #include @@ -292,14 +294,14 @@ i = filp->f_pos; switch (i) { case 0: - if (filldir(dirent, ".", 1, i, IROOT) < 0) + if (filldir(dirent, DT_DIR, ".", 1, i, IROOT) < 0) return 0; filp->f_pos++; i++; /* fall through */ case 1: - if (filldir(dirent, "..", 2, i, IROOT) < 0) + if (filldir(dirent, DT_DIR, "..", 2, i, IROOT) < 0) return 0; filp->f_pos++; i++; @@ -309,7 +311,7 @@ while (i >= 2 && i < 2+NRSPECIAL) { spec = &special[filp->f_pos-2]; - if (filldir(dirent, spec->name, strlen(spec->name), i, ISPECIAL | (filp->f_pos-2+IROOT)) < 0) + if (filldir(dirent, DT_REG, spec->name, strlen(spec->name), i, ISPECIAL | (filp->f_pos-2+IROOT)) < 0) return 0; filp->f_pos++; i++; @@ -325,7 +327,7 @@ } bus = list_entry(list, struct usb_bus, bus_list); sprintf(numbuf, "%03d", bus->busnum); - if (filldir(dirent, numbuf, 3, filp->f_pos, IBUS | ((bus->busnum & 0xff) << 8)) < 0) + if (filldir(dirent, DT_DIR, numbuf, 3, filp->f_pos, IBUS | ((bus->busnum & 0xff) << 8)) < 0) break; filp->f_pos++; } @@ -345,7 +347,7 @@ if (pos > 0) pos--; else { - if (filldir(dirent, numbuf, 3, filp->f_pos, ino | (dev->devnum & 0xff)) < 0) + if (filldir(dirent, DT_REG, numbuf, 3, filp->f_pos, ino | (dev->devnum & 0xff)) < 0) return -1; filp->f_pos++; } @@ -370,13 +372,13 @@ return -EINVAL; switch ((unsigned int)filp->f_pos) { case 0: - if (filldir(dirent, ".", 1, filp->f_pos, ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, filp->f_pos, ino) < 0) return 0; filp->f_pos++; /* fall through */ case 1: - if (filldir(dirent, "..", 2, filp->f_pos, IROOT) < 0) + if (filldir(dirent, DT_DIR, "..", 2, filp->f_pos, IROOT) < 0) return 0; filp->f_pos++; /* fall through */ diff -u linux-2.3/fs/adfs/dir.c.d_type linux-2.3/fs/adfs/dir.c --- linux-2.3/fs/adfs/dir.c.d_type Sun Mar 5 20:59:01 2000 +++ linux-2.3/fs/adfs/dir.c Sun Mar 5 21:04:26 2000 @@ -11,6 +11,7 @@ #include #include #include +#include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) #include @@ -41,12 +42,12 @@ switch (filp->f_pos) { case 0: - if (filldir(dirent, ".", 1, 0, inode->i_ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, 0, inode->i_ino) < 0) goto free_out; filp->f_pos += 1; case 1: - if (filldir(dirent, "..", 2, 1, dir.parent_id) < 0) + if (filldir(dirent, DT_DIR, "..", 2, 1, dir.parent_id) < 0) goto free_out; filp->f_pos += 1; @@ -60,7 +61,12 @@ if (ret) goto unlock_out; while (ops->getnext(&dir, &obj) == 0) { - if (filldir(dirent, obj.name, obj.name_len, + unsigned char type = DT_REG; + if (obj.attr & ADFS_NDA_DIRECTORY) + type = DT_DIR; + else if ((obj.loadaddr & 0xffffff00) == 0xffffc000) + type = DT_LNK; /* LinkFS */ + if (filldir(dirent, type, obj.name, obj.name_len, filp->f_pos, obj.file_id) < 0) goto unlock_out; filp->f_pos += 1; diff -u linux-2.3/fs/affs/dir.c.d_type linux-2.3/fs/affs/dir.c --- linux-2.3/fs/affs/dir.c.d_type Sun Mar 5 20:59:01 2000 +++ linux-2.3/fs/affs/dir.c Sun Mar 5 21:04:26 2000 @@ -23,6 +23,7 @@ #include #include #include +#include static int affs_readdir(struct file *, void *, filldir_t); @@ -72,14 +73,14 @@ if (filp->f_pos == 0) { filp->private_data = (void *)0; - if (filldir(dirent,".",1,filp->f_pos,inode->i_ino) < 0) { + if (filldir(dirent,DT_DIR,".",1,filp->f_pos,inode->i_ino) < 0) { return 0; } ++filp->f_pos; stored++; } if (filp->f_pos == 1) { - if (filldir(dirent,"..",2,filp->f_pos,affs_parent_ino(inode)) < 0) { + if (filldir(dirent,DT_DIR,"..",2,filp->f_pos,affs_parent_ino(inode)) < 0) { return stored; } filp->f_pos = 2; @@ -135,7 +136,7 @@ pr_debug("AFFS: readdir(): filldir(\"%.*s\",ino=%lu), i=%d\n", namelen,name,ino,i); filp->private_data = (void *)ino; - if (filldir(dirent,name,namelen,filp->f_pos,ino) < 0) + if (filldir(dirent,DT_UNKNOWN,name,namelen,filp->f_pos,ino) < 0) goto readdir_done; filp->private_data = (void *)i; affs_brelse(fh_bh); diff -u linux-2.3/fs/autofs/dir.c.d_type linux-2.3/fs/autofs/dir.c --- linux-2.3/fs/autofs/dir.c.d_type Sun Mar 5 20:59:02 2000 +++ linux-2.3/fs/autofs/dir.c Sun Mar 5 23:10:27 2000 @@ -10,6 +10,7 @@ * * ------------------------------------------------------------------------- */ +#include #include "autofs_i.h" static int autofs_dir_readdir(struct file *filp, @@ -20,12 +21,12 @@ switch((unsigned long) filp->f_pos) { case 0: - if (filldir(dirent, ".", 1, 0, inode->i_ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, 0, inode->i_ino) < 0) return 0; filp->f_pos++; /* fall through */ case 1: - if (filldir(dirent, "..", 2, 1, AUTOFS_ROOT_INO) < 0) + if (filldir(dirent, DT_DIR, "..", 2, 1, AUTOFS_ROOT_INO) < 0) return 0; filp->f_pos++; /* fall through */ diff -u linux-2.3/fs/autofs/root.c.d_type linux-2.3/fs/autofs/root.c --- linux-2.3/fs/autofs/root.c.d_type Sun Mar 5 20:59:02 2000 +++ linux-2.3/fs/autofs/root.c Sun Mar 5 22:26:13 2000 @@ -13,6 +13,7 @@ #include #include #include +#include #include "autofs_i.h" static int autofs_root_readdir(struct file *,void *,filldir_t); @@ -52,19 +53,22 @@ switch(nr) { case 0: - if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, nr, inode->i_ino) < 0) return 0; filp->f_pos = ++nr; /* fall through */ case 1: - if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0) + if (filldir(dirent, DT_DIR, "..", 2, nr, inode->i_ino) < 0) return 0; filp->f_pos = ++nr; /* fall through */ default: while ( onr = nr, ent = autofs_hash_enum(dirhash,&nr,ent) ) { if ( !ent->dentry || ent->dentry->d_mounts != ent->dentry ) { - if (filldir(dirent,ent->name,ent->len,onr,ent->ino) < 0) + unsigned char type = DT_DIR; + if (ent->ino < AUTOFS_FIRST_DIR_INO) + type = DT_LNK; + if (filldir(dirent,type,ent->name,ent->len,onr,ent->ino) < 0) return 0; filp->f_pos = nr; } diff -u linux-2.3/fs/autofs4/root.c.d_type linux-2.3/fs/autofs4/root.c --- linux-2.3/fs/autofs4/root.c.d_type Sun Mar 5 20:59:02 2000 +++ linux-2.3/fs/autofs4/root.c Sun Mar 5 22:02:57 2000 @@ -14,6 +14,7 @@ #include #include #include +#include #include "autofs_i.h" static int autofs4_dir_readdir(struct file *,void *,filldir_t); @@ -82,12 +83,12 @@ switch(nr) { case 0: - if (filldir(dirent, ".", 1, nr, dir->i_ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, nr, dir->i_ino) < 0) return 0; filp->f_pos = ++nr; /* fall through */ case 1: - if (filldir(dirent, "..", 2, nr, dentry->d_covers->d_parent->d_inode->i_ino) < 0) + if (filldir(dirent, DT_DIR, "..", 2, nr, dentry->d_covers->d_parent->d_inode->i_ino) < 0) return 0; filp->f_pos = ++nr; /* fall through */ @@ -101,7 +102,8 @@ while(cursor != &dentry->d_subdirs) { dent_ptr = list_entry(cursor, struct dentry, d_child); if (dent_ptr->d_inode && - filldir(dirent, dent_ptr->d_name.name, dent_ptr->d_name.len, nr, + filldir(dirent, IFTODT (dent_ptr->d_inode->i_mode), + dent_ptr->d_name.name, dent_ptr->d_name.len, nr, dent_ptr->d_inode->i_ino) < 0) return 0; filp->f_pos = ++nr; diff -u linux-2.3/fs/bfs/dir.c.d_type linux-2.3/fs/bfs/dir.c --- linux-2.3/fs/bfs/dir.c.d_type Sun Mar 5 20:59:02 2000 +++ linux-2.3/fs/bfs/dir.c Sun Mar 5 21:04:26 2000 @@ -8,6 +8,7 @@ #include #include #include +#include #include "bfs_defs.h" @@ -55,7 +56,7 @@ de = (struct bfs_dirent *)(bh->b_data + offset); if (de->ino) { int size = strnlen(de->name, BFS_NAMELEN); - if (filldir(dirent, de->name, size, f->f_pos, de->ino) < 0) { + if (filldir(dirent, DT_UNKNOWN, de->name, size, f->f_pos, de->ino) < 0) { brelse(bh); return 0; } diff -u linux-2.3/fs/coda/dir.c.d_type linux-2.3/fs/coda/dir.c --- linux-2.3/fs/coda/dir.c.d_type Sun Mar 5 20:59:02 2000 +++ linux-2.3/fs/coda/dir.c Sun Mar 5 21:04:26 2000 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -725,8 +726,10 @@ off_t offs = filp->f_pos; ino_t ino = vdirent->d_fileno; char *name = vdirent->d_name; + /* CDT_* types are the same as DT_* types. */ + unsigned char type = vdirent->d_type; - errfill = filldir(getdent, name, namlen, + errfill = filldir(getdent, type, name, namlen, offs, ino); CDEBUG(D_FILE, "entry %d: ino %ld, namlen %d, reclen %d, type %d, pos %d, string_offs %d, name %*s, offset %d, result: %d, errfill: %d.\n", i,vdirent->d_fileno, vdirent->d_namlen, vdirent->d_reclen, vdirent->d_type, pos, string_offset, vdirent->d_namlen, vdirent->d_name, (u_int) offs, result, errfill); /* errfill means no space for filling in this round */ diff -u linux-2.3/fs/cramfs/inode.c.d_type linux-2.3/fs/cramfs/inode.c --- linux-2.3/fs/cramfs/inode.c.d_type Sun Mar 5 20:59:02 2000 +++ linux-2.3/fs/cramfs/inode.c Sun Mar 5 21:04:26 2000 @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -266,7 +267,8 @@ break; namelen--; } - error = filldir(dirent, name, namelen, offset, CRAMINO(de)); + error = filldir(dirent, IFTODT(de->mode), + name, namelen, offset, CRAMINO(de)); if (error) break; diff -u linux-2.3/fs/devfs/base.c.d_type linux-2.3/fs/devfs/base.c --- linux-2.3/fs/devfs/base.c.d_type Sun Mar 5 20:59:02 2000 +++ linux-2.3/fs/devfs/base.c Sun Mar 5 21:04:26 2000 @@ -445,6 +445,7 @@ #include #include #include +#include #include #include #include @@ -2393,7 +2394,7 @@ { case 0: scan_dir_for_removable (parent); - err = (*filldir) (dirent, "..", 2, file->f_pos, + err = (*filldir) (dirent, DT_DIR, "..", 2, file->f_pos, file->f_dentry->d_parent->d_inode->i_ino); if (err == -EINVAL) break; if (err < 0) return err; @@ -2401,7 +2402,7 @@ ++stored; /* Fall through */ case 1: - err = (*filldir) (dirent, ".", 1, file->f_pos, inode->i_ino); + err = (*filldir) (dirent, DT_DIR, ".", 1, file->f_pos, inode->i_ino); if (err == -EINVAL) break; if (err < 0) return err; file->f_pos++; @@ -2443,7 +2444,7 @@ if (di == NULL) return -ENOMEM; } else if (di->ctime == 0) update_devfs_inode_from_entry (di); - err = (*filldir) (dirent, de->name, de->namelen, + err = (*filldir) (dirent, IFTODT (di->mode), de->name, de->namelen, file->f_pos, di->ino); if (err == -EINVAL) break; if (err < 0) return err; diff -u linux-2.3/fs/devpts/root.c.d_type linux-2.3/fs/devpts/root.c --- linux-2.3/fs/devpts/root.c.d_type Sun Mar 5 20:59:02 2000 +++ linux-2.3/fs/devpts/root.c Sun Mar 5 21:04:26 2000 @@ -14,6 +14,7 @@ #include #include #include +#include #include "devpts_i.h" static int devpts_root_readdir(struct file *,void *,filldir_t); @@ -54,12 +55,12 @@ switch(nr) { case 0: - if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, nr, inode->i_ino) < 0) return 0; filp->f_pos = ++nr; /* fall through */ case 1: - if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0) + if (filldir(dirent, DT_DIR, "..", 2, nr, inode->i_ino) < 0) return 0; filp->f_pos = ++nr; /* fall through */ @@ -68,7 +69,7 @@ int ptynr = nr - 2; if ( sbi->inodes[ptynr] ) { genptsname(numbuf, ptynr); - if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 ) + if ( filldir(dirent, DT_CHR, numbuf, strlen(numbuf), nr, nr) < 0 ) return 0; } filp->f_pos = ++nr; diff -u linux-2.3/fs/efs/dir.c.d_type linux-2.3/fs/efs/dir.c --- linux-2.3/fs/efs/dir.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/efs/dir.c Sun Mar 5 21:04:26 2000 @@ -5,6 +5,7 @@ */ #include +#include static int efs_readdir(struct file *, void *, filldir_t); @@ -78,7 +79,7 @@ filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot; /* copy filename and data in dirslot */ - filldir(dirent, nameptr, namelen, filp->f_pos, inodenum); + filldir(dirent, DT_UNKNOWN, nameptr, namelen, filp->f_pos, inodenum); /* sanity check */ if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) { diff -u linux-2.3/fs/ext2/dir.c.d_type linux-2.3/fs/ext2/dir.c --- linux-2.3/fs/ext2/dir.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/ext2/dir.c Sun Mar 5 21:04:26 2000 @@ -19,6 +19,7 @@ */ #include +#include static int ext2_readdir(struct file *, void *, filldir_t); @@ -57,6 +58,17 @@ return error_msg == NULL ? 1 : 0; } +static const char ext2_file_types [EXT2_FT_MAX] = { + DT_UNKNOWN, /* EXT2_FT_UNKNOWN */ + DT_REG, /* EXT2_FT_REG_FILE */ + DT_DIR, /* EXT2_FT_DIR */ + DT_CHR, /* EXT2_FT_CHRDEV */ + DT_BLK, /* EXT2_FT_BLKDEV */ + DT_FIFO, /* EXT2_FT_FIFO */ + DT_SOCK, /* EXT2_FT_SOCK */ + DT_LNK, /* EXT2_FT_SYMLINK */ +}; + static int ext2_readdir(struct file * filp, void * dirent, filldir_t filldir) { @@ -152,9 +164,13 @@ * during the copy operation. */ unsigned long version = inode->i_version; + unsigned char type = DT_UNKNOWN; + + if (de->file_type < EXT2_FT_MAX) + type = ext2_file_types [de->file_type]; - error = filldir(dirent, de->name, - de->name_len, + error = filldir(dirent, type, + de->name, de->name_len, filp->f_pos, le32_to_cpu(de->inode)); if (error) break; diff -u linux-2.3/fs/fat/dir.c.d_type linux-2.3/fs/fat/dir.c --- linux-2.3/fs/fat/dir.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/fat/dir.c Sun Mar 5 21:04:28 2000 @@ -296,7 +296,7 @@ struct nls_table *nls_io = MSDOS_SB(sb)->nls_io; struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk; struct nls_unicode bufuname[14], *ptuname = &bufuname[0]; - unsigned char long_slots, *unicode = NULL; + unsigned char long_slots, *unicode = NULL, type; char c, bufname[56], *ptname = bufname; unsigned long lpos, dummy, *furrfu = &lpos; int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate; @@ -309,7 +309,7 @@ /* Fake . and .. for the root directory. */ if (inode->i_ino == MSDOS_ROOT_INO) { while (cpos < 2) { - if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO) < 0) + if (filldir(dirent, DT_DIR, "..", cpos+1, cpos, MSDOS_ROOT_INO) < 0) return 0; cpos++; filp->f_pos++; @@ -438,6 +438,10 @@ i = last + dotoffset; + type = DT_REG; + if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) + type = DT_DIR; + lpos = cpos - (long_slots+1)*sizeof(struct msdos_dir_entry); if (!memcmp(de->name,MSDOS_DOT,11)) inum = inode->i_ino; @@ -463,7 +467,7 @@ if (!long_slots||shortnames) { if (both) bufname[i] = '\0'; - if (filldir(dirent, bufname, i, *furrfu, inum) < 0) + if (filldir(dirent, type, bufname, i, *furrfu, inum) < 0) goto FillFailed; } else { char longname[275]; @@ -474,7 +478,8 @@ memcpy(&longname[long_len+1], bufname, i); long_len += i; } - if (filldir(dirent, longname, long_len, *furrfu, inum) < 0) + if (filldir(dirent, type, longname, long_len, + *furrfu, inum) < 0) goto FillFailed; } @@ -501,13 +506,14 @@ static int vfat_ioctl_fill( void * buf, + unsigned char type, const char * name, int name_len, off_t offset, ino_t ino) { - struct dirent *d1 = (struct dirent *)buf; - struct dirent *d2 = d1 + 1; + struct getdents_dirent *d1 = (struct getdents_dirent *)buf; + struct getdents_dirent *d2 = d1 + 1; int len, slen; int dotdir; @@ -559,8 +565,9 @@ */ switch (cmd) { case VFAT_IOCTL_READDIR_BOTH: { - struct dirent *d1 = (struct dirent *)arg; - err = verify_area(VERIFY_WRITE, d1, sizeof(struct dirent[2])); + struct getdents_dirent *d1 = (struct getdents_dirent *)arg; + err = verify_area(VERIFY_WRITE, d1, + sizeof(struct getdents_dirent[2])); if (err) return err; put_user(0, &d1->d_reclen); @@ -568,9 +575,10 @@ vfat_ioctl_fill, 0, 1); } case VFAT_IOCTL_READDIR_SHORT: { - struct dirent *d1 = (struct dirent *)arg; + struct getdents_dirent *d1 = (struct getdents_dirent *) arg; put_user(0, &d1->d_reclen); - err = verify_area(VERIFY_WRITE, d1, sizeof(struct dirent[2])); + err = verify_area(VERIFY_WRITE, d1, + sizeof(struct getdents_dirent[2])); if (err) return err; return fat_readdirx(inode,filp,(void *)arg, diff -u linux-2.3/fs/hfs/dir_cap.c.d_type linux-2.3/fs/hfs/dir_cap.c --- linux-2.3/fs/hfs/dir_cap.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/hfs/dir_cap.c Sun Mar 5 21:04:28 2000 @@ -24,6 +24,7 @@ #include #include #include +#include /*================ Forward declarations ================*/ @@ -190,7 +191,7 @@ if (filp->f_pos == 0) { /* Entry 0 is for "." */ - if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino)) { + if (filldir(dirent, DT_DIR, DOT->Name, DOT_LEN, 0, dir->i_ino)) { return 0; } filp->f_pos = 1; @@ -206,7 +207,7 @@ cnid = entry->cnid; } - if (filldir(dirent, DOT_DOT->Name, + if (filldir(dirent, DT_DIR, DOT_DOT->Name, DOT_DOT_LEN, 1, ntohl(cnid))) { return 0; } @@ -233,7 +234,7 @@ ino = ntohl(cnid) | HFS_I(dir)->file_type; len = hfs_namein(dir, tmp_name, &((struct hfs_cat_key *)brec.key)->CName); - if (filldir(dirent, tmp_name, len, + if (filldir(dirent, DT_UNKNOWN, tmp_name, len, filp->f_pos, ino)) { hfs_cat_close(entry, &brec); return 0; @@ -248,7 +249,7 @@ if ((entry->cnid == htonl(HFS_ROOT_CNID)) && (type == HFS_CAP_NDIR)) { /* In root dir last-2 entry is for ".rootinfo" */ - if (filldir(dirent, DOT_ROOTINFO->Name, + if (filldir(dirent, DT_UNKNOWN, DOT_ROOTINFO->Name, DOT_ROOTINFO_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_CAP_FNDR)) { return 0; @@ -260,7 +261,7 @@ if (filp->f_pos == (dir->i_size - 2)) { if (type == HFS_CAP_NDIR) { /* In normal dirs last-1 entry is for ".finderinfo" */ - if (filldir(dirent, DOT_FINDERINFO->Name, + if (filldir(dirent, DT_UNKNOWN, DOT_FINDERINFO->Name, DOT_FINDERINFO_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_CAP_FDIR)) { return 0; @@ -272,7 +273,7 @@ if (filp->f_pos == (dir->i_size - 1)) { if (type == HFS_CAP_NDIR) { /* In normal dirs last entry is for ".resource" */ - if (filldir(dirent, DOT_RESOURCE->Name, + if (filldir(dirent, DT_UNKNOWN, DOT_RESOURCE->Name, DOT_RESOURCE_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_CAP_RDIR)) { return 0; diff -u linux-2.3/fs/hfs/dir_dbl.c.d_type linux-2.3/fs/hfs/dir_dbl.c --- linux-2.3/fs/hfs/dir_dbl.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/hfs/dir_dbl.c Sun Mar 5 21:04:28 2000 @@ -20,6 +20,7 @@ #include #include #include +#include /*================ Forward declarations ================*/ @@ -183,7 +184,7 @@ if (filp->f_pos == 0) { /* Entry 0 is for "." */ - if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino)) { + if (filldir(dirent, DT_DIR, DOT->Name, DOT_LEN, 0, dir->i_ino)) { return 0; } filp->f_pos = 1; @@ -191,7 +192,7 @@ if (filp->f_pos == 1) { /* Entry 1 is for ".." */ - if (filldir(dirent, DOT_DOT->Name, DOT_DOT_LEN, 1, + if (filldir(dirent, DT_DIR, DOT_DOT->Name, DOT_DOT_LEN, 1, hfs_get_hl(entry->key.ParID))) { return 0; } @@ -229,7 +230,7 @@ &((struct hfs_cat_key *)brec.key)->CName); } - if (filldir(dirent, tmp_name, len, filp->f_pos, ino)) { + if (filldir(dirent, DT_UNKNOWN, tmp_name, len, filp->f_pos, ino)) { hfs_cat_close(entry, &brec); return 0; } @@ -241,7 +242,7 @@ if (filp->f_pos == (dir->i_size - 1)) { if (entry->cnid == htonl(HFS_ROOT_CNID)) { /* In root dir last entry is for "%RootInfo" */ - if (filldir(dirent, PCNT_ROOTINFO->Name, + if (filldir(dirent, DT_UNKNOWN, PCNT_ROOTINFO->Name, PCNT_ROOTINFO_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_DBL_HDR)) { return 0; diff -u linux-2.3/fs/hfs/dir_nat.c.d_type linux-2.3/fs/hfs/dir_nat.c --- linux-2.3/fs/hfs/dir_nat.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/hfs/dir_nat.c Sun Mar 5 21:04:28 2000 @@ -26,6 +26,7 @@ #include #include #include +#include /*================ Forward declarations ================*/ @@ -191,7 +192,8 @@ if (filp->f_pos == 0) { /* Entry 0 is for "." */ - if (filldir(dirent, DOT->Name, DOT_LEN, 0, dir->i_ino)) { + if (filldir(dirent, DT_DIR, DOT->Name, DOT_LEN, + 0, dir->i_ino)) { return 0; } filp->f_pos = 1; @@ -207,8 +209,8 @@ cnid = entry->cnid; } - if (filldir(dirent, DOT_DOT->Name, - DOT_DOT_LEN, 1, ntohl(cnid))) { + if (filldir(dirent, DT_DIR, DOT_DOT->Name, DOT_DOT_LEN, + 1, ntohl(cnid))) { return 0; } filp->f_pos = 2; @@ -234,7 +236,7 @@ ino = ntohl(cnid) | HFS_I(dir)->file_type; len = hfs_namein(dir, tmp_name, &((struct hfs_cat_key *)brec.key)->CName); - if (filldir(dirent, tmp_name, len, + if (filldir(dirent, DT_UNKNOWN, tmp_name, len, filp->f_pos, ino)) { hfs_cat_close(entry, &brec); return 0; @@ -248,14 +250,14 @@ if (filp->f_pos == (dir->i_size - 2)) { if (type == HFS_NAT_NDIR) { /* In normal dirs entry 2 is for ".AppleDouble" */ - if (filldir(dirent, DOT_APPLEDOUBLE->Name, + if (filldir(dirent, DT_DIR, DOT_APPLEDOUBLE->Name, DOT_APPLEDOUBLE_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_NAT_HDIR)) { return 0; } } else if (type == HFS_NAT_HDIR) { /* In .AppleDouble entry 2 is for ".Parent" */ - if (filldir(dirent, DOT_PARENT->Name, + if (filldir(dirent, DT_UNKNOWN, DOT_PARENT->Name, DOT_PARENT_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_NAT_HDR)) { return 0; @@ -268,7 +270,7 @@ /* handle ROOT/.AppleDouble/RootInfo as the last entry. */ if ((entry->cnid == htonl(HFS_ROOT_CNID)) && (type == HFS_NAT_HDIR)) { - if (filldir(dirent, ROOTINFO->Name, + if (filldir(dirent, DT_UNKNOWN, ROOTINFO->Name, ROOTINFO_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_NAT_HDR)) { return 0; diff -u linux-2.3/fs/hpfs/dir.c.d_type linux-2.3/fs/hpfs/dir.c --- linux-2.3/fs/hpfs/dir.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/hpfs/dir.c Sun Mar 5 21:04:28 2000 @@ -7,6 +7,7 @@ */ #include "hpfs_fn.h" +#include int hpfs_dir_release(struct inode *inode, struct file *filp) { @@ -104,14 +105,14 @@ return 0; } if (filp->f_pos == 0) { - if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0) { + if (filldir(dirent, DT_DIR, ".", 1, filp->f_pos, inode->i_ino) < 0) { hpfs_unlock_inode(inode); return 0; } filp->f_pos = 11; } if (filp->f_pos == 11) { - if (filldir(dirent, "..", 2, filp->f_pos, inode->i_hpfs_parent_dir) < 0) { + if (filldir(dirent, DT_DIR, "..", 2, filp->f_pos, inode->i_hpfs_parent_dir) < 0) { hpfs_unlock_inode(inode); return 0; } @@ -140,7 +141,10 @@ goto again; } tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3); - if (filldir(dirent, tempname, de->namelen, old_pos, de->fnode) < 0) { + if (filldir(dirent, (de->directory ? DT_DIR + : !de->has_ea ? DT_REG + : DT_UNKNOWN), + tempname, de->namelen, old_pos, de->fnode) < 0) { filp->f_pos = old_pos; if (tempname != (char *)de->name) kfree(tempname); hpfs_brelse4(&qbh); diff -u linux-2.3/fs/isofs/dir.c.d_type linux-2.3/fs/isofs/dir.c --- linux-2.3/fs/isofs/dir.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/isofs/dir.c Sun Mar 5 21:04:28 2000 @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -112,6 +113,7 @@ int first_de = 1; char *p = NULL; /* Quiet GCC */ struct iso_directory_record *de; + unsigned char type; if (filp->f_pos >= inode->i_size) return 0; @@ -191,7 +193,7 @@ /* Handle the case of the '.' directory */ if (de->name_len[0] == 1 && de->name[0] == 0) { - if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, filp->f_pos, inode->i_ino) < 0) break; filp->f_pos += de_len; continue; @@ -202,7 +204,7 @@ /* Handle the case of the '..' directory */ if (de->name_len[0] == 1 && de->name[0] == 1) { inode_number = filp->f_dentry->d_parent->d_inode->i_ino; - if (filldir(dirent, "..", 2, filp->f_pos, inode_number) < 0) + if (filldir(dirent, DT_DIR, "..", 2, filp->f_pos, inode_number) < 0) break; filp->f_pos += de_len; continue; @@ -219,8 +221,9 @@ } map = 1; + type = (de->flags[-high_sierra] & 2) ? DT_DIR : DT_REG; if (inode->i_sb->u.isofs_sb.s_rock) { - len = get_rock_ridge_filename(de, tmpname, inode); + len = get_rock_ridge_filename(de, tmpname, inode, &type); if (len != 0) { p = tmpname; map = 0; @@ -247,7 +250,7 @@ } } if (len > 0) { - if (filldir(dirent, p, len, filp->f_pos, inode_number) < 0) + if (filldir(dirent, type, p, len, filp->f_pos, inode_number) < 0) break; } filp->f_pos += de_len; diff -u linux-2.3/fs/isofs/namei.c.d_type linux-2.3/fs/isofs/namei.c --- linux-2.3/fs/isofs/namei.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/isofs/namei.c Sun Mar 5 21:04:28 2000 @@ -169,7 +169,7 @@ } } if (dir->i_sb->u.isofs_sb.s_rock && - ((i = get_rock_ridge_filename(de, page, dir)))) { + ((i = get_rock_ridge_filename(de, page, dir, 0)))) { dlen = i; dpnt = page; #ifdef CONFIG_JOLIET diff -u linux-2.3/fs/isofs/rock.c.d_type linux-2.3/fs/isofs/rock.c --- linux-2.3/fs/isofs/rock.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/isofs/rock.c Sun Mar 5 21:04:28 2000 @@ -13,15 +13,16 @@ #include #include #include +#include #include "rock.h" /* These functions are designed to read the system areas of a directory record * and extract relevant information. There are different functions provided * depending upon what information we need at the time. One function fills - * out an inode structure, a second one extracts a filename, a third one - * returns a symbolic link name, and a fourth one returns the extent number - * for the file. */ + * out an inode structure, a second one extracts a filename and d_type value, + * a third one returns a symbolic link name, and a fourth one returns the + * extent number for the file. */ #define SIG(A,B) ((A << 8) | B) @@ -152,7 +153,8 @@ } int get_rock_ridge_filename(struct iso_directory_record * de, - char * retname, struct inode * inode) + char * retname, struct inode * inode, + unsigned char * rettype) { int len; unsigned char * chr; @@ -215,6 +217,34 @@ #endif if (buffer) kfree(buffer); return -1; + case SIG('C','L'): +#ifdef DEBUG + printk("RR: CL (%x)\n",inode->i_ino); +#endif + /* Mode is set from relocated entry. Don't look it up as that misses + the point of the DT_* optimisation. */ + if (rettype) + *rettype = DT_UNKNOWN; + break; + case SIG('P','X'): + /* + * Merge mode with previous type byte. It was either DT_DIR, DT_REG, + * or set by a previous PX record (should never repeat but hey...). + * + * Some RR directories have 0 (unknown) for the type here and + * are not flagged as directories in the base record. If you + * mount with norock, they look like empty files. But with + * RR, they are directories. This code sets the type to + * DT_UNKNOWN in that case (it would be DT_REG otherwise). + */ + if (rettype) { + mode_t mode = isonum_733(rr->u.PX.mode); + if (!S_ISDIR(mode) && *rettype == DT_REG) + *rettype = IFTODT(mode); + else if (*rettype != IFTODT(mode)) + *rettype = DT_UNKNOWN; + } + break; default: break; } diff -u linux-2.3/fs/minix/dir.c.d_type linux-2.3/fs/minix/dir.c --- linux-2.3/fs/minix/dir.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/minix/dir.c Sun Mar 5 21:04:28 2000 @@ -11,6 +11,7 @@ #include #include #include +#include static int minix_readdir(struct file *, void *, filldir_t); @@ -43,7 +44,7 @@ de = (struct minix_dir_entry *) (offset + bh->b_data); if (de->inode) { int size = strnlen(de->name, info->s_namelen); - if (filldir(dirent, de->name, size, filp->f_pos, de->inode) < 0) { + if (filldir(dirent, DT_UNKNOWN, de->name, size, filp->f_pos, de->inode) < 0) { brelse(bh); return 0; } diff -u linux-2.3/fs/ncpfs/dir.c.d_type linux-2.3/fs/ncpfs/dir.c --- linux-2.3/fs/ncpfs/dir.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/ncpfs/dir.c Sun Mar 5 21:04:28 2000 @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -433,12 +434,12 @@ result = 0; if (filp->f_pos == 0) { - if (filldir(dirent, ".", 1, 0, inode->i_ino)) + if (filldir(dirent, DT_DIR, ".", 1, 0, inode->i_ino)) goto out; filp->f_pos = 1; } if (filp->f_pos == 1) { - if (filldir(dirent, "..", 2, 1, + if (filldir(dirent, DT_DIR, "..", 2, 1, dentry->d_parent->d_inode->i_ino)) goto out; filp->f_pos = 2; @@ -488,9 +489,9 @@ dentry, filp->f_pos); if (!dent) goto invalid_cache; - res = filldir(dirent, dent->d_name.name, - dent->d_name.len, filp->f_pos, - dent->d_inode->i_ino); + res = filldir(dirent, IFTODT (dent->d_inode->i_mode), + dent->d_name.name, dent->d_name.len, + filp->f_pos, dent->d_inode->i_ino); dput(dent); if (res) goto finished; @@ -567,6 +568,7 @@ struct qstr qname; int valid = 0; ino_t ino = 0; + unsigned char type = DT_UNKNOWN; __u8 __name[256]; qname.len = 256; @@ -605,6 +607,7 @@ if (newdent->d_inode) { ino = newdent->d_inode->i_ino; + type = IFTODT (newdent->d_inode->i_mode); newdent->d_fsdata = (void *) ctl.fpos; ncp_new_dentry(newdent); } @@ -636,7 +639,7 @@ ino = find_inode_number(dentry, &qname); if (!ino) ino = iunique(inode->i_sb, 2); - ctl.filled = filldir(dirent, qname.name, qname.len, + ctl.filled = filldir(dirent, type, qname.name, qname.len, filp->f_pos, ino); if (!ctl.filled) filp->f_pos += 1; diff -u linux-2.3/fs/nfs/dir.c.d_type linux-2.3/fs/nfs/dir.c --- linux-2.3/fs/nfs/dir.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/nfs/dir.c Sun Mar 5 21:04:28 2000 @@ -30,6 +30,7 @@ #include #include #include +#include #include /* for fs functions */ @@ -379,7 +380,7 @@ continue; cookie = this_cookie; - if (filldir(dirent, name, len, cookie, fileid) < 0) + if (filldir(dirent, DT_UNKNOWN, name, len, cookie, fileid) < 0) break; } diff -u linux-2.3/fs/nfsd/nfs3xdr.c.d_type linux-2.3/fs/nfsd/nfs3xdr.c --- linux-2.3/fs/nfsd/nfs3xdr.c.d_type Sun Mar 5 21:01:59 2000 +++ linux-2.3/fs/nfsd/nfs3xdr.c Sun Mar 5 21:04:28 2000 @@ -736,15 +736,17 @@ } int -nfs3svc_encode_entry(struct readdir_cd *cd, const char *name, - int namlen, off_t offset, ino_t ino) +nfs3svc_encode_entry(struct readdir_cd *cd, unsigned char type, + const char *name, int namlen, + off_t offset, ino_t ino) { return encode_entry(cd, name, namlen, offset, ino, 0); } int -nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name, - int namlen, off_t offset, ino_t ino) +nfs3svc_encode_entry_plus(struct readdir_cd *cd, unsigned char type, + const char *name, int namlen, + off_t offset, ino_t ino) { return encode_entry(cd, name, namlen, offset, ino, 1); } diff -u linux-2.3/fs/nfsd/nfsfh.c.d_type linux-2.3/fs/nfsd/nfsfh.c --- linux-2.3/fs/nfsd/nfsfh.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/nfsd/nfsfh.c Sun Mar 5 21:04:28 2000 @@ -40,8 +40,8 @@ * A rather strange filldir function to capture * the name matching the specified inode number. */ -static int filldir_one(void * __buf, const char * name, int len, - off_t pos, ino_t ino) +static int filldir_one(void * __buf, unsigned char type, + const char * name, int len, off_t pos, ino_t ino) { struct nfsd_getdents_callback *buf = __buf; struct qstr *qs = buf->name; diff -u linux-2.3/fs/nfsd/nfsxdr.c.d_type linux-2.3/fs/nfsd/nfsxdr.c --- linux-2.3/fs/nfsd/nfsxdr.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/nfsd/nfsxdr.c Sun Mar 5 21:04:28 2000 @@ -442,7 +442,7 @@ } int -nfssvc_encode_entry(struct readdir_cd *cd, const char *name, +nfssvc_encode_entry(struct readdir_cd *cd, unsigned char type, const char *name, int namlen, off_t offset, ino_t ino) { u32 *p = cd->buffer; diff -u linux-2.3/fs/ntfs/fs.c.d_type linux-2.3/fs/ntfs/fs.c --- linux-2.3/fs/ntfs/fs.c.d_type Sun Mar 5 21:01:59 2000 +++ linux-2.3/fs/ntfs/fs.c Sun Mar 5 21:04:34 2000 @@ -28,6 +28,7 @@ #include #include #include +#include /* Forward declarations */ static struct inode_operations ntfs_dir_inode_operations; @@ -197,7 +198,7 @@ ntfs_debug(DEBUG_OTHER, "readdir got %s,len %d\n",nf->name,nf->namelen); /* filldir expects an off_t rather than an loff_t. Hope we don't have more than 65535 index records */ - error=nf->filldir(nf->dirent,nf->name,nf->namelen, + error=nf->filldir(nf->dirent,DT_UNKNOWN,nf->name,nf->namelen, (nf->ph<<16)|nf->pl,inum); ntfs_free(nf->name); /* Linux filldir errors are negative, other errors positive */ @@ -224,11 +225,11 @@ 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); + case 0: filldir(dirent,DT_DIR,".",1,filp->f_pos,dir->i_ino); filp->f_pos=0xFFFF0001; return 0; /* FIXME: parent directory */ - case 1: filldir(dirent,"..",2,filp->f_pos,0); + case 1: filldir(dirent,DT_DIR,"..",2,filp->f_pos,0); filp->f_pos=0xFFFF0002; return 0; } diff -u linux-2.3/fs/openpromfs/inode.c.d_type linux-2.3/fs/openpromfs/inode.c --- linux-2.3/fs/openpromfs/inode.c.d_type Sun Mar 5 21:01:59 2000 +++ linux-2.3/fs/openpromfs/inode.c Sun Mar 5 21:04:34 2000 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -754,12 +755,12 @@ i = filp->f_pos; switch (i) { case 0: - if (filldir(dirent, ".", 1, i, ino) < 0) return 0; + if (filldir(dirent, DT_DIR, ".", 1, i, ino) < 0) return 0; i++; filp->f_pos++; /* fall thru */ case 1: - if (filldir(dirent, "..", 2, i, + if (filldir(dirent, DT_DIR, "..", 2, i, (NODE(ino).parent == 0xffff) ? OPENPROM_ROOT_INO : NODE2INO(NODE(ino).parent)) < 0) return 0; @@ -784,7 +785,8 @@ } j = NODEP2INO(NODE(ino).first_prop); if (!i) { - if (filldir(dirent, ".node", 5, filp->f_pos, j) < 0) + if (filldir(dirent, DT_UNKNOWN, ".node", 5, + filp->f_pos, j) < 0) return 0; filp->f_pos++; } else @@ -793,7 +795,8 @@ if (ino == OPENPROM_FIRST_INO + aliases) { for (j++; i < aliases_nodes; i++, j++) { if (alias_names [i]) { - if (filldir (dirent, alias_names [i], + if (filldir (dirent, DT_UNKNOWN, + alias_names [i], strlen (alias_names [i]), filp->f_pos, j) < 0) return 0; filp->f_pos++; @@ -806,7 +809,8 @@ j++; if (i) i--; else { - if (filldir(dirent, p, strlen(p), + if (filldir(dirent, DT_UNKNOWN, + p, strlen(p), filp->f_pos, j) < 0) return 0; filp->f_pos++; diff -u linux-2.3/fs/proc/base.c.d_type linux-2.3/fs/proc/base.c --- linux-2.3/fs/proc/base.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/proc/base.c Sun Mar 5 21:04:34 2000 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -491,12 +492,12 @@ fd = filp->f_pos; switch (fd) { case 0: - if (filldir(dirent, ".", 1, 0, inode->i_ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, 0, inode->i_ino) < 0) goto out; filp->f_pos++; case 1: ino = fake_ino(pid, PROC_PID_INO); - if (filldir(dirent, "..", 2, 1, ino) < 0) + if (filldir(dirent, DT_DIR, "..", 2, 1, ino) < 0) goto out; filp->f_pos++; default: @@ -517,7 +518,7 @@ } while (i); ino = fake_ino(pid, PROC_PID_FD_DIR + fd); - if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0) + if (filldir(dirent, DT_LNK, buf+j, NUMBUF-j, fd+2, ino) < 0) break; } @@ -540,13 +541,13 @@ i = filp->f_pos; switch (i) { case 0: - if (filldir(dirent, ".", 1, i, inode->i_ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, i, inode->i_ino) < 0) return 0; i++; filp->f_pos++; /* fall through */ case 1: - if (filldir(dirent, "..", 2, i, PROC_ROOT_INO) < 0) + if (filldir(dirent, DT_DIR, "..", 2, i, PROC_ROOT_INO) < 0) return 0; i++; filp->f_pos++; @@ -557,7 +558,7 @@ return 1; p = base_stuff + i; while (p->name) { - if (filldir(dirent, p->name, p->len, filp->f_pos, fake_ino(pid, p->type)) < 0) + if (filldir(dirent, IFTODT (p->mode), p->name, p->len, filp->f_pos, fake_ino(pid, p->type)) < 0) return 0; filp->f_pos++; p++; @@ -936,7 +937,7 @@ pid /= 10; } while (pid); - if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino) < 0) + if (filldir(dirent, DT_DIR, buf+j, PROC_NUMBUF-j, filp->f_pos, ino) < 0) break; filp->f_pos++; } diff -u linux-2.3/fs/proc/generic.c.d_type linux-2.3/fs/proc/generic.c --- linux-2.3/fs/proc/generic.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/proc/generic.c Sun Mar 5 21:04:34 2000 @@ -14,6 +14,7 @@ #include #include #include +#include #include static ssize_t proc_file_read(struct file * file, char * buf, @@ -292,13 +293,13 @@ i = filp->f_pos; switch (i) { case 0: - if (filldir(dirent, ".", 1, i, ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, i, ino) < 0) return 0; i++; filp->f_pos++; /* fall through */ case 1: - if (filldir(dirent, "..", 2, i, + if (filldir(dirent, DT_DIR, "..", 2, i, filp->f_dentry->d_parent->d_inode->i_ino ) < 0) return 0; @@ -318,7 +319,7 @@ } do { - if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino) < 0) + if (filldir(dirent, IFTODT (de->mode), de->name, de->namelen, filp->f_pos, de->low_ino) < 0) return 0; filp->f_pos++; de = de->next; diff -u linux-2.3/fs/qnx4/dir.c.d_type linux-2.3/fs/qnx4/dir.c --- linux-2.3/fs/qnx4/dir.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/qnx4/dir.c Sun Mar 5 21:04:34 2000 @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -62,7 +63,7 @@ QNX4_INODES_PER_BLOCK + le->dl_inode_ndx; } - if (filldir(dirent, de->di_fname, size, filp->f_pos, ino) < 0) { + if (filldir(dirent, IFTODT (de->di_mode), de->di_fname, size, filp->f_pos, ino) < 0) { brelse(bh); return 0; } diff -u linux-2.3/fs/readdir.c.d_type linux-2.3/fs/readdir.c --- linux-2.3/fs/readdir.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/readdir.c Sun Mar 5 21:04:34 2000 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -24,22 +25,15 @@ #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1)) -struct old_linux_dirent { - unsigned long d_ino; - unsigned long d_offset; - unsigned short d_namlen; - char d_name[1]; -}; - struct readdir_callback { - struct old_linux_dirent * dirent; + struct readdir_dirent * dirent; int count; }; -static int fillonedir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino) +static int fillonedir(void * __buf, unsigned char type, const char * name, int namlen, off_t offset, ino_t ino) { struct readdir_callback * buf = (struct readdir_callback *) __buf; - struct old_linux_dirent * dirent; + struct readdir_dirent * dirent; if (buf->count) return -EINVAL; @@ -104,26 +98,21 @@ * New, all-improved, singing, dancing, iBCS2-compliant getdents() * interface. */ -struct linux_dirent { - unsigned long d_ino; - unsigned long d_off; - unsigned short d_reclen; - char d_name[1]; -}; - struct getdents_callback { - struct linux_dirent * current_dir; - struct linux_dirent * previous; + struct getdents_dirent * current_dir; + struct getdents_dirent * previous; int count; int error; }; -static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino) +static int filldir(void * __buf, unsigned char type, const char * name, int namlen, off_t offset, ino_t ino) { - struct linux_dirent * dirent; + struct getdents_dirent * dirent; struct getdents_callback * buf = (struct getdents_callback *) __buf; int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); + if (type != DT_UNKNOWN) + reclen += sizeof(long); buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; @@ -136,6 +125,17 @@ put_user(reclen, &dirent->d_reclen); copy_to_user(dirent->d_name, name, namlen); put_user(0, dirent->d_name + namlen); + if (type != DT_UNKNOWN) { + /* + * By storing a 0 at reclen-1-sizeof(long), we clearly + * distinguish this record from one which doesn't have + * a type. It is also binary backward compatible. + */ + put_user(0, (unsigned char *) dirent + reclen - (1 + sizeof (long))); + put_user(type, (unsigned char *) dirent + reclen - 2); + put_user(0, (unsigned char *) dirent + reclen - 1); + } + ((char *) dirent) += reclen; buf->current_dir = dirent; buf->count -= reclen; @@ -147,7 +147,7 @@ struct file * file; struct dentry * dentry; struct inode * inode; - struct linux_dirent * lastdirent; + struct getdents_dirent * lastdirent; struct getdents_callback buf; int error; @@ -165,7 +165,7 @@ if (!inode) goto out_putf; - buf.current_dir = (struct linux_dirent *) dirent; + buf.current_dir = (struct getdents_dirent *) dirent; buf.previous = NULL; buf.count = count; buf.error = 0; diff -u linux-2.3/fs/romfs/inode.c.d_type linux-2.3/fs/romfs/inode.c --- linux-2.3/fs/romfs/inode.c.d_type Sun Mar 5 20:59:03 2000 +++ linux-2.3/fs/romfs/inode.c Sun Mar 5 21:04:34 2000 @@ -73,6 +73,7 @@ #include #include #include +#include #include @@ -273,6 +274,12 @@ return res; } +static mode_t romfs_modemap[] = +{ + 0, S_IFDIR+0644, S_IFREG+0644, S_IFLNK+0777, + S_IFBLK+0600, S_IFCHR+0600, S_IFSOCK+0644, S_IFIFO+0644 +}; + static int romfs_readdir(struct file *filp, void *dirent, filldir_t filldir) { @@ -280,6 +287,7 @@ struct romfs_inode ri; unsigned long offset, maxoff; int j, ino, nextfh; + unsigned char type; int stored = 0; char fsname[ROMFS_MAXFN]; /* XXX dynamic? */ @@ -317,7 +325,8 @@ nextfh = ntohl(ri.next); if ((nextfh & ROMFH_TYPE) == ROMFH_HRD) ino = ntohl(ri.spec); - if (filldir(dirent, fsname, j, offset, ino) < 0) { + type = IFTODT (romfs_modemap [nextfh & ROMFH_TYPE]); + if (filldir(dirent, type, fsname, j, offset, ino) < 0) { return stored; } stored++; @@ -457,12 +466,6 @@ static struct inode_operations romfs_dir_inode_operations = { lookup: romfs_lookup, -}; - -static mode_t romfs_modemap[] = -{ - 0, S_IFDIR+0644, S_IFREG+0644, S_IFLNK+0777, - S_IFBLK+0600, S_IFCHR+0600, S_IFSOCK+0644, S_IFIFO+0644 }; static void diff -u linux-2.3/fs/smbfs/dir.c.d_type linux-2.3/fs/smbfs/dir.c --- linux-2.3/fs/smbfs/dir.c.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/fs/smbfs/dir.c Sun Mar 5 21:04:34 2000 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -88,11 +89,11 @@ switch ((unsigned int) filp->f_pos) { case 0: - if (filldir(dirent, ".", 1, 0, dir->i_ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, 0, dir->i_ino) < 0) goto out_free; filp->f_pos = 1; case 1: - if (filldir(dirent, "..", 2, 1, + if (filldir(dirent, DT_DIR, "..", 2, 1, dentry->d_parent->d_inode->i_ino) < 0) goto out_free; filp->f_pos = 2; @@ -117,7 +118,7 @@ entry->ino = smb_invent_inos(1); } - if (filldir(dirent, entry->name, entry->len, + if (filldir(dirent, DT_UNKNOWN, entry->name, entry->len, filp->f_pos, entry->ino) < 0) break; filp->f_pos += 1; diff -u linux-2.3/fs/sysv/dir.c.d_type linux-2.3/fs/sysv/dir.c --- linux-2.3/fs/sysv/dir.c.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/fs/sysv/dir.c Sun Mar 5 21:04:34 2000 @@ -18,6 +18,7 @@ #include #include #include +#include static int sysv_readdir(struct file *, void *, filldir_t); @@ -61,7 +62,7 @@ inode->i_ino, (off_t) filp->f_pos, sde.inode); i = strnlen(sde.name, SYSV_NAMELEN); - if (filldir(dirent, sde.name, i, filp->f_pos, sde.inode) < 0) { + if (filldir(dirent, DT_UNKNOWN, sde.name, i, filp->f_pos, sde.inode) < 0) { brelse(bh); return 0; } diff -u linux-2.3/fs/udf/dir.c.d_type linux-2.3/fs/udf/dir.c --- linux-2.3/fs/udf/dir.c.d_type Sun Mar 5 21:01:59 2000 +++ linux-2.3/fs/udf/dir.c Sun Mar 5 21:04:37 2000 @@ -40,6 +40,7 @@ #include #include #include +#include #endif /* Prototypes for file operations */ @@ -94,7 +95,7 @@ if ( filp->f_pos == 0 ) { - if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino)) + if (filldir(dirent, DT_DIR, ".", 1, filp->f_pos, dir->i_ino)) return 0; } @@ -111,6 +112,7 @@ struct FileIdentDesc cfi; int block, iblock; loff_t nf_pos = filp->f_pos; + unsigned char ftype; int flen; char fname[255]; char *nameptr; @@ -202,11 +204,15 @@ continue; } + ftype = DT_DIR; + if ( (cfi.fileCharacteristics & FILE_DIRECTORY) == 0 ) + ftype = DT_UNKNOWN; + iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0); if (!lfi) /* parent directory */ { - if (filldir(dirent, "..", 2, filp->f_pos, filp->f_dentry->d_parent->d_inode->i_ino)) + if (filldir(dirent, DT_DIR, "..", 2, filp->f_pos, filp->f_dentry->d_parent->d_inode->i_ino)) { if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); @@ -219,7 +225,7 @@ { if ((flen = udf_get_filename(nameptr, fname, lfi))) { - if (filldir(dirent, fname, flen, filp->f_pos, iblock)) + if (filldir(dirent, ftype, fname, flen, filp->f_pos, iblock)) { if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); diff -u linux-2.3/fs/ufs/dir.c.d_type linux-2.3/fs/ufs/dir.c --- linux-2.3/fs/ufs/dir.c.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/fs/ufs/dir.c Sun Mar 5 21:04:37 2000 @@ -15,6 +15,7 @@ #include #include +#include #include "swab.h" #include "util.h" @@ -125,7 +126,8 @@ UFSD(("filldir(%s,%u)\n", de->d_name, SWAB32(de->d_ino))) UFSD(("namlen %u\n", ufs_get_de_namlen(de))) - error = filldir(dirent, de->d_name, ufs_get_de_namlen(de), + error = filldir(dirent, ufs_get_de_type (de), + de->d_name, ufs_get_de_namlen(de), filp->f_pos, SWAB32(de->d_ino)); if (error) break; diff -u linux-2.3/fs/ufs/util.h.d_type linux-2.3/fs/ufs/util.h --- linux-2.3/fs/ufs/util.h.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/fs/ufs/util.h Sun Mar 5 21:04:37 2000 @@ -126,6 +126,11 @@ ? (de->d_u.d_namlen = SWAB16(value)) \ : (de->d_u.d_44.d_namlen = value)) +#define ufs_get_de_type(de) \ + (((flags & UFS_DE_MASK) == UFS_DE_OLD) \ + ? DT_UNKNOWN \ + : de->d_u.d_44.d_type) + #define ufs_set_de_type(de,mode) _ufs_set_de_type_(de,mode,flags,swab) static inline void _ufs_set_de_type_(struct ufs_dir_entry * de, int mode, unsigned flags, unsigned swab) diff -u linux-2.3/fs/umsdos/dir.c.d_type linux-2.3/fs/umsdos/dir.c --- linux-2.3/fs/umsdos/dir.c.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/fs/umsdos/dir.c Sun Mar 5 21:04:37 2000 @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -66,6 +67,7 @@ */ static int umsdos_dir_once ( void *buf, + unsigned char type, const char *name, int len, off_t offset, @@ -77,7 +79,7 @@ if (d->count == 0) { PRINTK ((KERN_DEBUG "dir_once :%.*s: offset %Ld\n", len, name, offset)); - ret = d->filldir (d->dirbuf, name, len, offset, ino); + ret = d->filldir (d->dirbuf, type, name, len, offset, ino); d->stop = ret < 0; d->count = 1; } @@ -122,7 +124,7 @@ */ Printk ((KERN_WARNING "umsdos_readdir_x: pseudo_root thing UMSDOS_SPECIAL_DIRFPOS\n")); - if (filldir (dirbuf, "DOS", 3, + if (filldir (dirbuf, DT_DIR, "DOS", 3, UMSDOS_SPECIAL_DIRFPOS, UMSDOS_ROOT_INO) == 0) { filp->f_pos++; } @@ -241,7 +243,8 @@ */ if (inode != pseudo_root && (internal_read || !(entry.flags & UMSDOS_HIDDEN))) { - if (filldir (dirbuf, entry.name, entry.name_len, + if (filldir (dirbuf, IFTODT (entry.mode), + entry.name, entry.name_len, cur_f_pos, inode->i_ino) < 0) { new_filp.f_pos = cur_f_pos; } diff -u linux-2.3/fs/umsdos/ioctl.c.d_type linux-2.3/fs/umsdos/ioctl.c --- linux-2.3/fs/umsdos/ioctl.c.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/fs/umsdos/ioctl.c Sun Mar 5 21:04:37 2000 @@ -14,9 +14,10 @@ #include #include #include +#include struct UMSDOS_DIR_ONCE { - struct dirent *ent; + struct getdents_dirent *ent; int count; }; @@ -26,6 +27,7 @@ */ static int umsdos_ioctl_fill ( void *buf, + unsigned char type, const char *name, int name_len, off_t offset, diff -u linux-2.3/fs/umsdos/rdir.c.d_type linux-2.3/fs/umsdos/rdir.c --- linux-2.3/fs/umsdos/rdir.c.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/fs/umsdos/rdir.c Sun Mar 5 21:04:37 2000 @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -30,6 +31,7 @@ }; static int rdir_filldir ( void *buf, + unsigned char type, const char *name, int name_len, off_t offset, @@ -48,11 +50,11 @@ /* Make sure the .. entry points back to the pseudo_root */ ino = pseudo_root->i_ino; } - ret = d->filldir (d->dirbuf, name, name_len, offset, ino); + ret = d->filldir (d->dirbuf, type, name, name_len, offset, ino); } } else { /* Any DOS directory */ - ret = d->filldir (d->dirbuf, name, name_len, offset, ino); + ret = d->filldir (d->dirbuf, type, name, name_len, offset, ino); } return ret; } diff -u linux-2.3/include/linux/dirent.h.d_type linux-2.3/include/linux/dirent.h --- linux-2.3/include/linux/dirent.h.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/include/linux/dirent.h Sun Mar 5 21:04:37 2000 @@ -1,11 +1,66 @@ +/* + * API for reading directories. + * + * Changed dirent types to match what we've always returned + * and DT_* support added by Jamie Lokier, 1999-2000. + */ + #ifndef _LINUX_DIRENT_H #define _LINUX_DIRENT_H -struct dirent { - long d_ino; - __kernel_off_t d_off; +/* + * Structure returned by sys_readdir. + */ +struct readdir_dirent { + unsigned long d_ino; + unsigned long d_offset; + unsigned short d_namlen; + char d_name[256]; /* NAME_MAX + 1. */ +}; + +/* + * Structure returned by sys_getdents. + */ +struct getdents_dirent { + unsigned long d_ino; + unsigned long d_off; unsigned short d_reclen; - char d_name[256]; /* We must not include limits.h! */ + char d_name[256]; /* NAME_MAX + 1. */ }; -#endif +/* + * Backward compatibility (umsdos tools, libc5). + */ +#define dirent getdents_dirent + +/* + * Returns the "d_type" value from a struct getdents_dirent. This is + * backward compatible with older kernels: it will return DT_UNKNOWN. + * It is also forward compatible: more information can be added in future. + */ +#define GETDENTS_DIRENT_D_TYPE(dent) \ + (((dent)->d_reclen > ((dent)->d_name - (char *) (dent) + sizeof (long)) \ + && !*((unsigned char *) (dent) + (dent)->d_reclen - (1 + sizeof (long)))) \ + ? *((unsigned char *) (dent) + (dent)->d_reclen - 2) : DT_UNKNOWN) + +/* + * "d_type" type code. DT_UNKNOWN when no type is available. + * These values are quite standard. + */ +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 + +/* + * Convert to and from S_IFREG etc. + */ +#define DTTOIF(dirtype) ((dirtype) << 12) +#define IFTODT(mode) (((mode) & 0170000) >> 12) + +#endif /* _LINUX_DIRENT_H */ diff -u linux-2.3/include/linux/fs.h.d_type linux-2.3/include/linux/fs.h --- linux-2.3/include/linux/fs.h.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/include/linux/fs.h Sun Mar 5 21:14:39 2000 @@ -640,7 +640,7 @@ * This allows the kernel to read directories into kernel space or * to have different dirent layouts depending on the binary type. */ -typedef int (*filldir_t)(void *, const char *, int, off_t, ino_t); +typedef int (*filldir_t)(void *, unsigned char, const char *, int, off_t, ino_t); struct block_device_operations { int (*open) (struct inode *, struct file *); diff -u linux-2.3/include/linux/iso_fs.h.d_type linux-2.3/include/linux/iso_fs.h --- linux-2.3/include/linux/iso_fs.h.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/include/linux/iso_fs.h Sun Mar 5 21:04:37 2000 @@ -176,7 +176,7 @@ extern int iso_date(char *, int); extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); -extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); +extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *, unsigned char *); extern int find_rock_ridge_relocation(struct iso_directory_record *, struct inode *); diff -u linux-2.3/include/linux/msdos_fs.h.d_type linux-2.3/include/linux/msdos_fs.h --- linux-2.3/include/linux/msdos_fs.h.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/include/linux/msdos_fs.h Sun Mar 5 21:25:03 2000 @@ -85,8 +85,8 @@ /* * ioctl commands */ -#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) -#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) +#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct getdents_dirent [2]) +#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct getdents_dirent [2]) /* * Conversion from and to little-endian byte order. (no-op on i386/i486) diff -u linux-2.3/include/linux/nfsd/nfsd.h.d_type linux-2.3/include/linux/nfsd/nfsd.h --- linux-2.3/include/linux/nfsd/nfsd.h.d_type Sun Mar 5 21:02:06 2000 +++ linux-2.3/include/linux/nfsd/nfsd.h Sun Mar 5 21:04:37 2000 @@ -56,8 +56,8 @@ char eob; /* end of buffer */ char dotonly; }; -typedef int (*encode_dent_fn)(struct readdir_cd *, const char *, - int, off_t, ino_t); +typedef int (*encode_dent_fn)(struct readdir_cd *, unsigned char, + const char *, int, off_t, ino_t); typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); /* diff -u linux-2.3/include/linux/nfsd/xdr.h.d_type linux-2.3/include/linux/nfsd/xdr.h --- linux-2.3/include/linux/nfsd/xdr.h.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/include/linux/nfsd/xdr.h Sun Mar 5 21:04:37 2000 @@ -151,8 +151,8 @@ int nfssvc_encode_statfsres(struct svc_rqst *, u32 *, struct nfsd_statfsres *); int nfssvc_encode_readdirres(struct svc_rqst *, u32 *, struct nfsd_readdirres *); -int nfssvc_encode_entry(struct readdir_cd *, const char *name, - int namlen, off_t offset, ino_t ino); +int nfssvc_encode_entry(struct readdir_cd *, unsigned char type, + const char *name, int namlen, off_t offset, ino_t ino); int nfssvc_release_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *); diff -u linux-2.3/include/linux/nfsd/xdr3.h.d_type linux-2.3/include/linux/nfsd/xdr3.h --- linux-2.3/include/linux/nfsd/xdr3.h.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/include/linux/nfsd/xdr3.h Sun Mar 5 21:04:37 2000 @@ -291,10 +291,12 @@ struct nfsd3_attrstat *); int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *, struct nfsd3_fhandle_pair *); -int nfs3svc_encode_entry(struct readdir_cd *, const char *name, - int namlen, off_t offset, ino_t ino); -int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name, - int namlen, off_t offset, ino_t ino); +int nfs3svc_encode_entry(struct readdir_cd *, unsigned char type, + const char *name, int namlen, + off_t offset, ino_t ino); +int nfs3svc_encode_entry_plus(struct readdir_cd *, unsigned char type, + const char *name, int namlen, + off_t offset, ino_t ino); #endif /* _LINUX_NFSD_XDR3_H */ diff -u linux-2.3/include/linux/umsdos_fs.h.d_type linux-2.3/include/linux/umsdos_fs.h --- linux-2.3/include/linux/umsdos_fs.h.d_type Sun Mar 5 20:59:04 2000 +++ linux-2.3/include/linux/umsdos_fs.h Sun Mar 5 21:25:03 2000 @@ -127,7 +127,7 @@ #define UMSDOS_RENAME_DOS _IO(0x04,220) /* rename a file/directory in the DOS * directory only */ struct umsdos_ioctl { - struct dirent dos_dirent; + struct getdents_dirent dos_dirent; struct umsdos_dirent umsdos_dirent; /* The following structure is used to exchange some data * with utilities (umsdos_progs/util/umsdosio.c). The first