Added silc_file_stat, silc_file_fstat and silc_file_fsize
[runtime.git] / lib / silcutil / unix / silcunixdir.c
1 /*
2
3   silcunixdir.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2008 Pekka Riikonen
8
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.
12
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.
17
18 */
19
20 #include "silcruntime.h"
21
22 /************************** Types and definitions ***************************/
23
24 /* Directory entry context */
25 struct SilcDirEntryStruct {
26   struct dirent *entry;                   /* Entry */
27   SilcFileStatStruct status;              /* Status */
28 };
29
30 /* The directory context */
31 struct SilcDirStruct {
32   DIR *dir;                               /* Directory */
33   char *name;                             /* Directory name */
34   struct SilcDirEntryStruct entry;        /* Current entry */
35 };
36
37 /****************************** SILC Dir API ********************************/
38
39 /* Open directory */
40
41 SilcDir silc_dir_open(const char *name)
42 {
43   SilcDir dir;
44
45   if (!name || !strlen(name)) {
46     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
47     return NULL;
48   }
49
50   SILC_LOG_DEBUG(("Open directory '%s'", name));
51
52   dir = silc_calloc(1, sizeof(*dir));
53   if (!dir)
54     return NULL;
55
56   dir->name = silc_strdup(name);
57   if (!dir->name) {
58     silc_free(dir);
59     return NULL;
60   }
61
62   if (dir->name[strlen(dir->name) - 1] == '/')
63     dir->name[strlen(dir->name) - 1] = '\0';
64
65   dir->dir = opendir(name);
66   if (!dir->dir) {
67     silc_set_errno_posix(errno);
68     silc_free(dir->name);
69     silc_free(dir);
70     return NULL;
71   }
72
73   return dir;
74 }
75
76 /* Close directory */
77
78 void silc_dir_close(SilcDir dir)
79 {
80   if (!dir)
81     return;
82
83   SILC_LOG_DEBUG(("Close directory '%s'", dir->name));
84
85   closedir(dir->dir);
86   silc_free(dir->name);
87   silc_free(dir);
88 }
89
90 /* Read next entry in the directory */
91
92 SilcDirEntry silc_dir_read(SilcDir dir, SilcFileStat status)
93 {
94   if (!dir) {
95     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
96     return NULL;
97   }
98
99   SILC_LOG_DEBUG(("Read directory '%s'", dir->name));
100
101   dir->entry.entry = readdir(dir->dir);
102   if (!dir->entry.entry) {
103     if (errno)
104       silc_set_errno_posix(errno);
105     return NULL;
106   }
107
108   if (status) {
109     char *name = NULL;
110     silc_asprintf(&name, "%s/%s", dir->name, dir->entry.entry->d_name);
111     if (name)
112       silc_file_stat(name, TRUE, status);
113     silc_free(name);
114   }
115
116   return (SilcDirEntry)&dir->entry;
117 }
118
119 /* Rewind directory */
120
121 void silc_dir_rewind(SilcDir dir)
122 {
123   if (!dir)
124     return;
125
126   SILC_LOG_DEBUG(("Rewind directory '%s'", dir->name));
127
128   rewinddir(dir->dir);
129 }
130
131 /* Return directory name */
132
133 const char *silc_dir_name(SilcDir dir)
134 {
135   if (!dir) {
136     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
137     return NULL;
138   }
139
140   return dir->name;
141 }
142
143 /* Return entry name */
144
145 const char *silc_dir_entry_name(SilcDirEntry entry)
146 {
147   if (!entry) {
148     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
149     return NULL;
150   }
151
152   return (const char *)entry->entry->d_name;
153 }