5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2008 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 #include "silcruntime.h"
22 /************************** Types and definitions ***************************/
24 /* Directory entry context */
25 struct SilcDirEntryStruct {
26 struct dirent *entry; /* Entry */
27 SilcDirEntryStatStruct status; /* Status */
30 /* The directory context */
31 struct SilcDirStruct {
32 DIR *dir; /* Directory */
33 char *name; /* Directory name */
34 struct SilcDirEntryStruct entry; /* Current entry */
37 /****************************** SILC Dir API ********************************/
41 SilcDir silc_dir_open(const char *name)
45 if (!name || !strlen(name)) {
46 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
50 SILC_LOG_DEBUG(("Open directory '%s'", name));
52 dir = silc_calloc(1, sizeof(*dir));
56 dir->name = silc_strdup(name);
62 if (dir->name[strlen(dir->name) - 1] == '/')
63 dir->name[strlen(dir->name) - 1] = '\0';
65 dir->dir = opendir(name);
67 silc_set_errno_posix(errno);
78 void silc_dir_close(SilcDir dir)
83 SILC_LOG_DEBUG(("Close directory '%s'", dir->name));
90 /* Read next entry in the directory */
92 SilcDirEntry silc_dir_read(SilcDir dir, SilcDirEntryStat *status)
95 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
99 SILC_LOG_DEBUG(("Read directory '%s'", dir->name));
101 dir->entry.entry = readdir(dir->dir);
102 if (!dir->entry.entry) {
104 silc_set_errno_posix(errno);
109 *status = silc_dir_entry_stat(dir, &dir->entry);
111 return (SilcDirEntry)&dir->entry;
114 /* Rewind directory */
116 void silc_dir_rewind(SilcDir dir)
121 SILC_LOG_DEBUG(("Rewind directory '%s'", dir->name));
126 /* Return directory name */
128 const char *silc_dir_name(SilcDir dir)
131 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
138 /* Return entry name */
140 const char *silc_dir_entry_name(SilcDirEntry entry)
143 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
147 return (const char *)entry->entry->d_name;
150 /* Return entry status information */
152 SilcDirEntryStat silc_dir_entry_stat(SilcDir dir, SilcDirEntry entry)
157 if (!dir || !entry) {
158 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
162 silc_asprintf(&name, "%s/%s", dir->name, entry->entry->d_name);
166 SILC_LOG_DEBUG(("Get status for entry '%s'", name));
168 if (lstat(name, &status) != 0) {
169 silc_set_errno_posix(errno);
176 memset(&entry->status, 0, sizeof(entry->status));
178 silc_time_value(status.st_atime * 1000, &entry->status.last_access);
179 silc_time_value(status.st_mtime * 1000, &entry->status.last_mod);
180 silc_time_value(status.st_ctime * 1000, &entry->status.last_change);
182 entry->status.dev = status.st_dev;
183 entry->status.nlink = status.st_nlink;
184 entry->status.gid = status.st_gid;
185 entry->status.uid = status.st_uid;
186 entry->status.size = status.st_size;
188 #if defined(S_IFSOCK)
189 if (status.st_mode & S_IFSOCK)
190 entry->status.mode |= SILC_DIR_ENTRY_IFSOCK;
191 #endif /* S_IFSOCK */
193 if (status.st_mode & S_IFLNK)
194 entry->status.mode |= SILC_DIR_ENTRY_IFLNK;
197 if (status.st_mode & S_IFREG)
198 entry->status.mode |= SILC_DIR_ENTRY_IFREG;
201 if (status.st_mode & S_IFBLK)
202 entry->status.mode |= SILC_DIR_ENTRY_IFBLK;
205 if (status.st_mode & S_IFDIR)
206 entry->status.mode |= SILC_DIR_ENTRY_IFDIR;
209 if (status.st_mode & S_IFCHR)
210 entry->status.mode |= SILC_DIR_ENTRY_IFCHR;
213 if (status.st_mode & S_IFIFO)
214 entry->status.mode |= SILC_DIR_ENTRY_IFIFO;
217 if (status.st_mode & S_IRUSR)
218 entry->status.mode |= SILC_DIR_ENTRY_IRUSR;
221 if (status.st_mode & S_IWUSR)
222 entry->status.mode |= SILC_DIR_ENTRY_IWUSR;
225 if (status.st_mode & S_IXUSR)
226 entry->status.mode |= SILC_DIR_ENTRY_IXUSR;
229 if (status.st_mode & S_IRGRP)
230 entry->status.mode |= SILC_DIR_ENTRY_IRGRP;
233 if (status.st_mode & S_IWGRP)
234 entry->status.mode |= SILC_DIR_ENTRY_IWGRP;
237 if (status.st_mode & S_IXGRP)
238 entry->status.mode |= SILC_DIR_ENTRY_IXGRP;
241 if (status.st_mode & S_IROTH)
242 entry->status.mode |= SILC_DIR_ENTRY_IROTH;
245 if (status.st_mode & S_IWOTH)
246 entry->status.mode |= SILC_DIR_ENTRY_IWOTH;
249 if (status.st_mode & S_IXOTH)
250 entry->status.mode |= SILC_DIR_ENTRY_IXOTH;
253 return (SilcDirEntryStat)&entry->status;