27cae8c49062ed9ba1ba670f47f3bc594b422763
[samba.git] / source4 / lib / registry / dir.c
1 /*
2    Unix SMB/CIFS implementation.
3    Registry interface
4    Copyright (C) Jelmer Vernooij                                  2004-2007.
5
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 3 of the License, or
9    (at your option) any later version.
10
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.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "hive.h"
22 #include "system/dir.h"
23 #include "system/filesys.h"
24
25 struct dir_key {
26         struct hive_key key;
27         const char *path;
28 };
29
30 static struct hive_operations reg_backend_dir;
31
32 static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx,
33                               const struct hive_key *parent,
34                               const char *name, const char *classname,
35                               struct security_descriptor *desc,
36                               struct hive_key **result)
37 {
38         struct dir_key *dk = talloc_get_type(parent, struct dir_key);
39         char *path;
40         int ret;
41
42         path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
43         ret = mkdir(path, 0700);
44         if (ret == 0) {
45                 struct dir_key *key = talloc(mem_ctx, struct dir_key);
46                 key->key.ops = &reg_backend_dir;
47                 key->path = talloc_steal(key, path);
48                 *result = (struct hive_key *)key;
49                 return WERR_OK;
50         }
51
52         if (errno == EEXIST)
53                 return WERR_ALREADY_EXISTS;
54         printf("FAILED %s BECAUSE: %s\n", path, strerror(errno));
55         return WERR_GENERAL_FAILURE;
56 }
57
58 static WERROR reg_dir_del_key(const struct hive_key *k, const char *name)
59 {
60         struct dir_key *dk = talloc_get_type(k, struct dir_key);
61         char *child = talloc_asprintf(NULL, "%s/%s", dk->path, name);
62         WERROR ret;
63
64         if (rmdir(child) == 0)
65                 ret = WERR_OK;
66         else if (errno == ENOENT)
67                 ret = WERR_BADFILE;
68         else
69                 ret = WERR_GENERAL_FAILURE;
70
71         talloc_free(child);
72
73         return ret;
74 }
75
76 static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx,
77                                const struct hive_key *parent,
78                                const char *name, struct hive_key **subkey)
79 {
80         DIR *d;
81         char *fullpath;
82         const struct dir_key *p = talloc_get_type(parent, struct dir_key);
83         struct dir_key *ret;
84
85         if (name == NULL) {
86                 DEBUG(0, ("NULL pointer passed as directory name!"));
87                 return WERR_INVALID_PARAM;
88         }
89
90         fullpath = talloc_asprintf(mem_ctx, "%s/%s", p->path, name);
91
92         d = opendir(fullpath);
93         if (d == NULL) {
94                 DEBUG(3,("Unable to open '%s': %s\n", fullpath,
95                         strerror(errno)));
96                 return WERR_BADFILE;
97         }
98         closedir(d);
99         ret = talloc(mem_ctx, struct dir_key);
100         ret->key.ops = &reg_backend_dir;
101         ret->path = talloc_steal(ret, fullpath);
102         *subkey = (struct hive_key *)ret;
103         return WERR_OK;
104 }
105
106 static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx,
107                                    const struct hive_key *k, uint32_t idx,
108                                    const char **name,
109                                    const char **classname,
110                                    NTTIME *last_mod_time)
111 {
112         struct dirent *e;
113         const struct dir_key *dk = talloc_get_type(k, struct dir_key);
114         int i = 0;
115         DIR *d;
116
117         d = opendir(dk->path);
118
119         if (d == NULL)
120                 return WERR_INVALID_PARAM;
121
122         while((e = readdir(d))) {
123                 if(!ISDOT(e->d_name) && !ISDOTDOT(e->d_name)) {
124                         struct stat stbuf;
125                         char *thispath;
126
127                         /* Check if file is a directory */
128                         asprintf(&thispath, "%s/%s", dk->path, e->d_name);
129                         stat(thispath, &stbuf);
130
131                         if (!S_ISDIR(stbuf.st_mode)) {
132                                 SAFE_FREE(thispath);
133                                 continue;
134                         }
135
136                         if (i == idx) {
137                                 struct stat st;
138                                 *name = talloc_strdup(mem_ctx, e->d_name);
139                                 *classname = NULL;
140                                 stat(thispath, &st);
141                                 unix_to_nt_time(last_mod_time, st.st_mtime);
142                                 SAFE_FREE(thispath);
143                                 closedir(d);
144                                 return WERR_OK;
145                         }
146                         i++;
147
148                         SAFE_FREE(thispath);
149                 }
150         }
151
152         closedir(d);
153
154         return WERR_NO_MORE_ITEMS;
155 }
156
157 WERROR reg_open_directory(TALLOC_CTX *parent_ctx,
158                           const char *location, struct hive_key **key)
159 {
160         struct dir_key *dk;
161
162         if (location == NULL)
163                 return WERR_INVALID_PARAM;
164
165         dk = talloc(parent_ctx, struct dir_key);
166         dk->key.ops = &reg_backend_dir;
167         dk->path = talloc_strdup(dk, location);
168         *key = (struct hive_key *)dk;
169         return WERR_OK;
170 }
171
172 WERROR reg_create_directory(TALLOC_CTX *parent_ctx,
173                             const char *location, struct hive_key **key)
174 {
175         if (mkdir(location, 0700) != 0) {
176                 *key = NULL;
177                 return WERR_GENERAL_FAILURE;
178         }
179
180         return reg_open_directory(parent_ctx, location, key);
181 }
182
183 static WERROR reg_dir_get_info(TALLOC_CTX *ctx, const struct hive_key *key,
184                                const char **classname,
185                                uint32_t *num_subkeys,
186                                uint32_t *num_values,
187                                NTTIME *lastmod,
188                                uint32_t *max_subkeynamelen,
189                                uint32_t *max_valnamelen,
190                                uint32_t *max_valbufsize)
191 {
192         DIR *d;
193         const struct dir_key *dk = talloc_get_type(key, struct dir_key);
194         struct dirent *e;
195         struct stat st;
196
197         SMB_ASSERT(key != NULL);
198
199         if (classname != NULL)
200                 *classname = NULL;
201
202         d = opendir(dk->path);
203         if (d == NULL)
204                 return WERR_INVALID_PARAM;
205
206         if (num_subkeys != NULL)
207                 *num_subkeys = 0;
208
209         if (num_values != NULL)
210                 *num_values = 0;
211
212         if (max_subkeynamelen != NULL)
213                 *max_subkeynamelen = 0;
214
215         if (max_valnamelen != NULL)
216                 *max_valnamelen = 0;
217
218         if (max_valbufsize != NULL)
219                 *max_valbufsize = 0;
220
221         while((e = readdir(d))) {
222                 if(!ISDOT(e->d_name) && !ISDOTDOT(e->d_name)) {
223                         char *path = talloc_asprintf(ctx, "%s/%s",
224                                                      dk->path, e->d_name);
225
226                         if (stat(path, &st) < 0) {
227                                 DEBUG(0, ("Error statting %s: %s\n", path,
228                                         strerror(errno)));
229                                 continue;
230                         }
231
232                         if (S_ISDIR(st.st_mode)) {
233                                 if (num_subkeys != NULL)
234                                         (*num_subkeys)++;
235                                 if (max_subkeynamelen != NULL)
236                                         *max_subkeynamelen = MAX(*max_subkeynamelen, strlen(e->d_name));
237                         }
238
239                         if (!S_ISDIR(st.st_mode)) {
240                                 if (num_values != NULL)
241                                         (*num_values)++;
242                                 if (max_valnamelen != NULL)
243                                         *max_valnamelen = MAX(*max_valnamelen, strlen(e->d_name));
244                                 if (max_valbufsize != NULL)
245                                         *max_valbufsize = MAX(*max_valbufsize, st.st_size);
246                         }
247
248                         talloc_free(path);
249                 }
250         }
251
252         closedir(d);
253
254         if (lastmod != NULL)
255                 *lastmod = 0;
256         return WERR_OK;
257 }
258
259 static WERROR reg_dir_set_value(struct hive_key *key, const char *name,
260                                 uint32_t type, const DATA_BLOB data)
261 {
262         const struct dir_key *dk = talloc_get_type(key, struct dir_key);
263         char *path = talloc_asprintf(dk, "%s/%s", dk->path, name);
264
265         if (!file_save(path, data.data, data.length))
266                 return WERR_GENERAL_FAILURE;
267
268         /* FIXME: Type */
269
270         return WERR_OK;
271 }
272
273 static WERROR reg_dir_get_value(TALLOC_CTX *mem_ctx,
274                                 struct hive_key *key, const char *name,
275                                 uint32_t *type, DATA_BLOB *data)
276 {
277         const struct dir_key *dk = talloc_get_type(key, struct dir_key);
278         char *path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
279         size_t size;
280         char *contents;
281
282         contents = file_load(path, &size, mem_ctx);
283         talloc_free(path);
284         if (contents == NULL)
285                 return WERR_BADFILE;
286
287         if (type != NULL)
288                 *type = 4; /* FIXME */
289
290         data->data = (uint8_t *)contents;
291         data->length = size;
292
293         return WERR_OK;
294 }
295
296 static WERROR reg_dir_enum_value(TALLOC_CTX *mem_ctx,
297                                  struct hive_key *key, int idx,
298                                  const char **name,
299                                  uint32_t *type, DATA_BLOB *data)
300 {
301         const struct dir_key *dk = talloc_get_type(key, struct dir_key);
302         DIR *d;
303         struct dirent *e;
304         int i;
305
306         d = opendir(dk->path);
307         if (d == NULL) {
308                 DEBUG(3,("Unable to open '%s': %s\n", dk->path,
309                         strerror(errno)));
310                 return WERR_BADFILE;
311         }
312
313         i = 0;
314         while((e = readdir(d))) {
315                 if (ISDOT(e->d_name) || ISDOTDOT(e->d_name))
316                         continue;
317
318                 if (i == idx) {
319                         if (name != NULL)
320                                 *name = talloc_strdup(mem_ctx, e->d_name);
321                         W_ERROR_NOT_OK_RETURN(reg_dir_get_value(mem_ctx, key,
322                                                                 *name, type,
323                                                                 data));
324                         return WERR_OK;
325                 }
326
327                 i++;
328         }
329         closedir(d);
330
331         return WERR_NO_MORE_ITEMS;
332 }
333
334
335 static WERROR reg_dir_del_value (struct hive_key *key, const char *name)
336 {
337         const struct dir_key *dk = talloc_get_type(key, struct dir_key);
338         char *path = talloc_asprintf(key, "%s/%s", dk->path, name);
339         if (unlink(path) < 0) {
340                 talloc_free(path);
341                 if (errno == ENOENT)
342                         return WERR_BADFILE;
343                 return WERR_GENERAL_FAILURE;
344         }
345         talloc_free(path);
346
347         return WERR_OK;
348 }
349
350 static struct hive_operations reg_backend_dir = {
351         .name = "dir",
352         .get_key_by_name = reg_dir_open_key,
353         .get_key_info = reg_dir_get_info,
354         .add_key = reg_dir_add_key,
355         .del_key = reg_dir_del_key,
356         .enum_key = reg_dir_key_by_index,
357         .set_value = reg_dir_set_value,
358         .get_value_by_name = reg_dir_get_value,
359         .enum_value = reg_dir_enum_value,
360         .delete_value = reg_dir_del_value,
361 };