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.
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 SILC_LOG_DEBUG(("Open directory '%s'", name));
47 dir = silc_calloc(1, sizeof(*dir));
51 dir->name = silc_strdup(name);
57 if (dir->name[strlen(dir->name) - 1] == '/')
58 dir->name[strlen(dir->name) - 1] = '\0';
60 dir->dir = opendir(name);
62 silc_set_errno_posix(errno);
73 void silc_dir_close(SilcDir dir)
78 SILC_LOG_DEBUG(("Close directory '%s'", dir->name));
85 /* Read next entry in the directory */
87 SilcDirEntry silc_dir_read(SilcDir dir, SilcDirEntryStat *status)
90 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
94 SILC_LOG_DEBUG(("Read directory '%s'", dir->name));
96 dir->entry.entry = readdir(dir->dir);
97 if (!dir->entry.entry) {
99 silc_set_errno_posix(errno);
104 *status = silc_dir_entry_stat(dir, &dir->entry);
106 return (SilcDirEntry)&dir->entry;
109 /* Rewind directory */
111 void silc_dir_rewind(SilcDir dir)
116 SILC_LOG_DEBUG(("Rewind directory '%s'", dir->name));
121 /* Return directory name */
123 const char *silc_dir_name(SilcDir dir)
126 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
133 /* Return entry name */
135 const char *silc_dir_entry_name(SilcDirEntry entry)
138 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
142 return (const char *)entry->entry->d_name;
145 /* Return entry status information */
147 SilcDirEntryStat silc_dir_entry_stat(SilcDir dir, SilcDirEntry entry)
152 if (!dir || !entry) {
153 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
157 silc_asprintf(&name, "%s/%s", dir->name, entry->entry->d_name);
161 SILC_LOG_DEBUG(("Get status for entry '%s'", name));
163 if (lstat(name, &status) != 0) {
164 silc_set_errno_posix(errno);
171 memset(&entry->status, 0, sizeof(entry->status));
173 silc_time_value(status.st_atime * 1000, &entry->status.last_access);
174 silc_time_value(status.st_mtime * 1000, &entry->status.last_mod);
175 silc_time_value(status.st_ctime * 1000, &entry->status.last_change);
177 entry->status.dev = status.st_dev;
178 entry->status.nlink = status.st_nlink;
179 entry->status.gid = status.st_gid;
180 entry->status.uid = status.st_uid;
181 entry->status.size = status.st_size;
183 #if defined(S_IFSOCK)
184 if (status.st_mode & S_IFSOCK)
185 entry->status.mode |= SILC_DIR_ENTRY_IFSOCK;
186 #endif /* S_IFSOCK */
188 if (status.st_mode & S_IFLNK)
189 entry->status.mode |= SILC_DIR_ENTRY_IFLNK;
192 if (status.st_mode & S_IFREG)
193 entry->status.mode |= SILC_DIR_ENTRY_IFREG;
196 if (status.st_mode & S_IFBLK)
197 entry->status.mode |= SILC_DIR_ENTRY_IFBLK;
200 if (status.st_mode & S_IFDIR)
201 entry->status.mode |= SILC_DIR_ENTRY_IFDIR;
204 if (status.st_mode & S_IFCHR)
205 entry->status.mode |= SILC_DIR_ENTRY_IFCHR;
208 if (status.st_mode & S_IFIFO)
209 entry->status.mode |= SILC_DIR_ENTRY_IFIFO;
212 if (status.st_mode & S_IRUSR)
213 entry->status.mode |= SILC_DIR_ENTRY_IRUSR;
216 if (status.st_mode & S_IWUSR)
217 entry->status.mode |= SILC_DIR_ENTRY_IWUSR;
220 if (status.st_mode & S_IXUSR)
221 entry->status.mode |= SILC_DIR_ENTRY_IXUSR;
224 if (status.st_mode & S_IRGRP)
225 entry->status.mode |= SILC_DIR_ENTRY_IRGRP;
228 if (status.st_mode & S_IWGRP)
229 entry->status.mode |= SILC_DIR_ENTRY_IWGRP;
232 if (status.st_mode & S_IXGRP)
233 entry->status.mode |= SILC_DIR_ENTRY_IXGRP;
236 if (status.st_mode & S_IROTH)
237 entry->status.mode |= SILC_DIR_ENTRY_IROTH;
240 if (status.st_mode & S_IWOTH)
241 entry->status.mode |= SILC_DIR_ENTRY_IWOTH;
244 if (status.st_mode & S_IXOTH)
245 entry->status.mode |= SILC_DIR_ENTRY_IXOTH;
248 return (SilcDirEntryStat)&entry->status;