source: vendor/3.6.0/source4/lib/registry/dir.c

Last change on this file was 740, checked in by Silvan Scherrer, 13 years ago

Samba Server: update vendor to 3.6.0

File size: 10.2 KB
Line 
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 "registry.h"
22#include "system/dir.h"
23#include "system/filesys.h"
24
25struct dir_key {
26 struct hive_key key;
27 const char *path;
28};
29
30static struct hive_operations reg_backend_dir;
31
32static 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 W_ERROR_HAVE_NO_MEMORY(path);
44 ret = mkdir(path, 0700);
45 if (ret == 0) {
46 struct dir_key *key = talloc(mem_ctx, struct dir_key);
47 W_ERROR_HAVE_NO_MEMORY(key);
48 key->key.ops = &reg_backend_dir;
49 key->path = talloc_steal(key, path);
50 *result = (struct hive_key *)key;
51 return WERR_OK;
52 }
53
54 if (errno == EEXIST)
55 return WERR_ALREADY_EXISTS;
56 printf("FAILED %s BECAUSE: %s\n", path, strerror(errno));
57 return WERR_GENERAL_FAILURE;
58}
59
60static WERROR reg_dir_delete_recursive(const char *name)
61{
62 DIR *d;
63 struct dirent *e;
64 WERROR werr;
65
66 d = opendir(name);
67 if (d == NULL) {
68 DEBUG(3,("Unable to open '%s': %s\n", name,
69 strerror(errno)));
70 return WERR_BADFILE;
71 }
72
73 while((e = readdir(d))) {
74 char *path;
75 struct stat stbuf;
76
77 if (ISDOT(e->d_name) || ISDOTDOT(e->d_name))
78 continue;
79
80 path = talloc_asprintf(name, "%s/%s", name, e->d_name);
81 W_ERROR_HAVE_NO_MEMORY(path);
82
83 stat(path, &stbuf);
84
85 if (!S_ISDIR(stbuf.st_mode)) {
86 if (unlink(path) < 0) {
87 talloc_free(path);
88 closedir(d);
89 return WERR_GENERAL_FAILURE;
90 }
91 } else {
92 werr = reg_dir_delete_recursive(path);
93 if (!W_ERROR_IS_OK(werr)) {
94 talloc_free(path);
95 closedir(d);
96 return werr;
97 }
98 }
99
100 talloc_free(path);
101 }
102 closedir(d);
103
104 if (rmdir(name) == 0)
105 return WERR_OK;
106 else if (errno == ENOENT)
107 return WERR_BADFILE;
108 else
109 return WERR_GENERAL_FAILURE;
110}
111
112static WERROR reg_dir_del_key(TALLOC_CTX *mem_ctx, const struct hive_key *k,
113 const char *name)
114{
115 struct dir_key *dk = talloc_get_type(k, struct dir_key);
116 char *child;
117 WERROR ret;
118
119 child = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
120 W_ERROR_HAVE_NO_MEMORY(child);
121
122 ret = reg_dir_delete_recursive(child);
123
124 talloc_free(child);
125
126 return ret;
127}
128
129static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx,
130 const struct hive_key *parent,
131 const char *name, struct hive_key **subkey)
132{
133 DIR *d;
134 char *fullpath;
135 const struct dir_key *p = talloc_get_type(parent, struct dir_key);
136 struct dir_key *ret;
137
138 if (name == NULL) {
139 DEBUG(0, ("NULL pointer passed as directory name!"));
140 return WERR_INVALID_PARAM;
141 }
142
143 fullpath = talloc_asprintf(mem_ctx, "%s/%s", p->path, name);
144 W_ERROR_HAVE_NO_MEMORY(fullpath);
145
146 d = opendir(fullpath);
147 if (d == NULL) {
148 DEBUG(3,("Unable to open '%s': %s\n", fullpath,
149 strerror(errno)));
150 talloc_free(fullpath);
151 return WERR_BADFILE;
152 }
153 closedir(d);
154 ret = talloc(mem_ctx, struct dir_key);
155 ret->key.ops = &reg_backend_dir;
156 ret->path = talloc_steal(ret, fullpath);
157 *subkey = (struct hive_key *)ret;
158 return WERR_OK;
159}
160
161static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx,
162 const struct hive_key *k, uint32_t idx,
163 const char **name,
164 const char **classname,
165 NTTIME *last_mod_time)
166{
167 struct dirent *e;
168 const struct dir_key *dk = talloc_get_type(k, struct dir_key);
169 unsigned int i = 0;
170 DIR *d;
171
172 d = opendir(dk->path);
173
174 if (d == NULL)
175 return WERR_INVALID_PARAM;
176
177 while((e = readdir(d))) {
178 if(!ISDOT(e->d_name) && !ISDOTDOT(e->d_name)) {
179 struct stat stbuf;
180 char *thispath;
181
182 /* Check if file is a directory */
183 thispath = talloc_asprintf(mem_ctx, "%s/%s", dk->path,
184 e->d_name);
185 W_ERROR_HAVE_NO_MEMORY(thispath);
186 stat(thispath, &stbuf);
187
188 if (!S_ISDIR(stbuf.st_mode)) {
189 talloc_free(thispath);
190 continue;
191 }
192
193 if (i == idx) {
194 struct stat st;
195 *name = talloc_strdup(mem_ctx, e->d_name);
196 W_ERROR_HAVE_NO_MEMORY(*name);
197 *classname = NULL;
198 stat(thispath, &st);
199 unix_to_nt_time(last_mod_time, st.st_mtime);
200 talloc_free(thispath);
201 closedir(d);
202 return WERR_OK;
203 }
204 i++;
205
206 talloc_free(thispath);
207 }
208 }
209
210 closedir(d);
211
212 return WERR_NO_MORE_ITEMS;
213}
214
215WERROR reg_open_directory(TALLOC_CTX *parent_ctx,
216 const char *location, struct hive_key **key)
217{
218 struct dir_key *dk;
219
220 if (location == NULL)
221 return WERR_INVALID_PARAM;
222
223 dk = talloc(parent_ctx, struct dir_key);
224 W_ERROR_HAVE_NO_MEMORY(dk);
225 dk->key.ops = &reg_backend_dir;
226 dk->path = talloc_strdup(dk, location);
227 *key = (struct hive_key *)dk;
228 return WERR_OK;
229}
230
231WERROR reg_create_directory(TALLOC_CTX *parent_ctx,
232 const char *location, struct hive_key **key)
233{
234 if (mkdir(location, 0700) != 0) {
235 *key = NULL;
236 return WERR_GENERAL_FAILURE;
237 }
238
239 return reg_open_directory(parent_ctx, location, key);
240}
241
242static WERROR reg_dir_get_info(TALLOC_CTX *ctx, const struct hive_key *key,
243 const char **classname,
244 uint32_t *num_subkeys,
245 uint32_t *num_values,
246 NTTIME *lastmod,
247 uint32_t *max_subkeynamelen,
248 uint32_t *max_valnamelen,
249 uint32_t *max_valbufsize)
250{
251 DIR *d;
252 const struct dir_key *dk = talloc_get_type(key, struct dir_key);
253 struct dirent *e;
254 struct stat st;
255
256 SMB_ASSERT(key != NULL);
257
258 if (classname != NULL)
259 *classname = NULL;
260
261 d = opendir(dk->path);
262 if (d == NULL)
263 return WERR_INVALID_PARAM;
264
265 if (num_subkeys != NULL)
266 *num_subkeys = 0;
267
268 if (num_values != NULL)
269 *num_values = 0;
270
271 if (max_subkeynamelen != NULL)
272 *max_subkeynamelen = 0;
273
274 if (max_valnamelen != NULL)
275 *max_valnamelen = 0;
276
277 if (max_valbufsize != NULL)
278 *max_valbufsize = 0;
279
280 while((e = readdir(d))) {
281 if(!ISDOT(e->d_name) && !ISDOTDOT(e->d_name)) {
282 char *path = talloc_asprintf(ctx, "%s/%s",
283 dk->path, e->d_name);
284 W_ERROR_HAVE_NO_MEMORY(path);
285
286 if (stat(path, &st) < 0) {
287 DEBUG(0, ("Error statting %s: %s\n", path,
288 strerror(errno)));
289 talloc_free(path);
290 continue;
291 }
292
293 if (S_ISDIR(st.st_mode)) {
294 if (num_subkeys != NULL)
295 (*num_subkeys)++;
296 if (max_subkeynamelen != NULL)
297 *max_subkeynamelen = MAX(*max_subkeynamelen, strlen(e->d_name));
298 }
299
300 if (!S_ISDIR(st.st_mode)) {
301 if (num_values != NULL)
302 (*num_values)++;
303 if (max_valnamelen != NULL)
304 *max_valnamelen = MAX(*max_valnamelen, strlen(e->d_name));
305 if (max_valbufsize != NULL)
306 *max_valbufsize = MAX(*max_valbufsize, st.st_size);
307 }
308
309 talloc_free(path);
310 }
311 }
312
313 closedir(d);
314
315 if (lastmod != NULL)
316 *lastmod = 0;
317 return WERR_OK;
318}
319
320static WERROR reg_dir_set_value(struct hive_key *key, const char *name,
321 uint32_t type, const DATA_BLOB data)
322{
323 const struct dir_key *dk = talloc_get_type(key, struct dir_key);
324 char *path;
325 bool ret;
326
327 path = talloc_asprintf(dk, "%s/%s", dk->path, name);
328 W_ERROR_HAVE_NO_MEMORY(path);
329
330 ret = file_save(path, data.data, data.length);
331
332 talloc_free(path);
333
334 if (!ret) {
335 return WERR_GENERAL_FAILURE;
336 }
337
338 /* FIXME: Type */
339
340 return WERR_OK;
341}
342
343static WERROR reg_dir_get_value(TALLOC_CTX *mem_ctx,
344 struct hive_key *key, const char *name,
345 uint32_t *type, DATA_BLOB *data)
346{
347 const struct dir_key *dk = talloc_get_type(key, struct dir_key);
348 char *path;
349 size_t size;
350 char *contents;
351
352 path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
353 W_ERROR_HAVE_NO_MEMORY(path);
354
355 contents = file_load(path, &size, 0, mem_ctx);
356
357 talloc_free(path);
358
359 if (contents == NULL)
360 return WERR_BADFILE;
361
362 if (type != NULL)
363 *type = 4; /* FIXME */
364
365 data->data = (uint8_t *)contents;
366 data->length = size;
367
368 return WERR_OK;
369}
370
371static WERROR reg_dir_enum_value(TALLOC_CTX *mem_ctx,
372 struct hive_key *key, uint32_t idx,
373 const char **name,
374 uint32_t *type, DATA_BLOB *data)
375{
376 const struct dir_key *dk = talloc_get_type(key, struct dir_key);
377 DIR *d;
378 struct dirent *e;
379 unsigned int i;
380
381 d = opendir(dk->path);
382 if (d == NULL) {
383 DEBUG(3,("Unable to open '%s': %s\n", dk->path,
384 strerror(errno)));
385 return WERR_BADFILE;
386 }
387
388 i = 0;
389 while((e = readdir(d))) {
390 if (ISDOT(e->d_name) || ISDOTDOT(e->d_name))
391 continue;
392
393 if (i == idx) {
394 if (name != NULL) {
395 *name = talloc_strdup(mem_ctx, e->d_name);
396 W_ERROR_HAVE_NO_MEMORY(*name);
397 }
398 W_ERROR_NOT_OK_RETURN(reg_dir_get_value(mem_ctx, key,
399 *name, type,
400 data));
401 return WERR_OK;
402 }
403
404 i++;
405 }
406 closedir(d);
407
408 return WERR_NO_MORE_ITEMS;
409}
410
411
412static WERROR reg_dir_del_value(TALLOC_CTX *mem_ctx,
413 struct hive_key *key, const char *name)
414{
415 const struct dir_key *dk = talloc_get_type(key, struct dir_key);
416 char *path;
417 int ret;
418
419 path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
420 W_ERROR_HAVE_NO_MEMORY(path);
421
422 ret = unlink(path);
423
424 talloc_free(path);
425
426 if (ret < 0) {
427 if (errno == ENOENT)
428 return WERR_BADFILE;
429 return WERR_GENERAL_FAILURE;
430 }
431
432 return WERR_OK;
433}
434
435static struct hive_operations reg_backend_dir = {
436 .name = "dir",
437 .get_key_by_name = reg_dir_open_key,
438 .get_key_info = reg_dir_get_info,
439 .add_key = reg_dir_add_key,
440 .del_key = reg_dir_del_key,
441 .enum_key = reg_dir_key_by_index,
442 .set_value = reg_dir_set_value,
443 .get_value_by_name = reg_dir_get_value,
444 .enum_value = reg_dir_enum_value,
445 .delete_value = reg_dir_del_value,
446};
Note: See TracBrowser for help on using the repository browser.