Annotation of 43BSDReno/contrib/isode-beta/dirent/seekdir.c, revision 1.1.1.1

1.1       root        1: /*
                      2:        seekdir -- reposition a directory stream
                      3: 
                      4:        last edit:      24-May-1987     D A Gwyn
                      5: 
                      6:        An unsuccessful seekdir() will in general alter the current
                      7:        directory position; beware.
                      8: 
                      9:        NOTE:   4.nBSD directory compaction makes seekdir() & telldir()
                     10:                practically impossible to do right.  Avoid using them!
                     11: */
                     12: 
                     13: #include       <sys/errno.h>
                     14: #include       <sys/types.h>
                     15: #include       "usr.dirent.h"
                     16: 
                     17: #ifndef        GETDENTS
                     18: extern off_t   lseek();
                     19: 
                     20: extern int     errno;
                     21: 
                     22: #ifndef NULL
                     23: #define        NULL    0
                     24: #endif
                     25: 
                     26: #ifndef SEEK_SET
                     27: #define        SEEK_SET        0
                     28: #endif
                     29: 
                     30: typedef int    bool;                   /* Boolean data type */
                     31: #define        false   0
                     32: #define        true    1
                     33: 
                     34: void
                     35: seekdir( dirp, loc )
                     36:        register DIR    *dirp;          /* stream from opendir() */
                     37:        register off_t  loc;            /* position from telldir() */
                     38:        {
                     39:        register bool   rewind;         /* "start over when stymied" flag */
                     40: 
                     41:        if ( dirp == NULL || dirp->dd_buf == NULL )
                     42:                {
                     43:                errno = EFAULT;
                     44:                return;                 /* invalid pointer */
                     45:                }
                     46: 
                     47:        /* A (struct dirent)'s d_off is an invented quantity on 4.nBSD
                     48:           NFS-supporting systems, so it is not safe to lseek() to it. */
                     49: 
                     50:        /* Monotonicity of d_off is heavily exploited in the following. */
                     51: 
                     52:        /* This algorithm is tuned for modest directory sizes.  For
                     53:           huge directories, it might be more efficient to read blocks
                     54:           until the first d_off is too large, then back up one block,
                     55:           or even to use binary search on the directory blocks.  I
                     56:           doubt that the extra code for that would be worthwhile. */
                     57: 
                     58:        if ( dirp->dd_loc >= dirp->dd_size      /* invalid index */
                     59:          || ((struct dirent *)&dirp->dd_buf[dirp->dd_loc])->d_off > loc
                     60:                                        /* too far along in buffer */
                     61:           )
                     62:                dirp->dd_loc = 0;       /* reset to beginning of buffer */
                     63:        /* else save time by starting at current dirp->dd_loc */
                     64: 
                     65:        for ( rewind = true; ; )
                     66:                {
                     67:                register struct dirent  *dp;
                     68: 
                     69:                /* See whether the matching entry is in the current buffer. */
                     70: 
                     71:                if ( (dirp->dd_loc < dirp->dd_size      /* valid index */
                     72:                   || readdir( dirp ) != NULL   /* next buffer read */
                     73:                   && (dirp->dd_loc = 0, true)  /* beginning of buffer set */
                     74:                     )
                     75:                  && (dp = (struct dirent *)&dirp->dd_buf[dirp->dd_loc])->d_off
                     76:                        <= loc          /* match possible in this buffer */
                     77:                   )    {
                     78:                        for ( /* dp initialized above */ ;
                     79:                              (char *)dp < &dirp->dd_buf[dirp->dd_size];
                     80:                              dp = (struct dirent *)((char *)dp + dp->d_reclen)
                     81:                            )
                     82:                                if ( dp->d_off == loc )
                     83:                                        {       /* found it! */
                     84:                                        dirp->dd_loc =
                     85:                                                (char *)dp - dirp->dd_buf;
                     86:                                        return;
                     87:                                        }
                     88: 
                     89:                        rewind = false; /* no point in backing up later */
                     90:                        dirp->dd_loc = dirp->dd_size;   /* set end of buffer */
                     91:                        }
                     92:                else                    /* whole buffer past matching entry */
                     93:                        if ( !rewind )
                     94:                                {       /* no point in searching further */
                     95:                                errno = EINVAL;
                     96:                                return; /* no entry at specified loc */
                     97:                                }
                     98:                        else    {       /* rewind directory and start over */
                     99:                                rewind = false; /* but only once! */
                    100: 
                    101:                                dirp->dd_loc = dirp->dd_size = 0;
                    102: 
                    103:                                if ( lseek( dirp->dd_fd, (off_t)0, SEEK_SET )
                    104:                                        != 0
                    105:                                   )
                    106:                                        return; /* errno already set (EBADF) */
                    107: 
                    108:                                if ( loc == 0 )
                    109:                                        return; /* save time */
                    110:                                }
                    111:                }
                    112:        }
                    113: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.