summaryrefslogtreecommitdiff
path: root/source4/lib/registry/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/registry/dir.c')
-rw-r--r--source4/lib/registry/dir.c333
1 files changed, 333 insertions, 0 deletions
diff --git a/source4/lib/registry/dir.c b/source4/lib/registry/dir.c
new file mode 100644
index 0000000000..146c5197fd
--- /dev/null
+++ b/source4/lib/registry/dir.c
@@ -0,0 +1,333 @@
+/*
+ Unix SMB/CIFS implementation.
+ Registry interface
+ Copyright (C) Jelmer Vernooij 2004-2007.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "hive.h"
+#include "system/dir.h"
+#include "system/filesys.h"
+
+struct dir_key {
+ struct hive_key key;
+ const char *path;
+};
+
+static struct hive_operations reg_backend_dir;
+
+static WERROR reg_dir_add_key(TALLOC_CTX *mem_ctx,
+ const struct hive_key *parent,
+ const char *name, const char *classname,
+ struct security_descriptor *desc,
+ struct hive_key **result)
+{
+ struct dir_key *dk = talloc_get_type(parent, struct dir_key);
+ char *path;
+ int ret;
+
+ path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
+ ret = mkdir(path, 0700);
+ if (ret == 0) {
+ struct dir_key *key = talloc(mem_ctx, struct dir_key);
+ key->key.ops = &reg_backend_dir;
+ key->path = talloc_steal(key, path);
+ *result = (struct hive_key *)key;
+ return WERR_OK;
+ }
+
+ if (errno == EEXIST)
+ return WERR_ALREADY_EXISTS;
+ printf("FAILED %s BECAUSE: %s\n", path, strerror(errno));
+ return WERR_GENERAL_FAILURE;
+}
+
+static WERROR reg_dir_del_key(const struct hive_key *k, const char *name)
+{
+ struct dir_key *dk = talloc_get_type(k, struct dir_key);
+ char *child = talloc_asprintf(NULL, "%s/%s", dk->path, name);
+ WERROR ret;
+
+ if (rmdir(child) == 0)
+ ret = WERR_OK;
+ else if (errno == ENOENT)
+ ret = WERR_NOT_FOUND;
+ else
+ ret = WERR_GENERAL_FAILURE;
+
+ talloc_free(child);
+
+ return ret;
+}
+
+static WERROR reg_dir_open_key(TALLOC_CTX *mem_ctx,
+ const struct hive_key *parent,
+ const char *name, struct hive_key **subkey)
+{
+ DIR *d;
+ char *fullpath;
+ const struct dir_key *p = talloc_get_type(parent, struct dir_key);
+ struct dir_key *ret;
+
+ if (name == NULL) {
+ DEBUG(0, ("NULL pointer passed as directory name!"));
+ return WERR_INVALID_PARAM;
+ }
+
+ fullpath = talloc_asprintf(mem_ctx, "%s/%s", p->path, name);
+
+ d = opendir(fullpath);
+ if (d == NULL) {
+ DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno)));
+ return WERR_BADFILE;
+ }
+ closedir(d);
+ ret = talloc(mem_ctx, struct dir_key);
+ ret->key.ops = &reg_backend_dir;
+ ret->path = talloc_steal(ret, fullpath);
+ *subkey = (struct hive_key *)ret;
+ return WERR_OK;
+}
+
+static WERROR reg_dir_key_by_index(TALLOC_CTX *mem_ctx,
+ const struct hive_key *k, uint32_t idx,
+ const char **name,
+ const char **classname,
+ NTTIME *last_mod_time)
+{
+ struct dirent *e;
+ const struct dir_key *dk = talloc_get_type(k, struct dir_key);
+ int i = 0;
+ DIR *d;
+
+ d = opendir(dk->path);
+
+ if (d == NULL)
+ return WERR_INVALID_PARAM;
+
+ while((e = readdir(d))) {
+ if(!ISDOT(e->d_name) && !ISDOTDOT(e->d_name)) {
+ struct stat stbuf;
+ char *thispath;
+
+ /* Check if file is a directory */
+ asprintf(&thispath, "%s/%s", dk->path, e->d_name);
+ stat(thispath, &stbuf);
+
+ if (!S_ISDIR(stbuf.st_mode)) {
+ SAFE_FREE(thispath);
+ continue;
+ }
+
+ if (i == idx) {
+ struct stat st;
+ *name = talloc_strdup(mem_ctx, e->d_name);
+ *classname = NULL;
+ stat(thispath, &st);
+ unix_to_nt_time(last_mod_time, st.st_mtime);
+ SAFE_FREE(thispath);
+ closedir(d);
+ return WERR_OK;
+ }
+ i++;
+
+ SAFE_FREE(thispath);
+ }
+ }
+
+ closedir(d);
+
+ return WERR_NO_MORE_ITEMS;
+}
+
+WERROR reg_open_directory(TALLOC_CTX *parent_ctx,
+ const char *location, struct hive_key **key)
+{
+ struct dir_key *dk;
+
+ if (location == NULL)
+ return WERR_INVALID_PARAM;
+
+ dk = talloc(parent_ctx, struct dir_key);
+ dk->key.ops = &reg_backend_dir;
+ dk->path = talloc_strdup(dk, location);
+ *key = (struct hive_key *)dk;
+ return WERR_OK;
+}
+
+WERROR reg_create_directory(TALLOC_CTX *parent_ctx,
+ const char *location, struct hive_key **key)
+{
+ if (mkdir(location, 0700) != 0) {
+ *key = NULL;
+ return WERR_GENERAL_FAILURE;
+ }
+
+ return reg_open_directory(parent_ctx, location, key);
+}
+
+static WERROR reg_dir_get_info(TALLOC_CTX *ctx, const struct hive_key *key,
+ const char **classname,
+ uint32_t *num_subkeys,
+ uint32_t *num_values,
+ NTTIME *lastmod)
+{
+ DIR *d;
+ const struct dir_key *dk = talloc_get_type(key, struct dir_key);
+ struct dirent *e;
+ struct stat st;
+
+ SMB_ASSERT(key != NULL);
+
+ if (classname != NULL)
+ *classname = NULL;
+
+ d = opendir(dk->path);
+ if (d == NULL)
+ return WERR_INVALID_PARAM;
+
+ if (num_subkeys != NULL)
+ *num_subkeys = 0;
+
+ if (num_values != NULL)
+ *num_values = 0;
+
+ while((e = readdir(d))) {
+ if(!ISDOT(e->d_name) && !ISDOTDOT(e->d_name)) {
+ char *path = talloc_asprintf(ctx, "%s/%s", dk->path, e->d_name);
+
+ if (stat(path, &st) < 0) {
+ DEBUG(0, ("Error statting %s: %s\n", path, strerror(errno)));
+ continue;
+ }
+
+ if (S_ISDIR(st.st_mode) && num_subkeys != NULL)
+ (*num_subkeys)++;
+
+ if (!S_ISDIR(st.st_mode) && num_values != NULL)
+ (*num_values)++;
+
+ talloc_free(path);
+ }
+ }
+
+ closedir(d);
+
+ if (lastmod != NULL)
+ *lastmod = 0;
+ return WERR_OK;
+}
+
+static WERROR reg_dir_set_value (struct hive_key *key, const char *name,
+ uint32_t type, const DATA_BLOB data)
+{
+ const struct dir_key *dk = talloc_get_type(key, struct dir_key);
+ char *path = talloc_asprintf(dk, "%s/%s", dk->path, name);
+
+ if (!file_save(path, data.data, data.length))
+ return WERR_GENERAL_FAILURE;
+
+ /* FIXME: Type */
+
+ return WERR_OK;
+}
+
+static WERROR reg_dir_get_value (TALLOC_CTX *mem_ctx,
+ struct hive_key *key, const char *name,
+ uint32_t *type, DATA_BLOB *data)
+{
+ const struct dir_key *dk = talloc_get_type(key, struct dir_key);
+ char *path = talloc_asprintf(mem_ctx, "%s/%s", dk->path, name);
+ size_t size;
+ char *contents;
+
+ contents = file_load(path, &size, mem_ctx);
+ talloc_free(path);
+ if (contents == NULL)
+ return WERR_NOT_FOUND;
+
+ if (type != NULL)
+ *type = 4; /* FIXME */
+
+ data->data = (uint8_t *)contents;
+ data->length = size;
+
+ return WERR_OK;
+}
+
+static WERROR reg_dir_enum_value (TALLOC_CTX *mem_ctx,
+ const struct hive_key *key, int idx,
+ const char **name,
+ uint32_t *type, DATA_BLOB *data)
+{
+ const struct dir_key *dk = talloc_get_type(key, struct dir_key);
+ DIR *d;
+ struct dirent *e;
+ int i;
+
+ d = opendir(dk->path);
+ if (d == NULL) {
+ DEBUG(3,("Unable to open '%s': %s\n", dk->path, strerror(errno)));
+ return WERR_BADFILE;
+ }
+
+ i = 0;
+ while((e = readdir(d))) {
+ if (ISDOT(e->d_name) || ISDOTDOT(e->d_name))
+ continue;
+
+ if (i == idx) {
+ if (name != NULL)
+ *name = talloc_strdup(mem_ctx, e->d_name);
+ W_ERROR_NOT_OK_RETURN(reg_dir_get_value(mem_ctx, key, *name, type, data));
+ return WERR_OK;
+ }
+
+ i++;
+ }
+ closedir(d);
+
+ return WERR_NO_MORE_ITEMS;
+}
+
+
+static WERROR reg_dir_del_value (struct hive_key *key, const char *name)
+{
+ const struct dir_key *dk = talloc_get_type(key, struct dir_key);
+ char *path = talloc_asprintf(key, "%s/%s", dk->path, name);
+ if (unlink(path) < 0) {
+ talloc_free(path);
+ if (errno == ENOENT)
+ return WERR_NOT_FOUND;
+ return WERR_GENERAL_FAILURE;
+ }
+ talloc_free(path);
+
+ return WERR_OK;
+}
+
+static struct hive_operations reg_backend_dir = {
+ .name = "dir",
+ .get_key_by_name = reg_dir_open_key,
+ .get_key_info = reg_dir_get_info,
+ .add_key = reg_dir_add_key,
+ .del_key = reg_dir_del_key,
+ .enum_key = reg_dir_key_by_index,
+ .set_value = reg_dir_set_value,
+ .get_value_by_name = reg_dir_get_value,
+ .enum_value = reg_dir_enum_value,
+ .delete_value = reg_dir_del_value,
+};