home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / sh / dirent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-15  |  4.8 KB  |  195 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Kenneth Almquist.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)dirent.c    5.1 (Berkeley) 3/7/91";
  39. #endif /* not lint */
  40.  
  41. #include "shell.h"    /* definitions for pointer, NULL, DIRENT, and BSD */
  42.  
  43. #if ! DIRENT
  44.  
  45. #include <errno.h>
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48. #include <fcntl.h>
  49. #include <dirent.h>
  50.  
  51. #ifndef S_ISDIR                /* macro to test for directory file */
  52. #define    S_ISDIR(mode)        (((mode) & S_IFMT) == S_IFDIR)
  53. #endif
  54.  
  55. #ifdef BSD
  56.  
  57. #ifdef __STDC__
  58. int stat(char *, struct stat *);
  59. #else
  60. int stat();
  61. #endif
  62.  
  63.  
  64. /*
  65.  * The BSD opendir routine doesn't check that what is being opened is a
  66.  * directory, so we have to include the check in a wrapper routine.
  67.  */
  68.  
  69. #undef opendir
  70.  
  71. DIR *
  72. myopendir(dirname)
  73.     char *dirname;            /* name of directory */
  74.     {
  75.     struct stat statb;
  76.  
  77.     if (stat(dirname, &statb) != 0 || ! S_ISDIR(statb.st_mode)) {
  78.         errno = ENOTDIR;
  79.         return NULL;        /* not a directory */
  80.     }
  81.     return opendir(dirname);
  82. }
  83.  
  84. #else /* not BSD */
  85.  
  86. /*
  87.  * Dirent routines for old style file systems.
  88.  */
  89.  
  90. #ifdef __STDC__
  91. pointer malloc(unsigned);
  92. void free(pointer);
  93. int open(char *, int, ...);
  94. int close(int);
  95. int fstat(int, struct stat *);
  96. #else
  97. pointer malloc();
  98. void free();
  99. int open();
  100. int close();
  101. int fstat();
  102. #endif
  103.  
  104.  
  105. DIR *
  106. opendir(dirname)
  107.     char        *dirname;    /* name of directory */
  108.     {
  109.     register DIR    *dirp;        /* -> malloc'ed storage */
  110.     register int    fd;        /* file descriptor for read */
  111.     struct stat    statb;        /* result of fstat() */
  112.  
  113. #ifdef O_NDELAY
  114.     fd = open(dirname, O_RDONLY|O_NDELAY);
  115. #else
  116.     fd = open(dirname, O_RDONLY);
  117. #endif
  118.     if (fd < 0)
  119.         return NULL;        /* errno set by open() */
  120.  
  121.     if (fstat(fd, &statb) != 0 || !S_ISDIR(statb.st_mode)) {
  122.         (void)close(fd);
  123.         errno = ENOTDIR;
  124.         return NULL;        /* not a directory */
  125.     }
  126.  
  127.     if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
  128.         (void)close(fd);
  129.         errno = ENOMEM;
  130.         return NULL;        /* not enough memory */
  131.     }
  132.  
  133.     dirp->dd_fd = fd;
  134.     dirp->dd_nleft = 0;        /* refill needed */
  135.  
  136.     return dirp;
  137. }
  138.  
  139.  
  140.  
  141. int
  142. closedir(dirp)
  143.     register DIR *dirp;        /* stream from opendir() */
  144.     {
  145.     register int fd;
  146.  
  147.     if (dirp == NULL) {
  148.         errno = EFAULT;
  149.         return -1;            /* invalid pointer */
  150.     }
  151.  
  152.     fd = dirp->dd_fd;
  153.     free((pointer)dirp);
  154.     return close(fd);
  155. }
  156.  
  157.  
  158.  
  159. struct dirent *
  160. readdir(dirp)
  161.     register DIR *dirp;        /* stream from opendir() */
  162.     {
  163.     register struct direct *dp;
  164.     register char *p, *q;
  165.     register int i;
  166.  
  167.     do {
  168.         if ((dirp->dd_nleft -= sizeof (struct direct)) < 0) {
  169.             if ((i = read(dirp->dd_fd,
  170.                        (char *)dirp->dd_buf,
  171.                        DIRBUFENT*sizeof(struct direct))) <= 0) {
  172.                 if (i == 0)
  173.                     errno = 0;    /* unnecessary */
  174.                 return NULL;        /* EOF or error */
  175.             }
  176.             dirp->dd_loc = dirp->dd_buf;
  177.             dirp->dd_nleft = i - sizeof (struct direct);
  178.         }
  179.         dp = dirp->dd_loc++;
  180.     } while (dp->d_ino == 0);
  181.     dirp->dd_entry.d_ino = dp->d_ino;
  182.  
  183.     /* now copy the name, nul terminating it */
  184.     p = dp->d_name;
  185.     q = dirp->dd_entry.d_name;
  186.     i = DIRSIZ;
  187.     while (--i >= 0 && *p != '\0')
  188.         *q++ = *p++;
  189.     *q = '\0';
  190.     return &dirp->dd_entry;
  191. }
  192.  
  193. #endif /* BSD */
  194. #endif /* DIRENT */
  195.