directory.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:8k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  * This product includes software developed by the University of
  16.  * California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33. #if defined(LIBC_SCCS) && !defined(lint)
  34. static char sccsid[] = "@(#)closedir.c 5.9 (Berkeley) 2/23/91";
  35. #endif /* LIBC_SCCS and not lint */
  36. /*
  37.  * One of these structures is malloced to describe the current directory
  38.  * position each time telldir is called. It records the current magic 
  39.  * cookie returned by getdirentries and the offset within the buffer
  40.  * associated with that return value.
  41.  */
  42. struct ddloc {
  43. struct ddloc *loc_next;/* next structure in list */
  44. long loc_index; /* key associated with structure */
  45. long loc_seek; /* magic cookie returned by getdirentries */
  46. long loc_loc; /* offset of entry in buffer */
  47. };
  48. static long dd_loccnt = 0; /* Index of entry for sequential telldir's */
  49. #include <errno.h>
  50. #include <pthread.h>
  51. #include <sys/types.h>
  52. #include <sys/param.h>
  53. #include <dirent.h>
  54. #include <stdlib.h>
  55. #include <unistd.h>
  56. #include <fcntl.h>
  57. #include <string.h>
  58. /*
  59.  * close a directory.
  60.  */
  61. int closedir(DIR * dirp)
  62. {
  63. void *ptr, *nextptr;
  64. int fd;
  65. pthread_mutex_lock (dirp->dd_lock);
  66. fd = dirp->dd_fd;
  67. dirp->dd_fd = -1;
  68. dirp->dd_loc = 0;
  69. for (ptr = (void *)dirp->dd_ddloc; ptr; ptr = nextptr) {
  70. nextptr = (void *)(((struct ddloc *)ptr)->loc_next);
  71. free(ptr);
  72. }
  73. for (ptr = (void *)dirp->dd_dp; ptr; ptr = nextptr) {
  74. nextptr = (void *)(((struct __dirent *)ptr)->next);
  75. free(ptr);
  76. }
  77. free((void *)dirp->dd_buf);
  78. free (dirp->dd_lock);
  79. free((void *)dirp);
  80. return(machdep_sys_close(fd));
  81. }
  82. /*
  83.  * open a directory.
  84.  */
  85. DIR * opendir(const char * name)
  86. {
  87. DIR *dirp;
  88. int fd;
  89. if ((fd = machdep_sys_open(name, 0)) < 0)
  90. return NULL;
  91. if (machdep_sys_fcntl(fd, F_SETFD, 1) < 0 ||
  92.     (dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
  93. machdep_sys_close (fd);
  94. return NULL;
  95. }
  96. dirp->dd_lock = (pthread_mutex_t*) malloc (sizeof (pthread_mutex_t));
  97. pthread_mutex_init (dirp->dd_lock, 0);
  98. /*
  99.  * If CLSIZE is an exact multiple of DIRBLKSIZ, use a CLSIZE
  100.  * buffer that it cluster boundary aligned.
  101.  * Hopefully this can be a big win someday by allowing page trades
  102.  * to user space to be done by getdirentries()
  103.  */
  104. #ifndef CLSIZE
  105. #define CLSIZE 1
  106. #endif
  107. if ((CLSIZE % DIRBLKSIZ) == 0) {
  108. dirp->dd_buf = malloc(CLSIZE);
  109. dirp->dd_len = CLSIZE;
  110. } else {
  111. dirp->dd_buf = malloc(DIRBLKSIZ);
  112. dirp->dd_len = DIRBLKSIZ;
  113. }
  114. if (dirp->dd_buf == NULL) {
  115. machdep_sys_close (fd);
  116. free((void *)dirp);
  117. return NULL;
  118. }
  119. dirp->dd_ddloc = NULL;
  120. dirp->dd_dp = NULL;
  121. dirp->dd_seek = 0;
  122. dirp->dd_loc = 0;
  123. dirp->dd_fd = fd;
  124. return(dirp);
  125. }
  126. /*
  127.  * The real work in gettint the next entry in a directory.
  128.  * Return
  129.  * NULL on End of directory
  130.  * &ERR on Error
  131.  * dp on valid directory;
  132.  */
  133. static struct dirent ERR;
  134. static struct dirent * readdir_basic(DIR * dirp)
  135. {
  136. register struct dirent *dp;
  137. for (;;) {
  138. if (dirp->dd_loc == 0) {
  139. dirp->dd_size = machdep_sys_getdirentries(dirp->dd_fd,
  140.     dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
  141. if (dirp->dd_size < 0)
  142. return(&ERR);
  143. if (dirp->dd_size == 0)
  144. return(NULL);
  145. }
  146. if (dirp->dd_loc >= dirp->dd_size) {
  147. dirp->dd_loc = 0;
  148. continue;
  149. }
  150. dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
  151. if ((long)dp & 03) /* bogus pointer check */
  152. return(&ERR);
  153. if (dp->d_reclen <= 0 ||
  154.     dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
  155. return(&ERR);
  156. dirp->dd_loc += dp->d_reclen;
  157. if (dp->d_ino == 0)
  158. continue;
  159. return(dp);
  160. }
  161. }
  162. /*
  163.  * POSIX.1 version of getting the next entry in a directory.
  164.  */
  165. struct dirent * readdir(DIR * dirp)
  166. {
  167. register struct dirent * rp;
  168. struct __dirent * my__dp;
  169. pthread_t self;
  170. pthread_mutex_lock (dirp->dd_lock);
  171. self = pthread_self();
  172. /* Allocate space and return */
  173. for (my__dp = dirp->dd_dp; my__dp; my__dp = my__dp->next) {
  174. if (pthread_equal(my__dp->owner, self)) {
  175. break;
  176. }
  177. }
  178. if (my__dp == NULL) {
  179. if (my__dp = (struct __dirent *)(malloc(sizeof(struct __dirent)))) {
  180. my__dp->next = dirp->dd_dp;
  181. dirp->dd_dp = my__dp;
  182. my__dp->owner = self;
  183. } else {
  184. pthread_mutex_unlock (dirp->dd_lock);
  185. return(NULL);
  186. }
  187. }
  188. if (rp = readdir_basic(dirp)) {
  189. if (rp != &ERR) {
  190. memcpy(& (my__dp->data), rp, sizeof(struct dirent));
  191. rp = & (my__dp->data);
  192. } else {
  193. rp = NULL;
  194. }
  195. }
  196. pthread_mutex_unlock (dirp->dd_lock);
  197. return(rp);
  198. }
  199. /*
  200.  * POSIX.4a version of getting the next entry in a directory.
  201.  */
  202. int readdir_r(DIR * dirp, struct dirent * entry, struct dirent ** result)
  203. {
  204. register struct dirent * rp;
  205. int ret;
  206. pthread_mutex_lock (dirp->dd_lock);
  207. rp = readdir_basic(dirp);
  208. if (rp != &ERR) {
  209. if (rp) {
  210. memcpy(entry, rp, sizeof(struct dirent));
  211. *result = entry;
  212. ret = 0;
  213. } else {
  214. *result = NULL;
  215. ret = 0;
  216. }
  217. } else {
  218. /* Should get it from errno */
  219. ret = EBADF;
  220. }
  221. pthread_mutex_unlock (dirp->dd_lock);
  222. return(ret);
  223. }
  224. void rewinddir(DIR * dirp)
  225. {
  226. pthread_mutex_lock (dirp->dd_lock);
  227. (void)machdep_sys_lseek(dirp->dd_fd, 0, 0);
  228. dirp->dd_seek = 0;
  229. dirp->dd_loc = 0;
  230. pthread_mutex_unlock (dirp->dd_lock);
  231. }
  232. /*
  233.  * Seek to an entry in a directory.
  234.  * _seekdir is in telldir.c so that it can share opaque data structures.
  235.  *
  236.  * Use the POSIX reentrant safe readdir_r to simplify varifying POSIX
  237.  * thread-safe compliance.
  238.  */
  239. void seekdir(DIR * dirp, long loc)
  240. {
  241.   register struct ddloc ** prevlp;
  242.   register struct ddloc * lp;
  243.   struct dirent * dp;
  244.   struct dirent   de;
  245.   pthread_mutex_lock (dirp->dd_lock);
  246.   prevlp = (struct ddloc **)&(dirp->dd_ddloc);
  247.   lp = *prevlp;
  248.   while (lp != NULL) {
  249.     if (lp->loc_index == loc)
  250.       break;
  251.     prevlp = &lp->loc_next;
  252.     lp = lp->loc_next;
  253.   }
  254.   if (lp) {
  255.     if (lp->loc_seek != dirp->dd_seek) {
  256.       if (machdep_sys_lseek(dirp->dd_fd, lp->loc_seek, 0) < 0) {
  257. *prevlp = lp->loc_next;
  258. pthread_mutex_unlock (dirp->dd_lock);
  259. return;
  260.       }
  261.       dirp->dd_seek = lp->loc_seek;
  262.       dirp->dd_loc = 0;
  263.       while (dirp->dd_loc < lp->loc_loc) {
  264. if (readdir_r(dirp, &de, &dp)) {
  265.   *prevlp = lp->loc_next;
  266.   break;
  267. }
  268.       }
  269.     }
  270.   }
  271.   pthread_mutex_unlock (dirp->dd_lock);
  272. }
  273. /*
  274.  * return a pointer into a directory
  275.  */
  276. long telldir(DIR *dirp)
  277. {
  278. struct ddloc *lp, **fakeout;
  279. int ret;
  280. pthread_mutex_lock (dirp->dd_lock);
  281. if (lp = (struct ddloc *)malloc(sizeof(struct ddloc))) {
  282. lp->loc_index = dd_loccnt++;
  283. lp->loc_seek = dirp->dd_seek;
  284. lp->loc_loc = dirp->dd_loc;
  285. lp->loc_next = dirp->dd_ddloc;
  286. /* Compiler won't let us change anything pointed to by db directly */
  287. /* So we fake to the left and do it anyway */
  288. /* Wonder if the compile optomizes it to the correct solution */
  289. fakeout = (struct ddloc **)&(dirp->dd_ddloc);
  290. *fakeout = lp;
  291. ret = lp->loc_index;
  292. } else {
  293. ret = -1;
  294. }
  295. pthread_mutex_unlock (dirp->dd_lock);
  296. return(ret);
  297. }