Annotation of coherent/d/usr/lib/ndir/libndir/seekdir.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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