Messages in this thread Patch in this message | | | Date | Sat, 27 Nov 1999 15:43:05 +0100 | From | Jamie Lokier <> | Subject | [PATCH] Updated dirent d_type for 2.3.29 |
| |
This is the dirent d_type patch updated for 2.3.29. A few changes were needed because procfs changed recently.
[ This allows readdir() to return type information in each directory entry. Specifically, whether the entry refers to a file, directory, symbolic link etc. The information is returned without reading the inode. It lets programs like "find", "updatedb" and "tar -g" run faster (with appropriate changes to their code). In some cases, significantly faster. I think d_type was first implemented in BSD4.4. Glibc already provides d_type to user space but currently it always says DT_UNKNOWN. ]
ext2 [FULL SUPPORT, TESTED] isofs/norock [FULL SUPPORT, TESTED] isofs/rock [FULL SUPPORT, TESTED] msdos [FULL SUPPORT, TESTED] vfat [FULL SUPPORT, TESTED] procfs [FULL SUPPORT, TESTED] # Except openpromfs on Sparcs. devpts [FULL SUPPORT, TESTED] autofs [UPDATED, TESTED] # More support may be possible. coda [FULL SUPPORT, not tested] ncpfs [FULL SUPPORT, not tested] qnx4 [FULL SUPPORT, not tested] romfs [FULL SUPPORT, not tested] ufs [FULL SUPPORT, not tested] umsdos [FULL SUPPORT, tried to test] # umsdos was broken already adfs [UPDATED, not tested] # Only . and .. possible. affs [UPDATED, not tested] # More support may be possible. bfs [UPDATED, not tested] # No support possible. efs [UPDATED, not tested] # No support possible. hfs [LIMITED, not tested] # More support may be possible. hpfs [DIR® ONLY, not tested] # More support may be possible. minix [UPDATED, not tested] # No support possible. nfs [UPDATED, not tested] # No support possible. nfsd [UPDATED, not tested] # Updated for readdir change. ntfs [UPDATED, not tested] # Code too scary to add support. smbfs [UPDATED, not tested] # More support may be possible. sysv [UPDATED, not tested] # No support possible. udf [DIR ONLY, not tested] # More support may be possible.
Let me know what you think.
Enjoy, -- Jamie
ps. There is available a different, much smaller patch which can also optimise "find /" type operations (but not "find . -type f"). It optimises O_DIRECTORY|O_NOFOLLOW opens. That patch might be interesting for 2.2.x.
---------- start of patch ----------
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 Sat Nov 27 01:14:36 1999 +++ linux-2.3/fs/adfs/dir.c Sat Nov 27 12:19:13 1999 @@ -9,6 +9,7 @@ #include <linux/adfs_fs.h> #include <linux/sched.h> #include <linux/stat.h> +#include <linux/dirent.h> static ssize_t adfs_dirread (struct file *filp, char *buf, size_t siz, loff_t *ppos) @@ -322,12 +323,13 @@ if (filp->f_pos < 2) { if (filp->f_pos < 1) { - 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 ++; } - if (filldir (dirent, "..", 2, 1, - adfs_inode_generate (parent_object_id, 0)) < 0) + if (filldir (dirent, DT_DIR, "..", 2, + 1, adfs_inode_generate (parent_object_id, 0)) < 0) return 0; filp->f_pos ++; } @@ -339,7 +341,8 @@ if (!adfs_dir_get (sb, bh, buffers, pos, dir_object_id, &ide)) break; - if (filldir (dirent, ide.name, ide.name_len, filp->f_pos, ide.inode_no) < 0) + if (filldir (dirent, DT_UNKNOWN, ide.name, ide.name_len, + filp->f_pos, ide.inode_no) < 0) return 0; filp->f_pos ++; pos += 26; 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 Sat Nov 27 01:14:36 1999 +++ linux-2.3/fs/affs/dir.c Sat Nov 27 12:19:13 1999 @@ -23,6 +23,7 @@ #include <linux/string.h> #include <linux/mm.h> #include <linux/amigaffs.h> +#include <linux/dirent.h> static int affs_readdir(struct file *, void *, filldir_t); static ssize_t affs_dir_read(struct file *, char *, size_t, loff_t *); @@ -98,14 +99,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; @@ -161,7 +162,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 Sat Nov 27 01:14:36 1999 +++ linux-2.3/fs/autofs/dir.c Sat Nov 27 12:19:13 1999 @@ -11,6 +11,7 @@ * ------------------------------------------------------------------------- */ #include "autofs_i.h" +#include <linux/dirent.h> static int autofs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) @@ -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 Sat Nov 27 01:14:36 1999 +++ linux-2.3/fs/autofs/root.c Sat Nov 27 12:19:13 1999 @@ -14,6 +14,7 @@ #include <linux/stat.h> #include <linux/param.h> #include "autofs_i.h" +#include <linux/dirent.h> static int autofs_root_readdir(struct file *,void *,filldir_t); static struct dentry *autofs_root_lookup(struct inode *,struct dentry *); @@ -79,19 +80,19 @@ 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) + if (filldir(dirent,DT_UNKNOWN,ent->name,ent->len,onr,ent->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 Sat Nov 27 01:14:36 1999 +++ linux-2.3/fs/bfs/dir.c Sat Nov 27 12:19:13 1999 @@ -8,6 +8,7 @@ #include <linux/string.h> #include <linux/bfs_fs.h> #include <linux/locks.h> +#include <linux/dirent.h> #include "bfs_defs.h" @@ -61,7 +62,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 Sat Nov 27 01:14:36 1999 +++ linux-2.3/fs/coda/dir.c Sat Nov 27 12:19:13 1999 @@ -18,6 +18,7 @@ #include <asm/segment.h> #include <asm/uaccess.h> #include <linux/string.h> +#include <linux/dirent.h> #include <linux/coda.h> #include <linux/coda_linux.h> @@ -737,12 +738,14 @@ /* if we don't have a null entry, copy it */ if ( vdirent->d_fileno && vdirent->d_reclen ) { - int namlen = vdirent->d_namlen; - off_t offs = filp->f_pos; - ino_t ino = vdirent->d_fileno; - char *name = vdirent->d_name; + int namlen = vdirent->d_namlen; + 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/devpts/root.c.d_type linux-2.3/fs/devpts/root.c --- linux-2.3/fs/devpts/root.c.d_type Sat Nov 27 01:14:36 1999 +++ linux-2.3/fs/devpts/root.c Sat Nov 27 12:19:13 1999 @@ -14,6 +14,7 @@ #include <linux/stat.h> #include <linux/param.h> #include <linux/string.h> +#include <linux/dirent.h> #include "devpts_i.h" static int devpts_root_readdir(struct file *,void *,filldir_t); @@ -86,12 +87,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 */ @@ -100,7 +101,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 Sat Nov 27 01:14:36 1999 +++ linux-2.3/fs/efs/dir.c Sat Nov 27 12:19:13 1999 @@ -5,6 +5,7 @@ */ #include <linux/efs_fs.h> +#include <linux/dirent.h> static int efs_readdir(struct file *, void *, filldir_t); @@ -111,7 +112,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 Sat Nov 27 01:14:36 1999 +++ linux-2.3/fs/ext2/dir.c Sat Nov 27 12:19:13 1999 @@ -20,6 +20,7 @@ #include <linux/module.h> #include <linux/fs.h> +#include <linux/dirent.h> @@ -102,6 +103,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) { @@ -197,9 +209,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/ext2/namei.c.d_type linux-2.3/fs/ext2/namei.c --- linux-2.3/fs/ext2/namei.c.d_type Sat Nov 27 01:14:43 1999 +++ linux-2.3/fs/ext2/namei.c Sat Nov 27 12:19:13 1999 @@ -346,18 +346,20 @@ umode_t mode) { if (!EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE)) return; - if (S_ISCHR(mode)) + if (S_ISREG(mode)) + de->file_type = EXT2_FT_REG_FILE; + else if (S_ISDIR(mode)) + de->file_type = EXT2_FT_DIR; + else if (S_ISLNK(mode)) + de->file_type = EXT2_FT_SYMLINK; + else if (S_ISSOCK(mode)) + de->file_type = EXT2_FT_SOCK; + else if (S_ISFIFO(mode)) + de->file_type = EXT2_FT_FIFO; + else if (S_ISCHR(mode)) de->file_type = EXT2_FT_CHRDEV; else if (S_ISBLK(mode)) de->file_type = EXT2_FT_BLKDEV; - else if (S_ISFIFO(mode)) - de->file_type = EXT2_FT_FIFO; - else if (S_ISLNK(mode)) - de->file_type = EXT2_FT_SYMLINK; - else if (S_ISREG(mode)) - de->file_type = EXT2_FT_REG_FILE; - else if (S_ISDIR(mode)) - de->file_type = EXT2_FT_DIR; } /* 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 Sat Nov 27 01:14:36 1999 +++ linux-2.3/fs/fat/dir.c Sat Nov 27 12:19:13 1999 @@ -297,12 +297,13 @@ int dotoffset = 0; unsigned long *furrfu = &lpos; unsigned long dummy; + unsigned char type; cpos = filp->f_pos; /* 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++; @@ -427,6 +428,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; @@ -445,7 +450,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]; @@ -456,7 +461,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; } @@ -483,13 +489,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; @@ -541,8 +548,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); @@ -550,9 +558,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/hfs/dir_cap.c Sat Nov 27 12:19:13 1999 @@ -24,6 +24,7 @@ #include <linux/hfs_fs_sb.h> #include <linux/hfs_fs_i.h> #include <linux/hfs_fs.h> +#include <linux/dirent.h> /*================ Forward declarations ================*/ @@ -249,7 +250,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; @@ -265,7 +266,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; } @@ -292,7 +293,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; @@ -307,7 +308,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; @@ -319,7 +320,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; @@ -331,7 +332,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/hfs/dir_dbl.c Sat Nov 27 12:19:13 1999 @@ -20,6 +20,7 @@ #include <linux/hfs_fs_sb.h> #include <linux/hfs_fs_i.h> #include <linux/hfs_fs.h> +#include <linux/dirent.h> /*================ Forward declarations ================*/ @@ -207,7 +208,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; @@ -215,7 +216,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; } @@ -253,7 +254,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; } @@ -265,7 +266,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/hfs/dir_nat.c Sat Nov 27 12:19:13 1999 @@ -26,6 +26,7 @@ #include <linux/hfs_fs_sb.h> #include <linux/hfs_fs_i.h> #include <linux/hfs_fs.h> +#include <linux/dirent.h> /*================ Forward declarations ================*/ @@ -231,7 +232,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; @@ -247,8 +249,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; @@ -274,7 +276,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; @@ -288,14 +290,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; @@ -308,7 +310,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/hpfs/dir.c Sat Nov 27 12:19:13 1999 @@ -7,6 +7,7 @@ */ #include "hpfs_fn.h" +#include <linux/dirent.h> int hpfs_dir_read(struct file *filp, char *name, size_t len, loff_t *loff) { @@ -109,14 +110,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; } @@ -145,7 +146,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/isofs/dir.c Sat Nov 27 12:19:13 1999 @@ -21,6 +21,7 @@ #include <linux/sched.h> #include <linux/locks.h> #include <linux/config.h> +#include <linux/dirent.h> #include <asm/uaccess.h> @@ -139,6 +140,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; @@ -218,7 +220,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; @@ -229,7 +231,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; @@ -246,8 +248,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; @@ -274,7 +277,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/isofs/namei.c Sat Nov 27 12:19:13 1999 @@ -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 Sat Nov 27 01:15:23 1999 +++ linux-2.3/fs/isofs/rock.c Sat Nov 27 12:19:13 1999 @@ -12,15 +12,16 @@ #include <linux/string.h> #include <linux/mm.h> #include <linux/malloc.h> +#include <linux/dirent.h> #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) @@ -151,7 +152,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; @@ -214,6 +216,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/minix/dir.c Sat Nov 27 12:19:13 1999 @@ -11,6 +11,7 @@ #include <linux/fs.h> #include <linux/minix_fs.h> #include <linux/stat.h> +#include <linux/dirent.h> #include <asm/uaccess.h> @@ -85,7 +86,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 Sat Nov 27 02:01:07 1999 +++ linux-2.3/fs/ncpfs/dir.c Sat Nov 27 12:19:13 1999 @@ -21,6 +21,7 @@ #include <asm/uaccess.h> #include <asm/byteorder.h> #include <linux/locks.h> +#include <linux/dirent.h> #include <linux/ncp_fs.h> @@ -507,12 +508,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; @@ -563,9 +564,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; @@ -642,6 +643,7 @@ struct ncp_cache_control ctl = *ctrl; struct qstr qname; ino_t ino = 0; + unsigned char type = DT_UNKNOWN; int valid = 0; vol2io(server, entry->i.entryName, @@ -678,6 +680,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); } @@ -710,7 +713,7 @@ ino = find_inode_number(dentry, &qname); if (!ino) ino = iunique(inode->i_sb, 2); - ctl.filled = filldir(dirent, entry->i.entryName, + ctl.filled = filldir(dirent, type, entry->i.entryName, entry->i.nameLen, 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 Sat Nov 27 02:01:07 1999 +++ linux-2.3/fs/nfs/dir.c Sat Nov 27 12:19:13 1999 @@ -30,6 +30,7 @@ #include <linux/nfs_fs.h> #include <linux/nfs.h> #include <linux/pagemap.h> +#include <linux/dirent.h> #include <asm/segment.h> /* for fs functions */ @@ -402,7 +403,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/nfsd/nfs3xdr.c Sat Nov 27 12:19:13 1999 @@ -635,7 +635,7 @@ #define NFS3_ENTRYPLUS_BAGGAGE ((1 + 20 + 1 + NFS3_FHSIZE) << 2) int -nfs3svc_encode_entry(struct readdir_cd *cd, const char *name, +nfs3svc_encode_entry(struct readdir_cd *cd, unsigned char type, const char *name, int namlen, unsigned long offset, ino_t ino) { u32 *p = cd->buffer; 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 Sat Nov 27 02:01:07 1999 +++ linux-2.3/fs/nfsd/nfsfh.c Sat Nov 27 12:19:13 1999 @@ -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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/nfsd/nfsxdr.c Sat Nov 27 12:19:13 1999 @@ -423,7 +423,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/ntfs/fs.c Sat Nov 27 12:19:13 1999 @@ -28,6 +28,7 @@ #include <linux/nls.h> #include <linux/locks.h> #include <linux/init.h> +#include <linux/dirent.h> /* 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/proc/base.c.d_type linux-2.3/fs/proc/base.c --- linux-2.3/fs/proc/base.c.d_type Sat Nov 27 01:15:23 1999 +++ linux-2.3/fs/proc/base.c Sat Nov 27 14:06:26 1999 @@ -20,6 +20,7 @@ #include <linux/sched.h> #include <linux/proc_fs.h> #include <linux/stat.h> +#include <linux/dirent.h> #include <linux/init.h> #include <linux/file.h> @@ -546,12 +547,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: @@ -572,7 +573,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; } @@ -595,13 +596,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++; @@ -612,7 +613,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++; @@ -1015,7 +1016,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 Sat Nov 27 02:01:07 1999 +++ linux-2.3/fs/proc/generic.c Sat Nov 27 13:47:17 1999 @@ -14,6 +14,7 @@ #include <linux/sched.h> #include <linux/proc_fs.h> #include <linux/stat.h> +#include <linux/dirent.h> #include <asm/bitops.h> static ssize_t proc_file_read(struct file * file, char * buf, @@ -315,13 +316,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; @@ -341,7 +342,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/proc/openpromfs.c.d_type linux-2.3/fs/proc/openpromfs.c --- linux-2.3/fs/proc/openpromfs.c.d_type Sat Nov 27 02:01:07 1999 +++ linux-2.3/fs/proc/openpromfs.c Sat Nov 27 12:19:13 1999 @@ -11,6 +11,7 @@ #include <linux/fs.h> #include <linux/proc_fs.h> #include <linux/init.h> +#include <linux/dirent.h> #include <asm/openprom.h> #include <asm/oplib.h> @@ -852,12 +853,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) ? PROC_ROOT_INO : NODE2INO(NODE(ino).parent)) < 0) return 0; @@ -874,7 +875,7 @@ while (node != 0xffff) { if (prom_getname (nodes[node].node, buffer, 128) < 0) return 0; - if (filldir(dirent, buffer, strlen(buffer), + if (filldir(dirent, DT_UNKNOWN, buffer, strlen(buffer), filp->f_pos, NODE2INO(node)) < 0) return 0; filp->f_pos++; @@ -882,7 +883,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 @@ -891,9 +893,11 @@ if (ino == PROC_OPENPROM_FIRST + aliases) { for (j++; i < aliases_nodes; i++, j++) { if (alias_names [i]) { - if (filldir (dirent, alias_names [i], - strlen (alias_names [i]), - filp->f_pos, j) < 0) return 0; + if (filldir (dirent, DT_UNKNOWN, + alias_names [i], + strlen (alias_names [i]), + filp->f_pos, j) < 0) + return 0; filp->f_pos++; } } @@ -904,7 +908,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++; @@ -915,8 +920,8 @@ if (d->node == n) { if (i) i--; else { - if (filldir(dirent, d->name, - strlen(d->name), + if (filldir(dirent, DT_UNKNOWN, + d->name, strlen(d->name), filp->f_pos, d->inode) < 0) return 0; filp->f_pos++; 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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/qnx4/dir.c Sat Nov 27 12:19:13 1999 @@ -17,6 +17,7 @@ #include <linux/fs.h> #include <linux/qnx4_fs.h> #include <linux/stat.h> +#include <linux/dirent.h> #include <asm/segment.h> @@ -57,7 +58,7 @@ if ((de->di_mode) || (de->di_status == QNX4_FILE_LINK)) { if (de->di_status) { - if (filldir(dirent, de->di_fname, size, filp->f_pos, de->di_first_xtnt.xtnt_blk) < 0) { + if (filldir(dirent, IFTODT (de->di_mode), de->di_fname, size, filp->f_pos, de->di_first_xtnt.xtnt_blk) < 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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/readdir.c Sat Nov 27 12:19:13 1999 @@ -9,6 +9,7 @@ #include <linux/errno.h> #include <linux/stat.h> #include <linux/file.h> +#include <linux/dirent.h> #include <linux/smp_lock.h> #include <asm/uaccess.h> @@ -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,16 @@ put_user(reclen, &dirent->d_reclen); copy_to_user(dirent->d_name, name, namlen); put_user(0, dirent->d_name + namlen); + /* + * This, plus adding sizeof(long) to reclen, allows d_type to be + * included in a backward & forward compatible way. + */ + if (type != DT_UNKNOWN) { + 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 +146,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 +164,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 Sat Nov 27 01:15:11 1999 +++ linux-2.3/fs/romfs/inode.c Sat Nov 27 12:19:13 1999 @@ -73,6 +73,7 @@ #include <linux/locks.h> #include <linux/init.h> #include <linux/smp_lock.h> +#include <linux/dirent.h> #include <asm/uaccess.h> @@ -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++; @@ -609,12 +618,6 @@ NULL, /* permission */ NULL, /* smap */ NULL /* revalidate */ -}; - -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 struct inode_operations *romfs_inoops[] = 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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/smbfs/dir.c Sat Nov 27 12:19:13 1999 @@ -9,6 +9,7 @@ #include <linux/sched.h> #include <linux/errno.h> #include <linux/kernel.h> +#include <linux/dirent.h> #include <linux/smb_fs.h> #include <linux/smbno.h> @@ -114,11 +115,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; @@ -143,7 +144,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/sysv/dir.c Sat Nov 27 12:19:13 1999 @@ -18,6 +18,7 @@ #include <linux/sysv_fs.h> #include <linux/stat.h> #include <linux/string.h> +#include <linux/dirent.h> #include <asm/uaccess.h> @@ -103,7 +104,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 Sat Nov 27 02:01:08 1999 +++ linux-2.3/fs/udf/dir.c Sat Nov 27 13:28:55 1999 @@ -41,6 +41,7 @@ #include <linux/mm.h> #include <linux/malloc.h> #include <linux/udf_fs.h> +#include <linux/dirent.h> #endif /* Prototypes for file operations */ @@ -143,7 +144,7 @@ if ( filp->f_pos == 0 ) { - if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino) < 0) + if (filldir(dirent, DT_DIR, ".", 1, filp->f_pos, dir->i_ino) < 0) return 0; } @@ -160,6 +161,7 @@ struct FileIdentDesc cfi; int block, iblock; loff_t nf_pos = filp->f_pos; + unsigned char ftype; int flen; char fname[255]; char *nameptr; @@ -251,11 +253,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) < 0) + if (filldir(dirent, DT_DIR, "..", 2, filp->f_pos, filp->f_dentry->d_parent->d_inode->i_ino) < 0) { if (fibh.sbh != fibh.ebh) udf_release_data(fibh.ebh); @@ -268,7 +274,7 @@ { if ((flen = udf_get_filename(nameptr, fname, lfi))) { - if (filldir(dirent, fname, flen, filp->f_pos, iblock) < 0) + if (filldir(dirent, ftype, fname, flen, filp->f_pos, iblock) < 0) { 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 Sat Nov 27 01:15:11 1999 +++ linux-2.3/fs/ufs/dir.c Sat Nov 27 12:19:13 1999 @@ -15,6 +15,7 @@ #include <linux/fs.h> #include <linux/ufs_fs.h> +#include <linux/dirent.h> #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 Sat Nov 27 01:15:11 1999 +++ linux-2.3/fs/ufs/util.h Sat Nov 27 12:19:13 1999 @@ -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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/umsdos/dir.c Sat Nov 27 12:19:13 1999 @@ -16,6 +16,7 @@ #include <linux/limits.h> #include <linux/umsdos_fs.h> #include <linux/malloc.h> +#include <linux/dirent.h> #include <asm/uaccess.h> @@ -79,6 +80,7 @@ */ static int umsdos_dir_once ( void *buf, + unsigned char type, const char *name, int len, off_t offset, @@ -90,7 +92,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; } @@ -135,7 +137,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++; } @@ -254,7 +256,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/umsdos/ioctl.c Sat Nov 27 12:19:13 1999 @@ -14,9 +14,10 @@ #include <linux/fs.h> #include <linux/msdos_fs.h> #include <linux/umsdos_fs.h> +#include <linux/dirent.h> 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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/fs/umsdos/rdir.c Sat Nov 27 12:19:13 1999 @@ -15,6 +15,7 @@ #include <linux/limits.h> #include <linux/umsdos_fs.h> #include <linux/malloc.h> +#include <linux/dirent.h> #include <asm/uaccess.h> @@ -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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/include/linux/dirent.h Sat Nov 27 12:19:13 1999 @@ -1,11 +1,64 @@ +/* + * API for directory reading system calls. + * Copyright (C) 1999 Jamie Lokier. + */ + #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. This may go away. + */ +#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. + * Must match Glibc values. These 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 Sat Nov 27 02:01:10 1999 +++ linux-2.3/include/linux/fs.h Sat Nov 27 14:01:05 1999 @@ -600,7 +600,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 file_operations { loff_t (*llseek) (struct file *, loff_t, int); 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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/include/linux/iso_fs.h Sat Nov 27 12:19:13 1999 @@ -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 char * get_rock_ridge_symlink(struct inode *); 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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/include/linux/msdos_fs.h Sat Nov 27 14:07:15 1999 @@ -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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/include/linux/nfsd/nfsd.h Sat Nov 27 12:19:14 1999 @@ -53,8 +53,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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/include/linux/nfsd/xdr.h Sat Nov 27 12:19:14 1999 @@ -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 Sat Nov 27 01:14:37 1999 +++ linux-2.3/include/linux/nfsd/xdr3.h Sat Nov 27 12:19:14 1999 @@ -262,7 +262,8 @@ struct nfsd_fhandle *); int nfs3svc_release_fhandle2(struct svc_rqst *, u32 *, struct nfsd3_fhandle2 *); -int nfs3svc_encode_entry(struct readdir_cd *, const char *name, - int namlen, unsigned long offset, ino_t ino); +int nfs3svc_encode_entry(struct readdir_cd *, unsigned char type, + const char *name, int namlen, + unsigned long 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 Sat Nov 27 01:14:38 1999 +++ linux-2.3/include/linux/umsdos_fs.h Sat Nov 27 14:07:15 1999 @@ -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 ---------- end of patch ---------- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |