1/* 2 * opendir.c -- 3 * 4 * This file provides dirent-style directory-reading procedures for V7 5 * Unix systems that don't have such procedures. The origin of this code 6 * is unclear, but it seems to have come originally from Larry Wall. 7 * 8 * RCS: @(#) $Id: opendir.c,v 1.4 2007/04/16 13:36:34 dkf Exp $ 9 */ 10 11#include "tclInt.h" 12 13#undef DIRSIZ 14#define DIRSIZ(dp) \ 15 ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3)) 16 17/* 18 * open a directory. 19 */ 20 21DIR * 22opendir( 23 char *name) 24{ 25 register DIR *dirp; 26 register int fd; 27 char *myname; 28 29 myname = ((*name == '\0') ? "." : name); 30 if ((fd = open(myname, 0, 0)) == -1) { 31 return NULL; 32 } 33 dirp = (DIR *) ckalloc(sizeof(DIR)); 34 if (dirp == NULL) { 35 /* unreachable? */ 36 close(fd); 37 return NULL; 38 } 39 dirp->dd_fd = fd; 40 dirp->dd_loc = 0; 41 return dirp; 42} 43 44/* 45 * read an old style directory entry and present it as a new one 46 */ 47#ifndef pyr 48#define ODIRSIZ 14 49 50struct olddirect { 51 ino_t od_ino; 52 char od_name[ODIRSIZ]; 53}; 54#else /* a Pyramid in the ATT universe */ 55#define ODIRSIZ 248 56 57struct olddirect { 58 long od_ino; 59 short od_fill1, od_fill2; 60 char od_name[ODIRSIZ]; 61}; 62#endif 63 64/* 65 * get next entry in a directory. 66 */ 67 68struct dirent * 69readdir( 70 register DIR *dirp) 71{ 72 register struct olddirect *dp; 73 static struct dirent dir; 74 75 for (;;) { 76 if (dirp->dd_loc == 0) { 77 dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ); 78 if (dirp->dd_size <= 0) { 79 return NULL; 80 } 81 } 82 if (dirp->dd_loc >= dirp->dd_size) { 83 dirp->dd_loc = 0; 84 continue; 85 } 86 dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc); 87 dirp->dd_loc += sizeof(struct olddirect); 88 if (dp->od_ino == 0) { 89 continue; 90 } 91 dir.d_ino = dp->od_ino; 92 strncpy(dir.d_name, dp->od_name, ODIRSIZ); 93 dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */ 94 dir.d_namlen = strlen(dir.d_name); 95 dir.d_reclen = DIRSIZ(&dir); 96 return &dir; 97 } 98} 99 100/* 101 * close a directory. 102 */ 103 104void 105closedir( 106 register DIR *dirp) 107{ 108 close(dirp->dd_fd); 109 dirp->dd_fd = -1; 110 dirp->dd_loc = 0; 111 ckfree((char *) dirp); 112} 113