1 /* savedirinfo.c -- Save the list of files in a directory, with additional information.
3 Copyright 1990, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 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)
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 James Youngman, <jay@gnu.org>. */
21 /* Derived from savedir.c, written by David MacKenzie <djm@gnu.org>. */
28 # include <sys/stat.h>
32 # include <sys/types.h>
44 # define dirent direct
46 # include <sys/ndir.h>
57 /* Fake a return value. */
58 # define CLOSEDIR(d) (closedir (d), 0)
60 # define CLOSEDIR(d) closedir (d)
68 #include "extendbuf.h"
69 #include "savedirinfo.h"
71 /* In order to use struct dirent.d_type, it has to be enabled on the
72 * configure command line, and we have to have a d_type member in
75 #if !defined(USE_STRUCT_DIRENT_D_TYPE)
76 /* Not enabled, hence pretend it is absent. */
77 #undef HAVE_STRUCT_DIRENT_D_TYPE
79 #if !defined(HAVE_STRUCT_DIRENT_D_TYPE)
80 /* Not present, so cannot use it. */
81 #undef USE_STRUCT_DIRENT_D_TYPE
85 #if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
86 /* Convert the value of struct dirent.d_type into a value for
87 * struct stat.st_mode (at least the file type bits), or zero
88 * if the type is DT_UNKNOWN or is a value we don't know about.
91 type_to_mode(unsigned type
)
98 case DT_FIFO
: return S_IFIFO
;
101 case DT_CHR
: return S_IFCHR
;
104 case DT_DIR
: return S_IFDIR
;
107 case DT_BLK
: return S_IFBLK
;
110 case DT_REG
: return S_IFREG
;
113 case DT_LNK
: return S_IFLNK
;
116 case DT_SOCK
: return S_IFSOCK
;
119 return 0; /* Unknown. */
126 /* Return a freshly allocated string containing the filenames
127 in directory DIR, separated by '\0' characters;
128 the end is marked by two '\0' characters in a row.
129 Return NULL (setting errno) if DIR cannot be opened, read, or closed. */
132 savedirinfo (const char *dir
, struct savedir_dirinfo
**extra
)
137 size_t namebuf_allocated
= 0u, namebuf_used
= 0u;
138 #if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
139 size_t extra_allocated
= 0u, extra_used
= 0u;
140 struct savedir_dirinfo
*info
= NULL
;
147 dirp
= opendir (dir
);
153 while ((dp
= readdir (dirp
)) != NULL
)
155 /* Skip "", ".", and "..". "" is returned by at least one buggy
156 implementation: Solaris 2.4 readdir on NFS file systems. */
157 char const *entry
= dp
->d_name
;
158 if (entry
[entry
[0] != '.' ? 0 : entry
[1] != '.' ? 1 : 2] != '\0')
160 /* Remember the name. */
161 size_t entry_size
= strlen (entry
) + 1;
162 name_space
= extendbuf(name_space
, namebuf_used
+entry_size
, &namebuf_allocated
);
163 memcpy (name_space
+ namebuf_used
, entry
, entry_size
);
164 namebuf_used
+= entry_size
;
167 #if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)
168 /* Remember the type. */
171 info
= extendbuf(info
,
172 (extra_used
+1) * sizeof(struct savedir_dirinfo
),
174 info
[extra_used
].type_info
= type_to_mode(dp
->d_type
);
181 name_space
= extendbuf(name_space
, namebuf_used
+1, &namebuf_allocated
);
182 name_space
[namebuf_used
] = '\0';
185 if (CLOSEDIR (dirp
) != 0)
194 #if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(USE_STRUCT_DIRENT_D_TYPE)