Initial implementation (temporarily disabled).
[findutils.git] / lib / savedirinfo.c
blob446c9ff92abbc8c461108c0b0fb9215dcd879f49
1 /* savedir.c -- save the list of files in a directory in a string
3 Copyright 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004 Free
4 Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
22 #if HAVE_CONFIG_H
23 # include <config.h>
24 #endif
26 #if HAVE_SYS_STAT_H
27 # include <sys/stat.h>
28 #endif
30 #if HAVE_SYS_TYPES_H
31 # include <sys/types.h>
32 #endif
34 #if HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
38 #include <errno.h>
40 #if HAVE_DIRENT_H
41 # include <dirent.h>
42 #else
43 # define dirent direct
44 # if HAVE_SYS_NDIR_H
45 # include <sys/ndir.h>
46 # endif
47 # if HAVE_SYS_DIR_H
48 # include <sys/dir.h>
49 # endif
50 # if HAVE_NDIR_H
51 # include <ndir.h>
52 # endif
53 #endif
55 #ifdef CLOSEDIR_VOID
56 /* Fake a return value. */
57 # define CLOSEDIR(d) (closedir (d), 0)
58 #else
59 # define CLOSEDIR(d) closedir (d)
60 #endif
62 #include <stddef.h>
63 #include <stdlib.h>
64 #include <string.h>
66 #include "xalloc.h"
67 #include "extendbuf.h"
68 #include "savedirinfo.h"
70 #undef HAVE_STRUCT_DIRENT_D_TYPE
73 #if defined HAVE_STRUCT_DIRENT_D_TYPE
74 static mode_t
75 type_to_mode(unsigned type)
77 mode_t result = 0;
79 switch (type)
81 #ifdef DT_FIFO
82 case DT_FIFO: return S_IFIFO;
83 #endif
84 #ifdef DT_CHR
85 case DT_CHR: return S_IFCHR;
86 #endif
87 #ifdef DT_DIR
88 case DT_DIR: return S_IFDIR;
89 #endif
90 #ifdef DT_BLK
91 case DT_BLK: return S_IFBLK;
92 #endif
93 #ifdef DT_REG
94 case DT_REG: return S_IFREG;
95 #endif
96 #ifdef DT_LNK
97 case DT_LNK: return S_IFLNK;
98 #endif
99 #ifdef DT_SOCK
100 case DT_SOCK: return S_IFSOCK;
101 #endif
102 default:
103 return 0; /* Unknown. */
107 #endif
110 /* Return a freshly allocated string containing the filenames
111 in directory DIR, separated by '\0' characters;
112 the end is marked by two '\0' characters in a row.
113 Return NULL (setting errno) if DIR cannot be opened, read, or closed. */
115 char *
116 savedirinfo (const char *dir, struct savedir_dirinfo **extra)
118 DIR *dirp;
119 struct dirent *dp;
120 char *name_space;
121 size_t namebuf_allocated = 0u, namebuf_used = 0u;
122 #if defined HAVE_STRUCT_DIRENT_D_TYPE
123 size_t extra_allocated = 0u, extra_used = 0u;
124 struct savedir_dirinfo *info = NULL;
125 #endif
126 int save_errno;
128 if (extra)
129 *extra = NULL;
131 dirp = opendir (dir);
132 if (dirp == NULL)
133 return NULL;
135 errno = 0;
136 name_space = NULL;
137 while ((dp = readdir (dirp)) != NULL)
139 /* Skip "", ".", and "..". "" is returned by at least one buggy
140 implementation: Solaris 2.4 readdir on NFS file systems. */
141 char const *entry = dp->d_name;
142 if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0')
144 /* Remember the name. */
145 size_t entry_size = strlen (entry) + 1;
146 name_space = extendbuf(name_space, namebuf_used+entry_size, &namebuf_allocated);
147 memcpy (name_space + namebuf_used, entry, entry_size);
148 namebuf_used += entry_size;
151 #if defined HAVE_STRUCT_DIRENT_D_TYPE
152 /* Remember the type. */
153 if (extra)
155 info = extendbuf(info,
156 (extra_used+1) * sizeof(struct savedir_dirinfo),
157 &extra_allocated);
158 info[extra_used].type_info = type_to_mode(dp->d_type);
160 #endif
164 name_space = extendbuf(name_space, namebuf_used+1, &namebuf_allocated);
165 name_space[namebuf_used] = '\0';
167 save_errno = errno;
168 if (CLOSEDIR (dirp) != 0)
169 save_errno = errno;
170 if (save_errno != 0)
172 free (name_space);
173 errno = save_errno;
174 return NULL;
177 #if defined HAVE_STRUCT_DIRENT_D_TYPE
178 if (extra && info)
179 *extra = info;
180 #endif
182 return name_space;