home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / microcode / uxfs.c < prev    next >
C/C++ Source or Header  |  2001-05-08  |  17KB  |  631 lines

  1. /* -*-C-*-
  2.  
  3. $Id: uxfs.c,v 1.21 2001/05/09 03:15:14 cph Exp $
  4.  
  5. Copyright (c) 1990-2001 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  20. USA.
  21. */
  22.  
  23. #include "ux.h"
  24. #include "osfs.h"
  25. #include "osfile.h"
  26. #include "osio.h"
  27.  
  28. #ifdef HAVE_STATFS
  29. #  ifdef HAVE_SYS_VFS_H
  30.      /* GNU/Linux */
  31. #    include <sys/vfs.h>
  32. #  else
  33. #    ifdef HAVE_SYS_MOUNT_H
  34.        /* FreeBSD */
  35. #      include <sys/param.h>
  36. #      include <sys/mount.h>
  37. #    endif
  38. #  endif
  39. #  ifdef __linux__
  40. /* The following superblock magic constants are taken from the kernel
  41.    headers for Linux 2.0.33.  We use these rather than reading the
  42.    header files, because the Linux kernel header files have
  43.    definitions that conflict with those of glibc2.  These constants
  44.    are unlikely to be changed, so this ought to be safe.  */
  45. #    ifndef AFFS_SUPER_MAGIC
  46. #      define AFFS_SUPER_MAGIC 0xadff
  47. #    endif
  48. #    ifndef COH_SUPER_MAGIC
  49. #      define COH_SUPER_MAGIC 0x012FF7B7
  50. #    endif
  51. #    ifndef EXT_SUPER_MAGIC
  52. #      define EXT_SUPER_MAGIC 0x137D
  53. #    endif
  54. #    ifndef EXT2_SUPER_MAGIC
  55. #      define EXT2_SUPER_MAGIC 0xEF53
  56. #    endif
  57. #    ifndef HPFS_SUPER_MAGIC
  58. #      define HPFS_SUPER_MAGIC 0xf995e849
  59. #    endif
  60. #    ifndef ISOFS_SUPER_MAGIC
  61. #      define ISOFS_SUPER_MAGIC 0x9660
  62. #    endif
  63. #    ifndef MINIX_SUPER_MAGIC
  64. #      define MINIX_SUPER_MAGIC 0x137F
  65. #    endif
  66. #    ifndef MINIX_SUPER_MAGIC2
  67. #      define MINIX_SUPER_MAGIC2 0x138F
  68. #    endif
  69. #    ifndef MINIX2_SUPER_MAGIC
  70. #      define MINIX2_SUPER_MAGIC 0x2468
  71. #    endif
  72. #    ifndef MINIX2_SUPER_MAGIC2
  73. #      define MINIX2_SUPER_MAGIC2 0x2478
  74. #    endif
  75. #    ifndef MSDOS_SUPER_MAGIC
  76. #      define MSDOS_SUPER_MAGIC 0x4d44
  77. #    endif
  78. #    ifndef NCP_SUPER_MAGIC
  79. #      define NCP_SUPER_MAGIC 0x564c
  80. #    endif
  81. #    ifndef NFS_SUPER_MAGIC
  82. #      define NFS_SUPER_MAGIC 0x6969
  83. #    endif
  84. #    ifndef NTFS_SUPER_MAGIC
  85. #      define NTFS_SUPER_MAGIC 0x5346544E
  86. #    endif
  87. #    ifndef PROC_SUPER_MAGIC
  88. #      define PROC_SUPER_MAGIC 0x9fa0
  89. #    endif
  90. #    ifndef SMB_SUPER_MAGIC
  91. #      define SMB_SUPER_MAGIC 0x517B
  92. #    endif
  93. #    ifndef SYSV2_SUPER_MAGIC
  94. #      define SYSV2_SUPER_MAGIC 0x012FF7B6
  95. #    endif
  96. #    ifndef SYSV4_SUPER_MAGIC
  97. #      define SYSV4_SUPER_MAGIC 0x012FF7B5
  98. #    endif
  99. #    ifndef XENIX_SUPER_MAGIC
  100. #      define XENIX_SUPER_MAGIC 0x012FF7B4
  101. #    endif
  102. #    ifndef _XIAFS_SUPER_MAGIC
  103. #      define _XIAFS_SUPER_MAGIC 0x012FD16D
  104. #    endif
  105. #  endif
  106. #endif
  107.  
  108. #ifndef FILE_TOUCH_OPEN_TRIES
  109. #  define FILE_TOUCH_OPEN_TRIES 5
  110. #endif
  111.  
  112. int
  113. DEFUN (UX_read_file_status, (filename, s),
  114.        CONST char * filename AND
  115.        struct stat * s)
  116. {
  117.   while ((UX_lstat (filename, s)) < 0)
  118.     {
  119.       if (errno == EINTR)
  120.     continue;
  121.       if ((errno == ENOENT) || (errno == ENOTDIR))
  122.     return (0);
  123.       error_system_call (errno, syscall_lstat);
  124.     }
  125.   return (1);
  126. }
  127.  
  128. int
  129. DEFUN (UX_read_file_status_indirect, (filename, s),
  130.        CONST char * filename AND
  131.        struct stat * s)
  132. {
  133.   while ((UX_stat (filename, s)) < 0)
  134.     {
  135.       if (errno == EINTR)
  136.     continue;
  137.       if ((errno == ENOENT) || (errno == ENOTDIR))
  138.     return (0);
  139.       error_system_call (errno, syscall_stat);
  140.     }
  141.   return (1);
  142. }
  143.  
  144. enum file_existence
  145. DEFUN (OS_file_existence_test, (name), CONST char * name)
  146. {
  147.   struct stat s;
  148.   if (!UX_read_file_status (name, (&s)))
  149.     return (file_doesnt_exist);
  150. #ifdef HAVE_SYMLINK
  151.   if (((s . st_mode) & S_IFMT) == S_IFLNK)
  152.     {
  153.       if (UX_read_file_status_indirect (name, (&s)))
  154.     return (file_does_exist);
  155.       else
  156.     return (file_is_link);
  157.     }
  158. #endif
  159.   return (file_does_exist);
  160. }
  161.  
  162. enum file_existence
  163. DEFUN (OS_file_existence_test_direct, (name), CONST char * name)
  164. {
  165.   struct stat s;
  166.   if (!UX_read_file_status (name, (&s)))
  167.     return (file_doesnt_exist);
  168. #ifdef HAVE_SYMLINK
  169.   if (((s . st_mode) & S_IFMT) == S_IFLNK)
  170.     return (file_is_link);
  171. #endif
  172.   return (file_does_exist);
  173. }
  174.  
  175. #ifndef S_ISREG
  176. #  define S_ISREG(mode) (((mode) & S_IFREG) != 0)
  177. #endif
  178. #ifndef S_ISDIR
  179. #  define S_ISDIR(mode) (((mode) & S_IFDIR) != 0)
  180. #endif
  181. #ifndef S_ISLNK
  182. #  define S_ISLNK(mode) (((mode) & S_IFLNK) != 0)
  183. #endif
  184. #ifndef S_ISCHR
  185. #  define S_ISCHR(mode) (((mode) & S_IFCHR) != 0)
  186. #endif
  187. #ifndef S_ISBLK
  188. #  define S_ISBLK(mode) (((mode) & S_IFBLK) != 0)
  189. #endif
  190. #ifndef S_ISFIFO
  191. #  define S_ISFIFO(mode) (((mode) & S_IFIFO) != 0)
  192. #endif
  193. #ifndef S_ISSOCK
  194. #  define S_ISSOCK(mode) (((mode) & S_IFSOCK) != 0)
  195. #endif
  196.  
  197. #define COMPUTE_FILE_TYPE(proc, name)                    \
  198. {                                    \
  199.   struct stat s;                            \
  200.   if (!proc ((name), (&s)))                        \
  201.     return (file_type_nonexistent);                    \
  202.   else if (S_ISREG (s . st_mode))                    \
  203.     return (file_type_regular);                        \
  204.   else if (S_ISDIR (s . st_mode))                    \
  205.     return (file_type_directory);                    \
  206.   else if (S_ISLNK (s . st_mode))                    \
  207.     return (file_type_unix_symbolic_link);                \
  208.   else if (S_ISCHR (s . st_mode))                    \
  209.     return (file_type_unix_character_device);                \
  210.   else if (S_ISBLK (s . st_mode))                    \
  211.     return (file_type_unix_block_device);                \
  212.   else if (S_ISFIFO (s . st_mode))                    \
  213.     return (file_type_unix_fifo);                    \
  214.   else if (S_ISSOCK (s . st_mode))                    \
  215.     return (file_type_unix_stream_socket);                \
  216.   else                                    \
  217.     return (file_type_unknown);                        \
  218. }
  219.  
  220. enum file_type
  221. DEFUN (OS_file_type_direct, (name), CONST char * name)
  222. COMPUTE_FILE_TYPE (UX_read_file_status, name)
  223.  
  224. enum file_type
  225. DEFUN (OS_file_type_indirect, (name), CONST char * name)
  226. COMPUTE_FILE_TYPE (UX_read_file_status_indirect, name)
  227.  
  228. CONST char *
  229. DEFUN (UX_file_system_type, (name), CONST char * name)
  230. {
  231. #ifdef HAVE_STATFS
  232.   struct statfs s;
  233.   while ((UX_statfs (name, (&s))) < 0)
  234.     {
  235.       if ((errno == ENOENT) || (errno == ENOTDIR))
  236.     return (0);
  237.       if (errno != EINTR)
  238.     error_system_call (errno, syscall_statfs);
  239.     }
  240.  
  241. #ifdef __linux__
  242.   switch (s . f_type)
  243.     {
  244.     case COH_SUPER_MAGIC:    return ("coherent");
  245.     case EXT_SUPER_MAGIC:    return ("ext");
  246.     case EXT2_SUPER_MAGIC:    return ("ext2");
  247.     case HPFS_SUPER_MAGIC:    return ("hpfs");
  248.     case ISOFS_SUPER_MAGIC:    return ("iso9660");
  249.     case MINIX_SUPER_MAGIC:    return ("minix1");
  250.     case MINIX_SUPER_MAGIC2:    return ("minix1-30");
  251.     case MINIX2_SUPER_MAGIC:    return ("minix2");
  252.     case MINIX2_SUPER_MAGIC2:    return ("minix2-30");
  253.     case MSDOS_SUPER_MAGIC:    return ("fat");
  254.     case NCP_SUPER_MAGIC:    return ("ncp");
  255.     case NFS_SUPER_MAGIC:    return ("nfs");
  256.     case NTFS_SUPER_MAGIC:    return ("ntfs");
  257.     case PROC_SUPER_MAGIC:    return ("proc");
  258.     case SMB_SUPER_MAGIC:    return ("smb");
  259.     case SYSV2_SUPER_MAGIC:    return ("sysv2");
  260.     case SYSV4_SUPER_MAGIC:    return ("sysv4");
  261.     case XENIX_SUPER_MAGIC:    return ("xenix");
  262.     case _XIAFS_SUPER_MAGIC:    return ("xiafs");
  263.     }
  264. #endif /* __linux__ */
  265.  
  266. #ifdef __HPUX__
  267.   switch ((s . f_fsid) [1])
  268.     {
  269.     case MOUNT_UFS:        return ("ufs");
  270.     case MOUNT_NFS:        return ("nfs");
  271.     case MOUNT_CDFS:        return ("iso9660");
  272.     }
  273. #endif /* __HPUX__ */
  274. #endif /* HAVE_STATFS */
  275.  
  276.   return (0);
  277. }
  278.  
  279. int
  280. DEFUN (OS_file_directory_p, (name), CONST char * name)
  281. {
  282.   struct stat s;
  283.   return
  284.     ((UX_read_file_status_indirect (name, (&s)))
  285.      && (((s . st_mode) & S_IFMT) == S_IFDIR));
  286. }
  287.  
  288. CONST char *
  289. DEFUN (OS_file_soft_link_p, (name), CONST char * name)
  290. {
  291. #ifdef HAVE_SYMLINK
  292.   struct stat s;
  293.   if (! ((UX_read_file_status (name, (&s)))
  294.      && (((s . st_mode) & S_IFMT) == S_IFLNK)))
  295.     return (0);
  296.   {
  297.     int scr;
  298.     int buffer_length = 100;
  299.     char * buffer = (UX_malloc (buffer_length));
  300.     if (buffer == 0)
  301.       error_system_call (ENOMEM, syscall_malloc);
  302.     while (1)
  303.       {
  304.     STD_UINT_SYSTEM_CALL
  305.       (syscall_readlink, scr, (UX_readlink (name, buffer, buffer_length)));
  306.     if (scr < buffer_length)
  307.       break;
  308.     buffer_length *= 2;
  309.     buffer = (UX_realloc (buffer, buffer_length));
  310.     if (buffer == 0)
  311.       error_system_call (ENOMEM, syscall_realloc);
  312.       }
  313.     (buffer[scr]) = '\0';
  314.     return ((CONST char *) buffer);
  315.   }
  316. #else
  317.   return (0);
  318. #endif
  319. }
  320.  
  321. int
  322. DEFUN (OS_file_access, (name, mode), CONST char * name AND unsigned int mode)
  323. {
  324.   return ((UX_access (name, mode)) == 0);
  325. }
  326.  
  327. void
  328. DEFUN (OS_file_remove, (name), CONST char * name)
  329. {
  330.   STD_VOID_SYSTEM_CALL (syscall_unlink, (UX_unlink (name)));
  331. }
  332.  
  333. void
  334. DEFUN (OS_file_remove_link, (name), CONST char * name)
  335. {
  336.   struct stat s;
  337.   if ((UX_read_file_status (name, (&s)))
  338.       && ((((s . st_mode) & S_IFMT) == S_IFREG)
  339. #ifdef HAVE_SYMLINK
  340.       || (((s . st_mode) & S_IFMT) == S_IFLNK)
  341. #endif
  342.       ))
  343.     UX_unlink (name);
  344. }
  345.  
  346. void
  347. DEFUN (OS_file_link_hard, (from_name, to_name),
  348.        CONST char * from_name AND
  349.        CONST char * to_name)
  350. {
  351.   STD_VOID_SYSTEM_CALL (syscall_link, (UX_link (from_name, to_name)));
  352. }
  353.  
  354. void
  355. DEFUN (OS_file_link_soft, (from_name, to_name),
  356.        CONST char * from_name AND
  357.        CONST char * to_name)
  358. {
  359. #ifdef HAVE_SYMLINK
  360.   STD_VOID_SYSTEM_CALL (syscall_symlink, (UX_symlink (from_name, to_name)));
  361. #else
  362.   error_unimplemented_primitive ();
  363. #endif
  364. }
  365.  
  366. void
  367. DEFUN (OS_file_rename, (from_name, to_name),
  368.        CONST char * from_name AND
  369.        CONST char * to_name)
  370. {
  371.   STD_VOID_SYSTEM_CALL (syscall_rename, (UX_rename (from_name, to_name)));
  372. }
  373.  
  374. #ifndef FILE_COPY_BUFFER_LENGTH
  375. #define FILE_COPY_BUFFER_LENGTH 8192
  376. #endif
  377.  
  378. void
  379. DEFUN (OS_file_copy, (from_name, to_name),
  380.        CONST char * from_name AND
  381.        CONST char * to_name)
  382. {
  383.   Tchannel src, dst;
  384.   off_t src_len, len;
  385.   char buffer [FILE_COPY_BUFFER_LENGTH];
  386.   long nread, nwrite;
  387.  
  388.   src = (OS_open_input_file (from_name));
  389.   OS_channel_close_on_abort (src);
  390.   dst = (OS_open_output_file (to_name));
  391.   OS_channel_close_on_abort (dst);
  392.   src_len = (OS_file_length (src));
  393.   len = (sizeof (buffer));
  394.   while (src_len > 0)
  395.     {
  396.       if (src_len < len)
  397.     len = src_len;
  398.       nread = (OS_channel_read (src, buffer, len));
  399.       if (nread < 0)
  400.     error_system_call (errno, syscall_read);
  401.       else if (nread == 0)
  402.     break;
  403.       nwrite = (OS_channel_write (dst, buffer, nread));
  404.       if (nwrite < 0)
  405.     error_system_call (errno, syscall_write);
  406.       else if (nwrite < nread)
  407.     error_system_call (ENOSPC, syscall_write);
  408.       src_len -= nread;
  409.     }
  410.   OS_channel_close (src);
  411.   OS_channel_close (dst);
  412. }
  413.  
  414. void
  415. DEFUN (OS_directory_make, (name), CONST char * name)
  416. {
  417.   STD_VOID_SYSTEM_CALL (syscall_mkdir, (UX_mkdir (name, MODE_DIR)));
  418. }
  419.  
  420. void
  421. DEFUN (OS_directory_delete, (name), CONST char * name)
  422. {
  423.   STD_VOID_SYSTEM_CALL (syscall_rmdir, (UX_rmdir (name)));
  424. }
  425.  
  426. static void EXFUN (protect_fd, (int fd));
  427.  
  428. int
  429. DEFUN (OS_file_touch, (filename), CONST char * filename)
  430. {
  431.   int fd;
  432.   transaction_begin ();
  433.   {
  434.     unsigned int count = 0;
  435.     while (1)
  436.       {
  437.     count += 1;
  438.     /* Use O_EXCL to prevent overwriting existing file. */
  439.     fd = (UX_open (filename, (O_RDWR | O_CREAT | O_EXCL), MODE_REG));
  440.     if (fd >= 0)
  441.       {
  442.         protect_fd (fd);
  443.         transaction_commit ();
  444.         return (1);
  445.       }
  446.     if (errno == EEXIST)
  447.       {
  448.         fd = (UX_open (filename, O_RDWR, MODE_REG));
  449.         if (fd >= 0)
  450.           {
  451.         protect_fd (fd);
  452.         break;
  453.           }
  454.         else if ((errno == ENOENT)
  455. #ifdef ESTALE
  456.              || (errno == ESTALE)
  457. #endif
  458.              )
  459.           continue;
  460.       }
  461.     if (count >= FILE_TOUCH_OPEN_TRIES)
  462.       error_system_call (errno, syscall_open);
  463.       }
  464.   }
  465.   {
  466.     struct stat file_status;
  467.     STD_VOID_SYSTEM_CALL (syscall_fstat, (UX_fstat (fd, (&file_status))));
  468.     if (((file_status . st_mode) & S_IFMT) != S_IFREG)
  469.       error_system_call (errno, syscall_open);
  470.     /* CASE 3: file length of 0 needs special treatment. */
  471.     if ((file_status . st_size) == 0)
  472.       {
  473.     char buf [1];
  474.     (buf[0]) = '\0';
  475.     STD_VOID_SYSTEM_CALL (syscall_write, (UX_write (fd, buf, 1)));
  476. #ifdef HAVE_FTRUNCATE
  477.     STD_VOID_SYSTEM_CALL (syscall_ftruncate, (UX_ftruncate (fd, 0)));
  478.     transaction_commit ();
  479. #else
  480.     transaction_commit ();
  481.     fd = (UX_open (filename, (O_WRONLY | O_TRUNC), MODE_REG));
  482.     if (fd >= 0)
  483.       STD_VOID_SYSTEM_CALL (syscall_close, (UX_close (fd)));
  484. #endif
  485.     return (0);
  486.       }
  487.   }
  488.   /* CASE 4: read, then write back the first byte in the file. */
  489.   {
  490.     char buf [1];
  491.     int scr;
  492.     STD_UINT_SYSTEM_CALL (syscall_read, scr, (UX_read (fd, buf, 1)));
  493.     if (scr > 0)
  494.       {
  495.     STD_VOID_SYSTEM_CALL (syscall_lseek, (UX_lseek (fd, 0, SEEK_SET)));
  496.     STD_VOID_SYSTEM_CALL (syscall_write, (UX_write (fd, buf, 1)));
  497.       }
  498.   }
  499.   transaction_commit ();
  500.   return (0);
  501. }
  502.  
  503. static void
  504. DEFUN (protect_fd_close, (ap), PTR ap)
  505. {
  506.   UX_close (* ((int *) ap));
  507. }
  508.  
  509. static void
  510. DEFUN (protect_fd, (fd), int fd)
  511. {
  512.   int * p = (dstack_alloc (sizeof (int)));
  513.   (*p) = fd;
  514.   transaction_record_action (tat_always, protect_fd_close, p);
  515. }
  516.  
  517. static DIR ** directory_pointers;
  518. static unsigned int n_directory_pointers;
  519.  
  520. void
  521. DEFUN_VOID (UX_initialize_directory_reader)
  522. {
  523.   directory_pointers = 0;
  524.   n_directory_pointers = 0;
  525.   return;
  526. }
  527.  
  528. static unsigned int
  529. DEFUN (allocate_directory_pointer, (pointer), DIR * pointer)
  530. {
  531.   if (n_directory_pointers == 0)
  532.     {
  533.       DIR ** pointers = ((DIR **) (UX_malloc ((sizeof (DIR *)) * 4)));
  534.       if (pointers == 0)
  535.     error_system_call (ENOMEM, syscall_malloc);
  536.       directory_pointers = pointers;
  537.       n_directory_pointers = 4;
  538.       {
  539.     DIR ** scan = directory_pointers;
  540.     DIR ** end = (scan + n_directory_pointers);
  541.     (*scan++) = pointer;
  542.     while (scan < end)
  543.       (*scan++) = 0;
  544.       }
  545.       return (0);
  546.     }
  547.   {
  548.     DIR ** scan = directory_pointers;
  549.     DIR ** end = (scan + n_directory_pointers);
  550.     while (scan < end)
  551.       if ((*scan++) == 0)
  552.     {
  553.       (*--scan) = pointer;
  554.       return (scan - directory_pointers);
  555.     }
  556.   }
  557.   {
  558.     unsigned int result = n_directory_pointers;
  559.     unsigned int n_pointers = (2 * n_directory_pointers);
  560.     DIR ** pointers =
  561.       ((DIR **)
  562.        (UX_realloc (((PTR) directory_pointers),
  563.             ((sizeof (DIR *)) * n_pointers))));
  564.     if (pointers == 0)
  565.       error_system_call (ENOMEM, syscall_realloc);
  566.     {
  567.       DIR ** scan = (pointers + result);
  568.       DIR ** end = (pointers + n_pointers);
  569.       (*scan++) = pointer;
  570.       while (scan < end)
  571.     (*scan++) = 0;
  572.     }
  573.     directory_pointers = pointers;
  574.     n_directory_pointers = n_pointers;
  575.     return (result);
  576.   }
  577. }
  578.  
  579. #define REFERENCE_DIRECTORY(index) (directory_pointers[(index)])
  580. #define DEALLOCATE_DIRECTORY(index) ((directory_pointers[(index)]) = 0)
  581.  
  582. int
  583. DEFUN (OS_directory_valid_p, (index), long index)
  584. {
  585.   return
  586.     ((0 <= index)
  587.      && (index < n_directory_pointers)
  588.      && ((REFERENCE_DIRECTORY (index)) != 0));
  589. }
  590.  
  591. unsigned int
  592. DEFUN (OS_directory_open, (name), CONST char * name)
  593. {
  594.   /* Cast `name' to non-const because hp-ux 7.0 declaration incorrect. */
  595.   DIR * pointer = (opendir ((char *) name));
  596.   if (pointer == 0)
  597.     error_system_call (errno, syscall_opendir);
  598.   return (allocate_directory_pointer (pointer));
  599. }
  600.  
  601. CONST char *
  602. DEFUN (OS_directory_read, (index), unsigned int index)
  603. {
  604.   struct dirent * entry = (readdir (REFERENCE_DIRECTORY (index)));
  605.   return ((entry == 0) ? 0 : (entry -> d_name));
  606. }
  607.  
  608. CONST char *
  609. DEFUN (OS_directory_read_matching, (index, prefix), 
  610.        unsigned int index AND
  611.        CONST char * prefix)
  612. {
  613.   DIR * pointer = (REFERENCE_DIRECTORY (index));
  614.   unsigned int n = (strlen (prefix));
  615.   while (1)
  616.     {
  617.       struct dirent * entry = (readdir (pointer));
  618.       if (entry == 0)
  619.     return (0);
  620.       if ((strncmp (prefix, (entry -> d_name), n)) == 0)
  621.     return (entry -> d_name);
  622.     }
  623. }
  624.  
  625. void
  626. DEFUN (OS_directory_close, (index), unsigned int index)
  627. {
  628.   closedir (REFERENCE_DIRECTORY (index));
  629.   DEALLOCATE_DIRECTORY (index);
  630. }
  631.