From 59859b547c81bf398d12a1f9b206a32c6fd55433 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 28 Jan 2009 08:52:53 +0100 Subject: s3: separate tdb validation code out into its own source file So this gets now linked only into its single user: winbindd (needed by winbindd_cache.c) Michael --- source3/lib/tdb_validate.c | 502 +++++++++++++++++++++++++++++++++++++++++++++ source3/lib/tdb_validate.h | 78 +++++++ source3/lib/util_tdb.c | 484 ------------------------------------------- 3 files changed, 580 insertions(+), 484 deletions(-) create mode 100644 source3/lib/tdb_validate.c create mode 100644 source3/lib/tdb_validate.h (limited to 'source3/lib') diff --git a/source3/lib/tdb_validate.c b/source3/lib/tdb_validate.c new file mode 100644 index 0000000000..c1ca97787c --- /dev/null +++ b/source3/lib/tdb_validate.c @@ -0,0 +1,502 @@ +/* + * Unix SMB/CIFS implementation. + * + * A general tdb content validation mechanism + * + * Copyright (C) Michael Adam 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 . + */ + +#include "includes.h" +#include "tdb_validate.h" + +/* + * internal validation function, executed by the child. + */ +static int tdb_validate_child(struct tdb_context *tdb, + tdb_validate_data_func validate_fn) +{ + int ret = 1; + int num_entries = 0; + struct tdb_validation_status v_status; + + v_status.tdb_error = False; + v_status.bad_freelist = False; + v_status.bad_entry = False; + v_status.unknown_key = False; + v_status.success = True; + + if (!tdb) { + v_status.tdb_error = True; + v_status.success = False; + goto out; + } + + /* Check if the tdb's freelist is good. */ + if (tdb_validate_freelist(tdb, &num_entries) == -1) { + v_status.bad_freelist = True; + v_status.success = False; + goto out; + } + + DEBUG(10,("tdb_validate_child: tdb %s freelist has %d entries\n", + tdb_name(tdb), num_entries)); + + /* Now traverse the tdb to validate it. */ + num_entries = tdb_traverse(tdb, validate_fn, (void *)&v_status); + if (!v_status.success) { + goto out; + } else if (num_entries == -1) { + v_status.tdb_error = True; + v_status.success = False; + goto out; + } + + DEBUG(10,("tdb_validate_child: tdb %s is good with %d entries\n", + tdb_name(tdb), num_entries)); + ret = 0; /* Cache is good. */ + +out: + DEBUG(10, ("tdb_validate_child: summary of validation status:\n")); + DEBUGADD(10,(" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no")); + DEBUGADD(10,(" * bad freelist: %s\n",v_status.bad_freelist?"yes":"no")); + DEBUGADD(10,(" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no")); + DEBUGADD(10,(" * unknown key: %s\n", v_status.unknown_key?"yes":"no")); + DEBUGADD(10,(" => overall success: %s\n", v_status.success?"yes":"no")); + + return ret; +} + +/* + * tdb validation function. + * returns 0 if tdb is ok, != 0 if it isn't. + * this function expects an opened tdb. + */ +int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn) +{ + pid_t child_pid = -1; + int child_status = 0; + int wait_pid = 0; + int ret = 1; + + if (tdb == NULL) { + DEBUG(1, ("Error: tdb_validate called with tdb == NULL\n")); + return ret; + } + + DEBUG(5, ("tdb_validate called for tdb '%s'\n", tdb_name(tdb))); + + /* fork and let the child do the validation. + * benefit: no need to twist signal handlers and panic functions. + * just let the child panic. we catch the signal. */ + + DEBUG(10, ("tdb_validate: forking to let child do validation.\n")); + child_pid = sys_fork(); + if (child_pid == 0) { + /* child code */ + DEBUG(10, ("tdb_validate (validation child): created\n")); + DEBUG(10, ("tdb_validate (validation child): " + "calling tdb_validate_child\n")); + exit(tdb_validate_child(tdb, validate_fn)); + } + else if (child_pid < 0) { + DEBUG(1, ("tdb_validate: fork for validation failed.\n")); + goto done; + } + + /* parent */ + + DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n",child_pid)); + + DEBUG(10, ("tdb_validate: waiting for child to finish...\n")); + while ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) { + if (errno == EINTR) { + DEBUG(10, ("tdb_validate: got signal during waitpid, " + "retrying\n")); + errno = 0; + continue; + } + DEBUG(1, ("tdb_validate: waitpid failed with error '%s'.\n", + strerror(errno))); + goto done; + } + if (wait_pid != child_pid) { + DEBUG(1, ("tdb_validate: waitpid returned pid %d, " + "but %d was expected\n", wait_pid, child_pid)); + goto done; + } + + DEBUG(10, ("tdb_validate: validating child returned.\n")); + if (WIFEXITED(child_status)) { + DEBUG(10, ("tdb_validate: child exited, code %d.\n", + WEXITSTATUS(child_status))); + ret = WEXITSTATUS(child_status); + } + if (WIFSIGNALED(child_status)) { + DEBUG(10, ("tdb_validate: child terminated by signal %d\n", + WTERMSIG(child_status))); +#ifdef WCOREDUMP + if (WCOREDUMP(child_status)) { + DEBUGADD(10, ("core dumped\n")); + } +#endif + ret = WTERMSIG(child_status); + } + if (WIFSTOPPED(child_status)) { + DEBUG(10, ("tdb_validate: child was stopped by signal %d\n", + WSTOPSIG(child_status))); + ret = WSTOPSIG(child_status); + } + +done: + DEBUG(5, ("tdb_validate returning code '%d' for tdb '%s'\n", ret, + tdb_name(tdb))); + + return ret; +} + +/* + * tdb validation function. + * returns 0 if tdb is ok, != 0 if it isn't. + * this is a wrapper around the actual validation function that opens and closes + * the tdb. + */ +int tdb_validate_open(const char *tdb_path, tdb_validate_data_func validate_fn) +{ + TDB_CONTEXT *tdb = NULL; + int ret = 1; + + DEBUG(5, ("tdb_validate_open called for tdb '%s'\n", tdb_path)); + + tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDONLY, 0); + if (!tdb) { + DEBUG(1, ("Error opening tdb %s\n", tdb_path)); + return ret; + } + + ret = tdb_validate(tdb, validate_fn); + tdb_close(tdb); + return ret; +} + +/* + * tdb backup function and helpers for tdb_validate wrapper with backup + * handling. + */ + +/* this structure eliminates the need for a global overall status for + * the traverse-copy */ +struct tdb_copy_data { + struct tdb_context *dst; + bool success; +}; + +static int traverse_copy_fn(struct tdb_context *tdb, TDB_DATA key, + TDB_DATA dbuf, void *private_data) +{ + struct tdb_copy_data *data = (struct tdb_copy_data *)private_data; + + if (tdb_store(data->dst, key, dbuf, TDB_INSERT) != 0) { + DEBUG(4, ("Failed to insert into %s: %s\n", tdb_name(data->dst), + strerror(errno))); + data->success = False; + return 1; + } + return 0; +} + +static int tdb_copy(struct tdb_context *src, struct tdb_context *dst) +{ + struct tdb_copy_data data; + int count; + + data.dst = dst; + data.success = True; + + count = tdb_traverse(src, traverse_copy_fn, (void *)(&data)); + if ((count < 0) || (data.success == False)) { + return -1; + } + return count; +} + +static int tdb_verify_basic(struct tdb_context *tdb) +{ + return tdb_traverse(tdb, NULL, NULL); +} + +/* this backup function is essentially taken from lib/tdb/tools/tdbbackup.tdb + */ +static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, + const char *dst_path, int hash_size) +{ + struct tdb_context *src_tdb = NULL; + struct tdb_context *dst_tdb = NULL; + char *tmp_path = NULL; + struct stat st; + int count1, count2; + int saved_errno = 0; + int ret = -1; + + if (stat(src_path, &st) != 0) { + DEBUG(3, ("Could not stat '%s': %s\n", src_path, + strerror(errno))); + goto done; + } + + /* open old tdb RDWR - so we can lock it */ + src_tdb = tdb_open_log(src_path, 0, TDB_DEFAULT, O_RDWR, 0); + if (src_tdb == NULL) { + DEBUG(3, ("Failed to open tdb '%s'\n", src_path)); + goto done; + } + + if (tdb_lockall(src_tdb) != 0) { + DEBUG(3, ("Failed to lock tdb '%s'\n", src_path)); + goto done; + } + + tmp_path = talloc_asprintf(ctx, "%s%s", dst_path, ".tmp"); + unlink(tmp_path); + dst_tdb = tdb_open_log(tmp_path, + hash_size ? hash_size : tdb_hash_size(src_tdb), + TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, + st.st_mode & 0777); + if (dst_tdb == NULL) { + DEBUG(3, ("Error creating tdb '%s': %s\n", tmp_path, + strerror(errno))); + saved_errno = errno; + unlink(tmp_path); + goto done; + } + + count1 = tdb_copy(src_tdb, dst_tdb); + if (count1 < 0) { + DEBUG(3, ("Failed to copy tdb '%s': %s\n", src_path, + strerror(errno))); + tdb_close(dst_tdb); + goto done; + } + + /* reopen ro and do basic verification */ + tdb_close(dst_tdb); + dst_tdb = tdb_open_log(tmp_path, 0, TDB_DEFAULT, O_RDONLY, 0); + if (!dst_tdb) { + DEBUG(3, ("Failed to reopen tdb '%s': %s\n", tmp_path, + strerror(errno))); + goto done; + } + count2 = tdb_verify_basic(dst_tdb); + if (count2 != count1) { + DEBUG(3, ("Failed to verify result of copying tdb '%s'.\n", + src_path)); + tdb_close(dst_tdb); + goto done; + } + + DEBUG(10, ("tdb_backup: successfully copied %d entries\n", count1)); + + /* make sure the new tdb has reached stable storage + * then rename it to its destination */ + fsync(tdb_fd(dst_tdb)); + tdb_close(dst_tdb); + unlink(dst_path); + if (rename(tmp_path, dst_path) != 0) { + DEBUG(3, ("Failed to rename '%s' to '%s': %s\n", + tmp_path, dst_path, strerror(errno))); + goto done; + } + + /* success */ + ret = 0; + +done: + if (src_tdb != NULL) { + tdb_close(src_tdb); + } + if (tmp_path != NULL) { + unlink(tmp_path); + TALLOC_FREE(tmp_path); + } + if (saved_errno != 0) { + errno = saved_errno; + } + return ret; +} + +static int rename_file_with_suffix(TALLOC_CTX *ctx, const char *path, + const char *suffix) +{ + int ret = -1; + char *dst_path; + + dst_path = talloc_asprintf(ctx, "%s%s", path, suffix); + + ret = (rename(path, dst_path) != 0); + + if (ret == 0) { + DEBUG(5, ("moved '%s' to '%s'\n", path, dst_path)); + } else if (errno == ENOENT) { + DEBUG(3, ("file '%s' does not exist - so not moved\n", path)); + ret = 0; + } else { + DEBUG(3, ("error renaming %s to %s: %s\n", path, dst_path, + strerror(errno))); + } + + TALLOC_FREE(dst_path); + return ret; +} + +/* + * do a backup of a tdb, moving the destination out of the way first + */ +static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path, + const char *dst_path, int hash_size, + const char *rotate_suffix, + bool retry_norotate_if_nospc, + bool rename_as_last_resort_if_nospc) +{ + int ret; + + rename_file_with_suffix(ctx, dst_path, rotate_suffix); + + ret = tdb_backup(ctx, src_path, dst_path, hash_size); + + if (ret != 0) { + DEBUG(10, ("backup of %s failed: %s\n", src_path, strerror(errno))); + } + if ((ret != 0) && (errno == ENOSPC) && retry_norotate_if_nospc) + { + char *rotate_path = talloc_asprintf(ctx, "%s%s", dst_path, + rotate_suffix); + DEBUG(10, ("backup of %s failed due to lack of space\n", + src_path)); + DEBUGADD(10, ("trying to free some space by removing rotated " + "dst %s\n", rotate_path)); + if (unlink(rotate_path) == -1) { + DEBUG(10, ("unlink of %s failed: %s\n", rotate_path, + strerror(errno))); + } else { + ret = tdb_backup(ctx, src_path, dst_path, hash_size); + } + TALLOC_FREE(rotate_path); + } + + if ((ret != 0) && (errno == ENOSPC) && rename_as_last_resort_if_nospc) + { + DEBUG(10, ("backup of %s failed due to lack of space\n", + src_path)); + DEBUGADD(10, ("using 'rename' as a last resort\n")); + ret = rename(src_path, dst_path); + } + + return ret; +} + +/* + * validation function with backup handling: + * + * - calls tdb_validate + * - if the tdb is ok, create a backup "name.bak", possibly moving + * existing backup to name.bak.old, + * return 0 (success) even if the backup fails + * - if the tdb is corrupt: + * - move the tdb to "name.corrupt" + * - check if there is valid backup. + * if so, restore the backup. + * if restore is successful, return 0 (success), + * - otherwise return -1 (failure) + */ +int tdb_validate_and_backup(const char *tdb_path, + tdb_validate_data_func validate_fn) +{ + int ret = -1; + const char *backup_suffix = ".bak"; + const char *corrupt_suffix = ".corrupt"; + const char *rotate_suffix = ".old"; + char *tdb_path_backup; + struct stat st; + TALLOC_CTX *ctx = NULL; + + ctx = talloc_new(NULL); + if (ctx == NULL) { + DEBUG(0, ("tdb_validate_and_backup: out of memory\n")); + goto done; + } + + tdb_path_backup = talloc_asprintf(ctx, "%s%s", tdb_path, backup_suffix); + + ret = tdb_validate_open(tdb_path, validate_fn); + + if (ret == 0) { + DEBUG(1, ("tdb '%s' is valid\n", tdb_path)); + ret = tdb_backup_with_rotate(ctx, tdb_path, tdb_path_backup, 0, + rotate_suffix, True, False); + if (ret != 0) { + DEBUG(1, ("Error creating backup of tdb '%s'\n", + tdb_path)); + /* the actual validation was successful: */ + ret = 0; + } else { + DEBUG(1, ("Created backup '%s' of tdb '%s'\n", + tdb_path_backup, tdb_path)); + } + } else { + DEBUG(1, ("tdb '%s' is invalid\n", tdb_path)); + + ret =stat(tdb_path_backup, &st); + if (ret != 0) { + DEBUG(5, ("Could not stat '%s': %s\n", tdb_path_backup, + strerror(errno))); + DEBUG(1, ("No backup found.\n")); + } else { + DEBUG(1, ("backup '%s' found.\n", tdb_path_backup)); + ret = tdb_validate_open(tdb_path_backup, validate_fn); + if (ret != 0) { + DEBUG(1, ("Backup '%s' is invalid.\n", + tdb_path_backup)); + } + } + + if (ret != 0) { + int renamed = rename_file_with_suffix(ctx, tdb_path, + corrupt_suffix); + if (renamed != 0) { + DEBUG(1, ("Error moving tdb to '%s%s'\n", + tdb_path, corrupt_suffix)); + } else { + DEBUG(1, ("Corrupt tdb stored as '%s%s'\n", + tdb_path, corrupt_suffix)); + } + goto done; + } + + DEBUG(1, ("valid backup '%s' found\n", tdb_path_backup)); + ret = tdb_backup_with_rotate(ctx, tdb_path_backup, tdb_path, 0, + corrupt_suffix, True, True); + if (ret != 0) { + DEBUG(1, ("Error restoring backup from '%s'\n", + tdb_path_backup)); + } else { + DEBUG(1, ("Restored tdb backup from '%s'\n", + tdb_path_backup)); + } + } + +done: + TALLOC_FREE(ctx); + return ret; +} diff --git a/source3/lib/tdb_validate.h b/source3/lib/tdb_validate.h new file mode 100644 index 0000000000..1a207fa669 --- /dev/null +++ b/source3/lib/tdb_validate.h @@ -0,0 +1,78 @@ +/* + * Unix SMB/CIFS implementation. + * + * A general tdb content validation mechanism + * + * Copyright (C) Michael Adam 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 . + */ + +#ifndef __TDB_VALIDATE_H__ +#define __TDB_VALIDATE_H__ + +#include "includes.h" + +/** + * Flag field for keeping track of the status of a validation. + */ +struct tdb_validation_status { + bool tdb_error; + bool bad_freelist; + bool bad_entry; + bool unknown_key; + bool success; +}; + +/** + * Callback function type for the validation mechanism. + */ +typedef int (*tdb_validate_data_func)(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, + TDB_DATA dbuf, void *state); + +/** + * tdb validation function. + * returns 0 if tdb is ok, != 0 if it isn't. + * this function expects an opened tdb. + */ +int tdb_validate(struct tdb_context *tdb, + tdb_validate_data_func validate_fn); + +/** + * tdb validation function. + * returns 0 if tdb is ok, != 0 if it isn't. + * This is a wrapper around the actual validation function that + * opens and closes the tdb. + */ +int tdb_validate_open(const char *tdb_path, + tdb_validate_data_func validate_fn); + +/** + * validation function with backup handling: + * + * - calls tdb_validate + * - if the tdb is ok, create a backup "name.bak", possibly moving + * existing backup to name.bak.old, + * return 0 (success) even if the backup fails + * - if the tdb is corrupt: + * - move the tdb to "name.corrupt" + * - check if there is valid backup. + * if so, restore the backup. + * if restore is successful, return 0 (success), + * - otherwise return -1 (failure) + */ +int tdb_validate_and_backup(const char *tdb_path, + tdb_validate_data_func validate_fn); + +#endif /* __TDB_VALIDATE_H__ */ diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 2dbdd57947..78fa7cd0a1 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -630,487 +630,3 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err) return NT_STATUS_INTERNAL_ERROR; } - - -/********************************************************************* - * the following is a generic validation mechanism for tdbs. - *********************************************************************/ - -/* - * internal validation function, executed by the child. - */ -static int tdb_validate_child(struct tdb_context *tdb, - tdb_validate_data_func validate_fn) -{ - int ret = 1; - int num_entries = 0; - struct tdb_validation_status v_status; - - v_status.tdb_error = False; - v_status.bad_freelist = False; - v_status.bad_entry = False; - v_status.unknown_key = False; - v_status.success = True; - - if (!tdb) { - v_status.tdb_error = True; - v_status.success = False; - goto out; - } - - /* Check if the tdb's freelist is good. */ - if (tdb_validate_freelist(tdb, &num_entries) == -1) { - v_status.bad_freelist = True; - v_status.success = False; - goto out; - } - - DEBUG(10,("tdb_validate_child: tdb %s freelist has %d entries\n", - tdb_name(tdb), num_entries)); - - /* Now traverse the tdb to validate it. */ - num_entries = tdb_traverse(tdb, validate_fn, (void *)&v_status); - if (!v_status.success) { - goto out; - } else if (num_entries == -1) { - v_status.tdb_error = True; - v_status.success = False; - goto out; - } - - DEBUG(10,("tdb_validate_child: tdb %s is good with %d entries\n", - tdb_name(tdb), num_entries)); - ret = 0; /* Cache is good. */ - -out: - DEBUG(10, ("tdb_validate_child: summary of validation status:\n")); - DEBUGADD(10,(" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no")); - DEBUGADD(10,(" * bad freelist: %s\n",v_status.bad_freelist?"yes":"no")); - DEBUGADD(10,(" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no")); - DEBUGADD(10,(" * unknown key: %s\n", v_status.unknown_key?"yes":"no")); - DEBUGADD(10,(" => overall success: %s\n", v_status.success?"yes":"no")); - - return ret; -} - -/* - * tdb validation function. - * returns 0 if tdb is ok, != 0 if it isn't. - * this function expects an opened tdb. - */ -int tdb_validate(struct tdb_context *tdb, tdb_validate_data_func validate_fn) -{ - pid_t child_pid = -1; - int child_status = 0; - int wait_pid = 0; - int ret = 1; - - if (tdb == NULL) { - DEBUG(1, ("Error: tdb_validate called with tdb == NULL\n")); - return ret; - } - - DEBUG(5, ("tdb_validate called for tdb '%s'\n", tdb_name(tdb))); - - /* fork and let the child do the validation. - * benefit: no need to twist signal handlers and panic functions. - * just let the child panic. we catch the signal. */ - - DEBUG(10, ("tdb_validate: forking to let child do validation.\n")); - child_pid = sys_fork(); - if (child_pid == 0) { - /* child code */ - DEBUG(10, ("tdb_validate (validation child): created\n")); - DEBUG(10, ("tdb_validate (validation child): " - "calling tdb_validate_child\n")); - exit(tdb_validate_child(tdb, validate_fn)); - } - else if (child_pid < 0) { - DEBUG(1, ("tdb_validate: fork for validation failed.\n")); - goto done; - } - - /* parent */ - - DEBUG(10, ("tdb_validate: fork succeeded, child PID = %d\n",child_pid)); - - DEBUG(10, ("tdb_validate: waiting for child to finish...\n")); - while ((wait_pid = sys_waitpid(child_pid, &child_status, 0)) < 0) { - if (errno == EINTR) { - DEBUG(10, ("tdb_validate: got signal during waitpid, " - "retrying\n")); - errno = 0; - continue; - } - DEBUG(1, ("tdb_validate: waitpid failed with error '%s'.\n", - strerror(errno))); - goto done; - } - if (wait_pid != child_pid) { - DEBUG(1, ("tdb_validate: waitpid returned pid %d, " - "but %d was expected\n", wait_pid, child_pid)); - goto done; - } - - DEBUG(10, ("tdb_validate: validating child returned.\n")); - if (WIFEXITED(child_status)) { - DEBUG(10, ("tdb_validate: child exited, code %d.\n", - WEXITSTATUS(child_status))); - ret = WEXITSTATUS(child_status); - } - if (WIFSIGNALED(child_status)) { - DEBUG(10, ("tdb_validate: child terminated by signal %d\n", - WTERMSIG(child_status))); -#ifdef WCOREDUMP - if (WCOREDUMP(child_status)) { - DEBUGADD(10, ("core dumped\n")); - } -#endif - ret = WTERMSIG(child_status); - } - if (WIFSTOPPED(child_status)) { - DEBUG(10, ("tdb_validate: child was stopped by signal %d\n", - WSTOPSIG(child_status))); - ret = WSTOPSIG(child_status); - } - -done: - DEBUG(5, ("tdb_validate returning code '%d' for tdb '%s'\n", ret, - tdb_name(tdb))); - - return ret; -} - -/* - * tdb validation function. - * returns 0 if tdb is ok, != 0 if it isn't. - * this is a wrapper around the actual validation function that opens and closes - * the tdb. - */ -int tdb_validate_open(const char *tdb_path, tdb_validate_data_func validate_fn) -{ - TDB_CONTEXT *tdb = NULL; - int ret = 1; - - DEBUG(5, ("tdb_validate_open called for tdb '%s'\n", tdb_path)); - - tdb = tdb_open_log(tdb_path, 0, TDB_DEFAULT, O_RDONLY, 0); - if (!tdb) { - DEBUG(1, ("Error opening tdb %s\n", tdb_path)); - return ret; - } - - ret = tdb_validate(tdb, validate_fn); - tdb_close(tdb); - return ret; -} - -/* - * tdb backup function and helpers for tdb_validate wrapper with backup - * handling. - */ - -/* this structure eliminates the need for a global overall status for - * the traverse-copy */ -struct tdb_copy_data { - struct tdb_context *dst; - bool success; -}; - -static int traverse_copy_fn(struct tdb_context *tdb, TDB_DATA key, - TDB_DATA dbuf, void *private_data) -{ - struct tdb_copy_data *data = (struct tdb_copy_data *)private_data; - - if (tdb_store(data->dst, key, dbuf, TDB_INSERT) != 0) { - DEBUG(4, ("Failed to insert into %s: %s\n", tdb_name(data->dst), - strerror(errno))); - data->success = False; - return 1; - } - return 0; -} - -static int tdb_copy(struct tdb_context *src, struct tdb_context *dst) -{ - struct tdb_copy_data data; - int count; - - data.dst = dst; - data.success = True; - - count = tdb_traverse(src, traverse_copy_fn, (void *)(&data)); - if ((count < 0) || (data.success == False)) { - return -1; - } - return count; -} - -static int tdb_verify_basic(struct tdb_context *tdb) -{ - return tdb_traverse(tdb, NULL, NULL); -} - -/* this backup function is essentially taken from lib/tdb/tools/tdbbackup.tdb - */ -static int tdb_backup(TALLOC_CTX *ctx, const char *src_path, - const char *dst_path, int hash_size) -{ - struct tdb_context *src_tdb = NULL; - struct tdb_context *dst_tdb = NULL; - char *tmp_path = NULL; - struct stat st; - int count1, count2; - int saved_errno = 0; - int ret = -1; - - if (stat(src_path, &st) != 0) { - DEBUG(3, ("Could not stat '%s': %s\n", src_path, - strerror(errno))); - goto done; - } - - /* open old tdb RDWR - so we can lock it */ - src_tdb = tdb_open_log(src_path, 0, TDB_DEFAULT, O_RDWR, 0); - if (src_tdb == NULL) { - DEBUG(3, ("Failed to open tdb '%s'\n", src_path)); - goto done; - } - - if (tdb_lockall(src_tdb) != 0) { - DEBUG(3, ("Failed to lock tdb '%s'\n", src_path)); - goto done; - } - - tmp_path = talloc_asprintf(ctx, "%s%s", dst_path, ".tmp"); - unlink(tmp_path); - dst_tdb = tdb_open_log(tmp_path, - hash_size ? hash_size : tdb_hash_size(src_tdb), - TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, - st.st_mode & 0777); - if (dst_tdb == NULL) { - DEBUG(3, ("Error creating tdb '%s': %s\n", tmp_path, - strerror(errno))); - saved_errno = errno; - unlink(tmp_path); - goto done; - } - - count1 = tdb_copy(src_tdb, dst_tdb); - if (count1 < 0) { - DEBUG(3, ("Failed to copy tdb '%s': %s\n", src_path, - strerror(errno))); - tdb_close(dst_tdb); - goto done; - } - - /* reopen ro and do basic verification */ - tdb_close(dst_tdb); - dst_tdb = tdb_open_log(tmp_path, 0, TDB_DEFAULT, O_RDONLY, 0); - if (!dst_tdb) { - DEBUG(3, ("Failed to reopen tdb '%s': %s\n", tmp_path, - strerror(errno))); - goto done; - } - count2 = tdb_verify_basic(dst_tdb); - if (count2 != count1) { - DEBUG(3, ("Failed to verify result of copying tdb '%s'.\n", - src_path)); - tdb_close(dst_tdb); - goto done; - } - - DEBUG(10, ("tdb_backup: successfully copied %d entries\n", count1)); - - /* make sure the new tdb has reached stable storage - * then rename it to its destination */ - fsync(tdb_fd(dst_tdb)); - tdb_close(dst_tdb); - unlink(dst_path); - if (rename(tmp_path, dst_path) != 0) { - DEBUG(3, ("Failed to rename '%s' to '%s': %s\n", - tmp_path, dst_path, strerror(errno))); - goto done; - } - - /* success */ - ret = 0; - -done: - if (src_tdb != NULL) { - tdb_close(src_tdb); - } - if (tmp_path != NULL) { - unlink(tmp_path); - TALLOC_FREE(tmp_path); - } - if (saved_errno != 0) { - errno = saved_errno; - } - return ret; -} - -static int rename_file_with_suffix(TALLOC_CTX *ctx, const char *path, - const char *suffix) -{ - int ret = -1; - char *dst_path; - - dst_path = talloc_asprintf(ctx, "%s%s", path, suffix); - - ret = (rename(path, dst_path) != 0); - - if (ret == 0) { - DEBUG(5, ("moved '%s' to '%s'\n", path, dst_path)); - } else if (errno == ENOENT) { - DEBUG(3, ("file '%s' does not exist - so not moved\n", path)); - ret = 0; - } else { - DEBUG(3, ("error renaming %s to %s: %s\n", path, dst_path, - strerror(errno))); - } - - TALLOC_FREE(dst_path); - return ret; -} - -/* - * do a backup of a tdb, moving the destination out of the way first - */ -static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path, - const char *dst_path, int hash_size, - const char *rotate_suffix, - bool retry_norotate_if_nospc, - bool rename_as_last_resort_if_nospc) -{ - int ret; - - rename_file_with_suffix(ctx, dst_path, rotate_suffix); - - ret = tdb_backup(ctx, src_path, dst_path, hash_size); - - if (ret != 0) { - DEBUG(10, ("backup of %s failed: %s\n", src_path, strerror(errno))); - } - if ((ret != 0) && (errno == ENOSPC) && retry_norotate_if_nospc) - { - char *rotate_path = talloc_asprintf(ctx, "%s%s", dst_path, - rotate_suffix); - DEBUG(10, ("backup of %s failed due to lack of space\n", - src_path)); - DEBUGADD(10, ("trying to free some space by removing rotated " - "dst %s\n", rotate_path)); - if (unlink(rotate_path) == -1) { - DEBUG(10, ("unlink of %s failed: %s\n", rotate_path, - strerror(errno))); - } else { - ret = tdb_backup(ctx, src_path, dst_path, hash_size); - } - TALLOC_FREE(rotate_path); - } - - if ((ret != 0) && (errno == ENOSPC) && rename_as_last_resort_if_nospc) - { - DEBUG(10, ("backup of %s failed due to lack of space\n", - src_path)); - DEBUGADD(10, ("using 'rename' as a last resort\n")); - ret = rename(src_path, dst_path); - } - - return ret; -} - -/* - * validation function with backup handling: - * - * - calls tdb_validate - * - if the tdb is ok, create a backup "name.bak", possibly moving - * existing backup to name.bak.old, - * return 0 (success) even if the backup fails - * - if the tdb is corrupt: - * - move the tdb to "name.corrupt" - * - check if there is valid backup. - * if so, restore the backup. - * if restore is successful, return 0 (success), - * - otherwise return -1 (failure) - */ -int tdb_validate_and_backup(const char *tdb_path, - tdb_validate_data_func validate_fn) -{ - int ret = -1; - const char *backup_suffix = ".bak"; - const char *corrupt_suffix = ".corrupt"; - const char *rotate_suffix = ".old"; - char *tdb_path_backup; - struct stat st; - TALLOC_CTX *ctx = NULL; - - ctx = talloc_new(NULL); - if (ctx == NULL) { - DEBUG(0, ("tdb_validate_and_backup: out of memory\n")); - goto done; - } - - tdb_path_backup = talloc_asprintf(ctx, "%s%s", tdb_path, backup_suffix); - - ret = tdb_validate_open(tdb_path, validate_fn); - - if (ret == 0) { - DEBUG(1, ("tdb '%s' is valid\n", tdb_path)); - ret = tdb_backup_with_rotate(ctx, tdb_path, tdb_path_backup, 0, - rotate_suffix, True, False); - if (ret != 0) { - DEBUG(1, ("Error creating backup of tdb '%s'\n", - tdb_path)); - /* the actual validation was successful: */ - ret = 0; - } else { - DEBUG(1, ("Created backup '%s' of tdb '%s'\n", - tdb_path_backup, tdb_path)); - } - } else { - DEBUG(1, ("tdb '%s' is invalid\n", tdb_path)); - - ret =stat(tdb_path_backup, &st); - if (ret != 0) { - DEBUG(5, ("Could not stat '%s': %s\n", tdb_path_backup, - strerror(errno))); - DEBUG(1, ("No backup found.\n")); - } else { - DEBUG(1, ("backup '%s' found.\n", tdb_path_backup)); - ret = tdb_validate_open(tdb_path_backup, validate_fn); - if (ret != 0) { - DEBUG(1, ("Backup '%s' is invalid.\n", - tdb_path_backup)); - } - } - - if (ret != 0) { - int renamed = rename_file_with_suffix(ctx, tdb_path, - corrupt_suffix); - if (renamed != 0) { - DEBUG(1, ("Error moving tdb to '%s%s'\n", - tdb_path, corrupt_suffix)); - } else { - DEBUG(1, ("Corrupt tdb stored as '%s%s'\n", - tdb_path, corrupt_suffix)); - } - goto done; - } - - DEBUG(1, ("valid backup '%s' found\n", tdb_path_backup)); - ret = tdb_backup_with_rotate(ctx, tdb_path_backup, tdb_path, 0, - corrupt_suffix, True, True); - if (ret != 0) { - DEBUG(1, ("Error restoring backup from '%s'\n", - tdb_path_backup)); - } else { - DEBUG(1, ("Restored tdb backup from '%s'\n", - tdb_path_backup)); - } - } - -done: - TALLOC_FREE(ctx); - return ret; -} -- cgit From eccbc32ae36790ad9471aaa89d115a8dffd7fb4c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 28 Jan 2009 08:56:17 +0100 Subject: s3:tdb_validate: clean up leading tabs/spaces and trailing spaces. Michael --- source3/lib/tdb_validate.c | 56 +++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/tdb_validate.c b/source3/lib/tdb_validate.c index c1ca97787c..948201a5f2 100644 --- a/source3/lib/tdb_validate.c +++ b/source3/lib/tdb_validate.c @@ -22,8 +22,8 @@ #include "includes.h" #include "tdb_validate.h" -/* - * internal validation function, executed by the child. +/* + * internal validation function, executed by the child. */ static int tdb_validate_child(struct tdb_context *tdb, tdb_validate_data_func validate_fn) @@ -364,46 +364,46 @@ static int rename_file_with_suffix(TALLOC_CTX *ctx, const char *path, * do a backup of a tdb, moving the destination out of the way first */ static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path, - const char *dst_path, int hash_size, + const char *dst_path, int hash_size, const char *rotate_suffix, bool retry_norotate_if_nospc, bool rename_as_last_resort_if_nospc) { int ret; - rename_file_with_suffix(ctx, dst_path, rotate_suffix); + rename_file_with_suffix(ctx, dst_path, rotate_suffix); - ret = tdb_backup(ctx, src_path, dst_path, hash_size); + ret = tdb_backup(ctx, src_path, dst_path, hash_size); if (ret != 0) { DEBUG(10, ("backup of %s failed: %s\n", src_path, strerror(errno))); } - if ((ret != 0) && (errno == ENOSPC) && retry_norotate_if_nospc) - { - char *rotate_path = talloc_asprintf(ctx, "%s%s", dst_path, - rotate_suffix); - DEBUG(10, ("backup of %s failed due to lack of space\n", + if ((ret != 0) && (errno == ENOSPC) && retry_norotate_if_nospc) + { + char *rotate_path = talloc_asprintf(ctx, "%s%s", dst_path, + rotate_suffix); + DEBUG(10, ("backup of %s failed due to lack of space\n", src_path)); - DEBUGADD(10, ("trying to free some space by removing rotated " + DEBUGADD(10, ("trying to free some space by removing rotated " "dst %s\n", rotate_path)); - if (unlink(rotate_path) == -1) { - DEBUG(10, ("unlink of %s failed: %s\n", rotate_path, + if (unlink(rotate_path) == -1) { + DEBUG(10, ("unlink of %s failed: %s\n", rotate_path, strerror(errno))); - } else { - ret = tdb_backup(ctx, src_path, dst_path, hash_size); - } - TALLOC_FREE(rotate_path); - } - - if ((ret != 0) && (errno == ENOSPC) && rename_as_last_resort_if_nospc) - { - DEBUG(10, ("backup of %s failed due to lack of space\n", + } else { + ret = tdb_backup(ctx, src_path, dst_path, hash_size); + } + TALLOC_FREE(rotate_path); + } + + if ((ret != 0) && (errno == ENOSPC) && rename_as_last_resort_if_nospc) + { + DEBUG(10, ("backup of %s failed due to lack of space\n", src_path)); - DEBUGADD(10, ("using 'rename' as a last resort\n")); - ret = rename(src_path, dst_path); - } + DEBUGADD(10, ("using 'rename' as a last resort\n")); + ret = rename(src_path, dst_path); + } - return ret; + return ret; } /* @@ -416,8 +416,8 @@ static int tdb_backup_with_rotate(TALLOC_CTX *ctx, const char *src_path, * - if the tdb is corrupt: * - move the tdb to "name.corrupt" * - check if there is valid backup. - * if so, restore the backup. - * if restore is successful, return 0 (success), + * if so, restore the backup. + * if restore is successful, return 0 (success), * - otherwise return -1 (failure) */ int tdb_validate_and_backup(const char *tdb_path, -- cgit From ab63bad94bfc378aca08d3314692de90e1aa1bf3 Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Sat, 24 Jan 2009 10:00:13 +0100 Subject: async_sock: Move to top level --- source3/lib/async_sock.c | 693 ----------------------------------------------- 1 file changed, 693 deletions(-) delete mode 100644 source3/lib/async_sock.c (limited to 'source3/lib') diff --git a/source3/lib/async_sock.c b/source3/lib/async_sock.c deleted file mode 100644 index 73ff6f2870..0000000000 --- a/source3/lib/async_sock.c +++ /dev/null @@ -1,693 +0,0 @@ -/* - Unix SMB/CIFS implementation. - async socket syscalls - Copyright (C) Volker Lendecke 2008 - - 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 . -*/ - -#include "includes.h" - -/** - * Discriminator for async_syscall_state - */ -enum async_syscall_type { - ASYNC_SYSCALL_SEND, - ASYNC_SYSCALL_SENDALL, - ASYNC_SYSCALL_RECV, - ASYNC_SYSCALL_RECVALL, - ASYNC_SYSCALL_CONNECT -}; - -/** - * Holder for syscall arguments and the result - */ - -struct async_syscall_state { - enum async_syscall_type syscall_type; - struct fd_event *fde; - - union { - struct param_send { - int fd; - const void *buffer; - size_t length; - int flags; - } param_send; - struct param_sendall { - int fd; - const void *buffer; - size_t length; - int flags; - size_t sent; - } param_sendall; - struct param_recv { - int fd; - void *buffer; - size_t length; - int flags; - } param_recv; - struct param_recvall { - int fd; - void *buffer; - size_t length; - int flags; - size_t received; - } param_recvall; - struct param_connect { - /** - * connect needs to be done on a nonblocking - * socket. Keep the old flags around - */ - long old_sockflags; - int fd; - const struct sockaddr *address; - socklen_t address_len; - } param_connect; - } param; - - union { - ssize_t result_ssize_t; - size_t result_size_t; - int result_int; - } result; - int sys_errno; -}; - -/** - * @brief Create a new async syscall req - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] type Which syscall will this be - * @param[in] pstate Where to put the newly created private_data state - * @retval The new request - * - * This is a helper function to prepare a new struct async_req with an - * associated struct async_syscall_state. The async_syscall_state will be put - * into the async_req as private_data. - */ - -static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx, - struct event_context *ev, - enum async_syscall_type type, - struct async_syscall_state **pstate) -{ - struct async_req *result; - struct async_syscall_state *state; - - if (!async_req_setup(mem_ctx, &result, &state, - struct async_syscall_state)) { - return NULL; - } - state->syscall_type = type; - - result->private_data = state; - - *pstate = state; - - return result; -} - -/** - * @brief Create a new async syscall req based on a fd - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] type Which syscall will this be - * @param[in] fd The file descriptor we work on - * @param[in] fde_flags EVENT_FD_READ/WRITE -- what are we interested in? - * @param[in] fde_cb The callback function for the file descriptor event - * @param[in] pstate Where to put the newly created private_data state - * @retval The new request - * - * This is a helper function to prepare a new struct async_req with an - * associated struct async_syscall_state and an associated file descriptor - * event. - */ - -static struct async_req *async_fde_syscall_new( - TALLOC_CTX *mem_ctx, - struct event_context *ev, - enum async_syscall_type type, - int fd, - uint16_t fde_flags, - void (*fde_cb)(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv), - struct async_syscall_state **pstate) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_syscall_new(mem_ctx, ev, type, &state); - if (result == NULL) { - return NULL; - } - - state->fde = event_add_fd(ev, state, fd, fde_flags, fde_cb, result); - if (state->fde == NULL) { - TALLOC_FREE(result); - return NULL; - } - *pstate = state; - return result; -} - -/** - * Retrieve a ssize_t typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_ssize_t; -} - -/** - * Retrieve a size_t typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -size_t async_syscall_result_size_t(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_size_t; -} - -/** - * Retrieve a int typed result from an async syscall - * @param[in] req The syscall that has just finished - * @param[out] perrno Where to put the syscall's errno - * @retval The return value from the asynchronously called syscall - */ - -int async_syscall_result_int(struct async_req *req, int *perrno) -{ - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - - *perrno = state->sys_errno; - return state->result.result_int; -} - -/** - * fde event handler for the "send" syscall - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the send - * @param[in] flags Can only be EVENT_FD_WRITE here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_send_callback(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_send *p = &state->param.param_send; - - if (state->syscall_type != ASYNC_SYSCALL_SEND) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - state->result.result_ssize_t = send(p->fd, p->buffer, p->length, - p->flags); - state->sys_errno = errno; - - TALLOC_FREE(state->fde); - - async_req_done(req); -} - -/** - * Async version of send(2) - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to send to - * @param[in] buffer The buffer to send - * @param[in] length How many bytes to send - * @param[in] flags flags passed to send(2) - * - * This function is a direct counterpart of send(2) - */ - -struct async_req *async_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, const void *buffer, size_t length, - int flags) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_SEND, - fd, EVENT_FD_WRITE, async_send_callback, - &state); - if (result == NULL) { - return NULL; - } - - state->param.param_send.fd = fd; - state->param.param_send.buffer = buffer; - state->param.param_send.length = length; - state->param.param_send.flags = flags; - - return result; -} - -/** - * fde event handler for the "sendall" syscall group - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the send - * @param[in] flags Can only be EVENT_FD_WRITE here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_sendall_callback(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_sendall *p = &state->param.param_sendall; - - if (state->syscall_type != ASYNC_SYSCALL_SENDALL) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - state->result.result_ssize_t = send(p->fd, (char *)p->buffer + p->sent, - p->length - p->sent, p->flags); - state->sys_errno = errno; - - if (state->result.result_ssize_t == -1) { - async_req_error(req, map_nt_error_from_unix(state->sys_errno)); - return; - } - - if (state->result.result_ssize_t == 0) { - async_req_error(req, NT_STATUS_END_OF_FILE); - return; - } - - p->sent += state->result.result_ssize_t; - if (p->sent > p->length) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - if (p->sent == p->length) { - TALLOC_FREE(state->fde); - async_req_done(req); - } -} - -/** - * @brief Send all bytes to a socket - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to send to - * @param[in] buffer The buffer to send - * @param[in] length How many bytes to send - * @param[in] flags flags passed to send(2) - * - * async_sendall calls send(2) as long as it is necessary to send all of the - * "length" bytes - */ - -struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, const void *buffer, size_t length, - int flags) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_SENDALL, - fd, EVENT_FD_WRITE, async_sendall_callback, - &state); - if (result == NULL) { - return NULL; - } - - state->param.param_sendall.fd = fd; - state->param.param_sendall.buffer = buffer; - state->param.param_sendall.length = length; - state->param.param_sendall.flags = flags; - state->param.param_sendall.sent = 0; - - return result; -} - -NTSTATUS sendall_recv(struct async_req *req) -{ - return async_req_simple_recv(req); -} - -/** - * fde event handler for the "recv" syscall - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the recv - * @param[in] flags Can only be EVENT_FD_READ here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_recv_callback(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_recv *p = &state->param.param_recv; - - if (state->syscall_type != ASYNC_SYSCALL_RECV) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - state->result.result_ssize_t = recv(p->fd, p->buffer, p->length, - p->flags); - state->sys_errno = errno; - - TALLOC_FREE(state->fde); - - async_req_done(req); -} - -/** - * Async version of recv(2) - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to recv from - * @param[in] buffer The buffer to recv into - * @param[in] length How many bytes to recv - * @param[in] flags flags passed to recv(2) - * - * This function is a direct counterpart of recv(2) - */ - -struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, void *buffer, size_t length, - int flags) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_RECV, - fd, EVENT_FD_READ, async_recv_callback, - &state); - - if (result == NULL) { - return NULL; - } - - state->param.param_recv.fd = fd; - state->param.param_recv.buffer = buffer; - state->param.param_recv.length = length; - state->param.param_recv.flags = flags; - - return result; -} - -/** - * fde event handler for the "recvall" syscall group - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the recv - * @param[in] flags Can only be EVENT_FD_READ here - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_recvall_callback(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_syscall_state *state = talloc_get_type_abort( - req->private_data, struct async_syscall_state); - struct param_recvall *p = &state->param.param_recvall; - - if (state->syscall_type != ASYNC_SYSCALL_RECVALL) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - state->result.result_ssize_t = recv(p->fd, - (char *)p->buffer + p->received, - p->length - p->received, p->flags); - state->sys_errno = errno; - - if (state->result.result_ssize_t == -1) { - async_req_error(req, map_nt_error_from_unix(state->sys_errno)); - return; - } - - if (state->result.result_ssize_t == 0) { - async_req_error(req, NT_STATUS_END_OF_FILE); - return; - } - - p->received += state->result.result_ssize_t; - if (p->received > p->length) { - async_req_error(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - if (p->received == p->length) { - TALLOC_FREE(state->fde); - async_req_done(req); - } -} - -/** - * Receive a specified number of bytes from a socket - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to recv from - * @param[in] buffer The buffer to recv into - * @param[in] length How many bytes to recv - * @param[in] flags flags passed to recv(2) - * - * async_recvall will call recv(2) until "length" bytes are received - */ - -struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct event_context *ev, - int fd, void *buffer, size_t length, - int flags) -{ - struct async_req *result; - struct async_syscall_state *state; - - result = async_fde_syscall_new( - mem_ctx, ev, ASYNC_SYSCALL_RECVALL, - fd, EVENT_FD_READ, async_recvall_callback, - &state); - if (result == NULL) { - return NULL; - } - - state->param.param_recvall.fd = fd; - state->param.param_recvall.buffer = buffer; - state->param.param_recvall.length = length; - state->param.param_recvall.flags = flags; - state->param.param_recvall.received = 0; - - return result; -} - -NTSTATUS recvall_recv(struct async_req *req) -{ - return async_req_simple_recv(req); -} - -struct async_connect_state { - int fd; - int result; - int sys_errno; - long old_sockflags; -}; - -static void async_connect_connected(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv); - -/** - * @brief async version of connect(2) - * @param[in] mem_ctx The memory context to hang the result off - * @param[in] ev The event context to work from - * @param[in] fd The socket to recv from - * @param[in] address Where to connect? - * @param[in] address_len Length of *address - * @retval The async request - * - * This function sets the socket into non-blocking state to be able to call - * connect in an async state. This will be reset when the request is finished. - */ - -struct async_req *async_connect_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, - int fd, const struct sockaddr *address, - socklen_t address_len) -{ - struct async_req *result; - struct async_connect_state *state; - struct fd_event *fde; - NTSTATUS status; - - if (!async_req_setup(mem_ctx, &result, &state, - struct async_connect_state)) { - return NULL; - } - - /** - * We have to set the socket to nonblocking for async connect(2). Keep - * the old sockflags around. - */ - - state->fd = fd; - state->sys_errno = 0; - - state->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0); - if (state->old_sockflags == -1) { - goto post_errno; - } - - set_blocking(fd, false); - - state->result = connect(fd, address, address_len); - if (state->result == 0) { - state->sys_errno = 0; - status = NT_STATUS_OK; - goto post_status; - } - - /** - * A number of error messages show that something good is progressing - * and that we have to wait for readability. - * - * If none of them are present, bail out. - */ - - if (!(errno == EINPROGRESS || errno == EALREADY || -#ifdef EISCONN - errno == EISCONN || -#endif - errno == EAGAIN || errno == EINTR)) { - goto post_errno; - } - - fde = event_add_fd(ev, state, fd, EVENT_FD_READ | EVENT_FD_WRITE, - async_connect_connected, result); - if (fde == NULL) { - status = NT_STATUS_NO_MEMORY; - goto post_status; - } - return result; - - post_errno: - state->sys_errno = errno; - status = map_nt_error_from_unix(state->sys_errno); - post_status: - sys_fcntl_long(fd, F_SETFL, state->old_sockflags); - if (!async_post_status(result, ev, status)) { - goto fail; - } - return result; - fail: - TALLOC_FREE(result); - return NULL; -} - -/** - * fde event handler for connect(2) - * @param[in] ev The event context that sent us here - * @param[in] fde The file descriptor event associated with the connect - * @param[in] flags Indicate read/writeability of the socket - * @param[in] priv private data, "struct async_req *" in this case - */ - -static void async_connect_connected(struct event_context *ev, - struct fd_event *fde, uint16_t flags, - void *priv) -{ - struct async_req *req = talloc_get_type_abort( - priv, struct async_req); - struct async_connect_state *state = talloc_get_type_abort( - req->private_data, struct async_connect_state); - - TALLOC_FREE(fde); - - /* - * Stevens, Network Programming says that if there's a - * successful connect, the socket is only writable. Upon an - * error, it's both readable and writable. - */ - if ((flags & (EVENT_FD_READ|EVENT_FD_WRITE)) - == (EVENT_FD_READ|EVENT_FD_WRITE)) { - int sockerr; - socklen_t err_len = sizeof(sockerr); - - if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR, - (void *)&sockerr, &err_len) == 0) { - errno = sockerr; - } - - state->sys_errno = errno; - - DEBUG(10, ("connect returned %s\n", strerror(errno))); - - sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags); - async_req_error(req, map_nt_error_from_unix(state->sys_errno)); - return; - } - - state->sys_errno = 0; - async_req_done(req); -} - -NTSTATUS async_connect_recv(struct async_req *req, int *perrno) -{ - struct async_connect_state *state = talloc_get_type_abort( - req->private_data, struct async_connect_state); - NTSTATUS status; - - sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags); - - *perrno = state->sys_errno; - - if (async_req_is_error(req, &status)) { - return status; - } - if (state->sys_errno == 0) { - return NT_STATUS_OK; - } - return map_nt_error_from_unix(state->sys_errno); -} -- cgit From 4c7296cc0c0770ea547b67d668d5b42ab00a27da Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 27 Jan 2009 19:45:51 +0100 Subject: Avoid valgrind errors In event handlers, we might destroy other events that are pending in the lists. We can only run one event safely per select call. Yes, I've seen these valgrind errors :-) Jeremy, with ccdd921e61 you had checked in the change to run multiple events. Do you remember why it was necessary and could not be solved in a different way? Volker --- source3/lib/events.c | 48 +++++++++++++----------------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/events.c b/source3/lib/events.c index 4484d5323b..44b4562757 100644 --- a/source3/lib/events.c +++ b/source3/lib/events.c @@ -83,45 +83,24 @@ bool event_add_to_select_args(struct tevent_context *ev, bool run_events(struct tevent_context *ev, int selrtn, fd_set *read_fds, fd_set *write_fds) { - bool fired = false; - struct tevent_fd *fde, *next; + struct tevent_fd *fde; + struct timeval now; if (ev->signal_events && tevent_common_check_signal(ev)) { return true; } - /* Run all events that are pending, not just one (as we - did previously. */ - - while (ev->timer_events) { - struct timeval now; - GetTimeOfDay(&now); - - if (timeval_compare( - &now, &ev->timer_events->next_event) < 0) { - /* Nothing to do yet */ - DEBUG(11, ("run_events: Nothing to do\n")); - break; - } - - DEBUG(10, ("Running event \"%s\" %p\n", - ev->timer_events->handler_name, - ev->timer_events)); + GetTimeOfDay(&now); - ev->timer_events->handler( - ev, - ev->timer_events, now, - ev->timer_events->private_data); + if ((ev->timer_events != NULL) + && (timeval_compare(&now, &ev->timer_events->next_event) >= 0)) { - fired = true; - } + DEBUG(10, ("Running timed event \"%s\" %p\n", + ev->timer_events->handler_name, ev->timer_events)); - if (fired) { - /* - * We might have changed the socket status during the timed - * events, return to run select again. - */ + ev->timer_events->handler(ev, ev->timer_events, now, + ev->timer_events->private_data); return true; } @@ -129,23 +108,22 @@ bool run_events(struct tevent_context *ev, /* * No fd ready */ - return fired; + return false; } - for (fde = ev->fd_events; fde; fde = next) { + for (fde = ev->fd_events; fde; fde = fde->next) { uint16 flags = 0; - next = fde->next; if (FD_ISSET(fde->fd, read_fds)) flags |= EVENT_FD_READ; if (FD_ISSET(fde->fd, write_fds)) flags |= EVENT_FD_WRITE; if (flags & fde->flags) { fde->handler(ev, fde, flags, fde->private_data); - fired = true; + return true; } } - return fired; + return false; } -- cgit From 7540d13956a8a69d25f6fbbc4f9a3417e91db1d2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 28 Jan 2009 18:55:13 +0100 Subject: s3:ctdbd_conn: canonicalize ips before sending them to ctdbd This makes samba work with older ctdb versions. metze --- source3/lib/ctdbd_conn.c | 50 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c index f8dae8fbd6..88d82caab8 100644 --- a/source3/lib/ctdbd_conn.c +++ b/source3/lib/ctdbd_conn.c @@ -1176,46 +1176,76 @@ NTSTATUS ctdbd_traverse(uint32 db_id, return status; } +/* + This is used to canonicalize a ctdb_sock_addr structure. +*/ +static void smbd_ctdb_canonicalize_ip(const struct sockaddr_storage *in, + struct sockaddr_storage *out) +{ + memcpy(out, in, sizeof (*out)); + +#ifdef HAVE_IPV6 + if (in->ss_family == AF_INET6) { + const char prefix[12] = { 0,0,0,0,0,0,0,0,0,0,0xff,0xff }; + const struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)in; + struct sockaddr_in *out4 = (struct sockaddr_in *)out; + if (memcmp(&in6->sin6_addr, prefix, 12) == 0) { + memset(out, 0, sizeof(*out)); +#ifdef HAVE_SOCK_SIN_LEN + out4->sin_len = sizeof(*out); +#endif + out4->sin_family = AF_INET; + out4->sin_port = in6->sin6_port; + memcpy(&out4->sin_addr, &in6->sin6_addr.s6_addr32[3], 4); + } + } +#endif +} + /* * Register us as a server for a particular tcp connection */ NTSTATUS ctdbd_register_ips(struct ctdbd_connection *conn, - const struct sockaddr_storage *server, - const struct sockaddr_storage *client, + const struct sockaddr_storage *_server, + const struct sockaddr_storage *_client, void (*release_ip_handler)(const char *ip_addr, void *private_data), void *private_data) { - struct sockaddr *sock = (struct sockaddr *)client; /* * we still use ctdb_control_tcp for ipv4 * because we want to work against older ctdb * versions at runtime */ struct ctdb_control_tcp p4; -#ifdef HAVE_IPV6 +#ifdef HAVE_STRUCT_CTDB_CONTROL_TCP_ADDR struct ctdb_control_tcp_addr p; #endif TDB_DATA data; NTSTATUS status; + struct sockaddr_storage client; + struct sockaddr_storage server; /* * Only one connection so far */ SMB_ASSERT(conn->release_ip_handler == NULL); - switch (sock->sa_family) { + smbd_ctdb_canonicalize_ip(_client, &client); + smbd_ctdb_canonicalize_ip(_server, &server); + + switch (client.ss_family) { case AF_INET: - p4.dest = *(struct sockaddr_in *)server; - p4.src = *(struct sockaddr_in *)client; + p4.dest = *(struct sockaddr_in *)&server; + p4.src = *(struct sockaddr_in *)&client; data.dptr = (uint8_t *)&p4; data.dsize = sizeof(p4); break; -#ifdef HAVE_IPV6 +#ifdef HAVE_STRUCT_CTDB_CONTROL_TCP_ADDR case AF_INET6: - p.dest.ip6 = *(struct sockaddr_in6 *)server; - p.src.ip6 = *(struct sockaddr_in6 *)client; + p.dest.ip6 = *(struct sockaddr_in6 *)&server; + p.src.ip6 = *(struct sockaddr_in6 *)&client; data.dptr = (uint8_t *)&p; data.dsize = sizeof(p); break; -- cgit From 3639e525a92c1c91dd8d6f9286f1da4a33ee7656 Mon Sep 17 00:00:00 2001 From: Björn Jacke Date: Thu, 29 Jan 2009 00:35:26 +0100 Subject: add AIX sub-second resolution timestamp support --- source3/lib/time.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'source3/lib') diff --git a/source3/lib/time.c b/source3/lib/time.c index 7dd0da8fa8..1466471639 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -404,6 +404,11 @@ struct timespec get_atimespec(const SMB_STRUCT_STAT *pst) ret.tv_sec = pst->st_atime; ret.tv_nsec = pst->st_atimensec; return ret; +#elif defined(HAVE_STAT_ST_ATIME_N) + struct timespec ret; + ret.tv_sec = pst->st_atime; + ret.tv_nsec = pst->st_atime_n; + return ret; #elif defined(HAVE_STAT_ST_ATIMESPEC) return pst->st_atimespec; #else @@ -423,6 +428,9 @@ void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts) #elif defined(HAVE_STAT_ST_ATIMENSEC) pst->st_atime = ts.tv_sec; pst->st_atimensec = ts.tv_nsec +#elif defined(HAVE_STAT_ST_ATIME_N) + pst->st_atime = ts.tv_sec; + pst->st_atime_n = ts.tv_nsec #elif defined(HAVE_STAT_ST_ATIMESPEC) pst->st_atimespec = ts; #else @@ -448,6 +456,11 @@ struct timespec get_mtimespec(const SMB_STRUCT_STAT *pst) ret.tv_sec = pst->st_mtime; ret.tv_nsec = pst->st_mtimensec; return ret; +#elif defined(HAVE_STAT_ST_MTIME_N) + struct timespec ret; + ret.tv_sec = pst->st_mtime; + ret.tv_nsec = pst->st_mtime_n; + return ret; #elif defined(HAVE_STAT_ST_MTIMESPEC) return pst->st_mtimespec; #else @@ -467,6 +480,9 @@ void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts) #elif defined(HAVE_STAT_ST_MTIMENSEC) pst->st_mtime = ts.tv_sec; pst->st_mtimensec = ts.tv_nsec +#elif defined(HAVE_STAT_ST_MTIME_N) + pst->st_mtime = ts.tv_sec; + pst->st_mtime_n = ts.tv_nsec #elif defined(HAVE_STAT_ST_ATIMESPEC) pst->st_atimespec = ts; #else @@ -492,6 +508,11 @@ struct timespec get_ctimespec(const SMB_STRUCT_STAT *pst) ret.tv_sec = pst->st_ctime; ret.tv_nsec = pst->st_ctimensec; return ret; +#elif defined(HAVE_STAT_ST_CTIME_N) + struct timespec ret; + ret.tv_sec = pst->st_ctime; + ret.tv_nsec = pst->st_ctime_n; + return ret; #elif defined(HAVE_STAT_ST_CTIMESPEC) return pst->st_ctimespec; #else @@ -511,6 +532,9 @@ void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts) #elif defined(HAVE_STAT_ST_CTIMENSEC) pst->st_ctime = ts.tv_sec; pst->st_ctimensec = ts.tv_nsec +#elif defined(HAVE_STAT_ST_CTIME_N) + pst->st_ctime = ts.tv_sec; + pst->st_ctime_n = ts.tv_nsec #elif defined(HAVE_STAT_ST_CTIMESPEC) pst->st_ctimespec = ts; #else -- cgit From 12f57f95b504af63634978e6faabb9a1859a4e82 Mon Sep 17 00:00:00 2001 From: Björn Jacke Date: Thu, 29 Jan 2009 13:23:26 +0100 Subject: setting mtime setted atime on BSD systems, fix this --- source3/lib/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/time.c b/source3/lib/time.c index 1466471639..d3b85433ea 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -483,8 +483,8 @@ void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts) #elif defined(HAVE_STAT_ST_MTIME_N) pst->st_mtime = ts.tv_sec; pst->st_mtime_n = ts.tv_nsec -#elif defined(HAVE_STAT_ST_ATIMESPEC) - pst->st_atimespec = ts; +#elif defined(HAVE_STAT_ST_MTIMESPEC) + pst->st_mtimespec = ts; #else #error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT #endif -- cgit From 29ab9ed933ff12d593414d13b5ce584e008f158c Mon Sep 17 00:00:00 2001 From: Björn Jacke Date: Thu, 29 Jan 2009 20:56:51 +0100 Subject: add missing semicolons the fixed configure check led to a missing semicolon in the now activated BSD code. Then this error was even copypasted into the new AIX code. grrr --- source3/lib/time.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/time.c b/source3/lib/time.c index d3b85433ea..682d96c7db 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -427,10 +427,10 @@ void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts) pst->st_atim = ts; #elif defined(HAVE_STAT_ST_ATIMENSEC) pst->st_atime = ts.tv_sec; - pst->st_atimensec = ts.tv_nsec + pst->st_atimensec = ts.tv_nsec; #elif defined(HAVE_STAT_ST_ATIME_N) pst->st_atime = ts.tv_sec; - pst->st_atime_n = ts.tv_nsec + pst->st_atime_n = ts.tv_nsec; #elif defined(HAVE_STAT_ST_ATIMESPEC) pst->st_atimespec = ts; #else @@ -479,10 +479,10 @@ void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts) pst->st_mtim = ts; #elif defined(HAVE_STAT_ST_MTIMENSEC) pst->st_mtime = ts.tv_sec; - pst->st_mtimensec = ts.tv_nsec + pst->st_mtimensec = ts.tv_nsec; #elif defined(HAVE_STAT_ST_MTIME_N) pst->st_mtime = ts.tv_sec; - pst->st_mtime_n = ts.tv_nsec + pst->st_mtime_n = ts.tv_nsec; #elif defined(HAVE_STAT_ST_MTIMESPEC) pst->st_mtimespec = ts; #else @@ -531,10 +531,10 @@ void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts) pst->st_ctim = ts; #elif defined(HAVE_STAT_ST_CTIMENSEC) pst->st_ctime = ts.tv_sec; - pst->st_ctimensec = ts.tv_nsec + pst->st_ctimensec = ts.tv_nsec; #elif defined(HAVE_STAT_ST_CTIME_N) pst->st_ctime = ts.tv_sec; - pst->st_ctime_n = ts.tv_nsec + pst->st_ctime_n = ts.tv_nsec; #elif defined(HAVE_STAT_ST_CTIMESPEC) pst->st_ctimespec = ts; #else -- cgit From 1a87568d99e35c7d028d742c59a3f811a67731e3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 29 Jan 2009 20:07:58 +0100 Subject: Fix the build on "opi" It did not like to include "includes.h" twice --- source3/lib/tdb_validate.c | 2 +- source3/lib/tdb_validate.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/tdb_validate.c b/source3/lib/tdb_validate.c index 948201a5f2..1f5dfe4d25 100644 --- a/source3/lib/tdb_validate.c +++ b/source3/lib/tdb_validate.c @@ -19,8 +19,8 @@ * along with this program. If not, see . */ -#include "includes.h" #include "tdb_validate.h" +#include "includes.h" /* * internal validation function, executed by the child. diff --git a/source3/lib/tdb_validate.h b/source3/lib/tdb_validate.h index 1a207fa669..9eda79d7db 100644 --- a/source3/lib/tdb_validate.h +++ b/source3/lib/tdb_validate.h @@ -22,7 +22,8 @@ #ifndef __TDB_VALIDATE_H__ #define __TDB_VALIDATE_H__ -#include "includes.h" +#include "lib/replace/replace.h" +#include "tdb.h" /** * Flag field for keeping track of the status of a validation. -- cgit From d177015a6d43fcc26a823e52b86850a82261ad4d Mon Sep 17 00:00:00 2001 From: Björn Jacke Date: Thu, 29 Jan 2009 22:59:00 +0100 Subject: add Tru64 sub-second resolution timestamp support --- source3/lib/time.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'source3/lib') diff --git a/source3/lib/time.c b/source3/lib/time.c index 682d96c7db..e2cfe687b2 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -409,6 +409,11 @@ struct timespec get_atimespec(const SMB_STRUCT_STAT *pst) ret.tv_sec = pst->st_atime; ret.tv_nsec = pst->st_atime_n; return ret; +#elif defined(HAVE_STAT_ST_UATIME) + struct timespec ret; + ret.tv_sec = pst->st_atime; + ret.tv_nsec = pst->st_uatime * 1000; + return ret; #elif defined(HAVE_STAT_ST_ATIMESPEC) return pst->st_atimespec; #else @@ -431,6 +436,9 @@ void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts) #elif defined(HAVE_STAT_ST_ATIME_N) pst->st_atime = ts.tv_sec; pst->st_atime_n = ts.tv_nsec; +#elif defined(HAVE_STAT_ST_UATIME) + pst->st_atime = ts.tv_sec; + pst->st_uatime = ts.tv_nsec / 1000; #elif defined(HAVE_STAT_ST_ATIMESPEC) pst->st_atimespec = ts; #else @@ -461,6 +469,11 @@ struct timespec get_mtimespec(const SMB_STRUCT_STAT *pst) ret.tv_sec = pst->st_mtime; ret.tv_nsec = pst->st_mtime_n; return ret; +#elif defined(HAVE_STAT_ST_UMTIME) + struct timespec ret; + ret.tv_sec = pst->st_mtime; + ret.tv_nsec = pst->st_umtime * 1000; + return ret; #elif defined(HAVE_STAT_ST_MTIMESPEC) return pst->st_mtimespec; #else @@ -483,6 +496,9 @@ void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts) #elif defined(HAVE_STAT_ST_MTIME_N) pst->st_mtime = ts.tv_sec; pst->st_mtime_n = ts.tv_nsec; +#elif defined(HAVE_STAT_ST_UMTIME) + pst->st_mtime = ts.tv_sec; + pst->st_umtime = ts.tv_nsec / 1000; #elif defined(HAVE_STAT_ST_MTIMESPEC) pst->st_mtimespec = ts; #else @@ -513,6 +529,11 @@ struct timespec get_ctimespec(const SMB_STRUCT_STAT *pst) ret.tv_sec = pst->st_ctime; ret.tv_nsec = pst->st_ctime_n; return ret; +#elif defined(HAVE_STAT_ST_UCTIME) + struct timespec ret; + ret.tv_sec = pst->st_ctime; + ret.tv_nsec = pst->st_uctime * 1000; + return ret; #elif defined(HAVE_STAT_ST_CTIMESPEC) return pst->st_ctimespec; #else @@ -535,6 +556,9 @@ void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts) #elif defined(HAVE_STAT_ST_CTIME_N) pst->st_ctime = ts.tv_sec; pst->st_ctime_n = ts.tv_nsec; +#elif defined(HAVE_STAT_ST_UCTIME) + pst->st_ctime = ts.tv_sec; + pst->st_uctime = ts.tv_nsec / 1000; #elif defined(HAVE_STAT_ST_CTIMESPEC) pst->st_ctimespec = ts; #else -- cgit From b8f7cdbd79918bba0fea181f97fff5ab0c79192d Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Mon, 26 Jan 2009 15:39:40 -0800 Subject: s3: Add a new SMB_VFS_GET_ALLOC_SIZE vfs operation This allows module implementors to customize what allocation size is returned to the client. --- source3/lib/util.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source3/lib') diff --git a/source3/lib/util.c b/source3/lib/util.c index 2485d1def5..195065a1e0 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -541,6 +541,15 @@ bool directory_exist_stat(char *dname,SMB_STRUCT_STAT *st) return ret; } +/******************************************************************* + Returns the size in bytes of the named given the stat struct. +********************************************************************/ + +uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf) +{ + return sbuf->st_size; +} + /******************************************************************* Returns the size in bytes of the named file. ********************************************************************/ @@ -551,7 +560,7 @@ SMB_OFF_T get_file_size(char *file_name) buf.st_size = 0; if(sys_stat(file_name,&buf) != 0) return (SMB_OFF_T)-1; - return(buf.st_size); + return get_file_size_stat(&buf); } /******************************************************************* -- cgit From 50db8ede23dd9bf28a4f329edebb9105be215d3e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 30 Jan 2009 14:36:48 +0100 Subject: s3:smbconftort: don't use reserved words ('test:', 'failure:', 'success:') Temporary results printfs should not contain reserved subunit words. metze --- source3/lib/smbconf/testsuite.c | 60 ++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 31 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/smbconf/testsuite.c b/source3/lib/smbconf/testsuite.c index 3d3c2d0ff0..b31dec0438 100644 --- a/source3/lib/smbconf/testsuite.c +++ b/source3/lib/smbconf/testsuite.c @@ -41,11 +41,11 @@ static bool test_get_includes(struct smbconf_ctx *ctx) char **includes = NULL; TALLOC_CTX *mem_ctx = talloc_stackframe(); - printf("test: get_includes\n"); + printf("TEST: get_includes\n"); werr = smbconf_get_global_includes(ctx, mem_ctx, &num_includes, &includes); if (!W_ERROR_IS_OK(werr)) { - printf("failure: get_includes - %s\n", win_errstr(werr)); + printf("FAIL: get_includes - %s\n", win_errstr(werr)); goto done; } @@ -53,7 +53,7 @@ static bool test_get_includes(struct smbconf_ctx *ctx) (num_includes > 0) ? ":" : "."); print_strings("", num_includes, (const char **)includes); - printf("success: get_includes\n"); + printf("OK: get_includes\n"); ret = true; done: @@ -75,11 +75,11 @@ static bool test_set_get_includes(struct smbconf_ctx *ctx) uint32_t get_num_includes = 0; TALLOC_CTX *mem_ctx = talloc_stackframe(); - printf("test: set_get_includes\n"); + printf("TEST: set_get_includes\n"); werr = smbconf_set_global_includes(ctx, set_num_includes, set_includes); if (!W_ERROR_IS_OK(werr)) { - printf("failure: get_set_includes (setting includes) - %s\n", + printf("FAIL: get_set_includes (setting includes) - %s\n", win_errstr(werr)); goto done; } @@ -87,13 +87,13 @@ static bool test_set_get_includes(struct smbconf_ctx *ctx) werr = smbconf_get_global_includes(ctx, mem_ctx, &get_num_includes, &get_includes); if (!W_ERROR_IS_OK(werr)) { - printf("failure: get_set_includes (getting includes) - %s\n", + printf("FAIL: get_set_includes (getting includes) - %s\n", win_errstr(werr)); goto done; } if (get_num_includes != set_num_includes) { - printf("failure: get_set_includes - set %d includes, got %d\n", + printf("FAIL: get_set_includes - set %d includes, got %d\n", set_num_includes, get_num_includes); goto done; } @@ -105,12 +105,12 @@ static bool test_set_get_includes(struct smbconf_ctx *ctx) printf("got: \n"); print_strings("* ", get_num_includes, (const char **)get_includes); - printf("failure: get_set_includes - data mismatch:\n"); + printf("FAIL: get_set_includes - data mismatch:\n"); goto done; } } - printf("success: set_includes\n"); + printf("OK: set_includes\n"); ret = true; done: @@ -130,18 +130,18 @@ static bool test_delete_includes(struct smbconf_ctx *ctx) uint32_t get_num_includes = 0; TALLOC_CTX *mem_ctx = talloc_stackframe(); - printf("test: delete_includes\n"); + printf("TEST: delete_includes\n"); werr = smbconf_set_global_includes(ctx, set_num_includes, set_includes); if (!W_ERROR_IS_OK(werr)) { - printf("failure: delete_includes (setting includes) - %s\n", + printf("FAIL: delete_includes (setting includes) - %s\n", win_errstr(werr)); goto done; } werr = smbconf_delete_global_includes(ctx); if (!W_ERROR_IS_OK(werr)) { - printf("failure: delete_includes (deleting includes) - %s\n", + printf("FAIL: delete_includes (deleting includes) - %s\n", win_errstr(werr)); goto done; } @@ -149,24 +149,24 @@ static bool test_delete_includes(struct smbconf_ctx *ctx) werr = smbconf_get_global_includes(ctx, mem_ctx, &get_num_includes, &get_includes); if (!W_ERROR_IS_OK(werr)) { - printf("failure: delete_includes (getting includes) - %s\n", + printf("FAIL: delete_includes (getting includes) - %s\n", win_errstr(werr)); goto done; } if (get_num_includes != 0) { - printf("failure: delete_includes (not empty after delete)\n"); + printf("FAIL: delete_includes (not empty after delete)\n"); goto done; } werr = smbconf_delete_global_includes(ctx); if (!W_ERROR_IS_OK(werr)) { - printf("failuer: delete_includes (delete empty includes) - " + printf("FAIL: delete_includes (delete empty includes) - " "%s\n", win_errstr(werr)); goto done; } - printf("success: delete_includes\n"); + printf("OK: delete_includes\n"); ret = true; done: @@ -177,7 +177,7 @@ static bool create_conf_file(const char *filename) { FILE *f; - printf("creating file\n"); + printf("TEST: creating file\n"); f = sys_fopen(filename, "w"); if (!f) { printf("failure: failed to open %s for writing: %s\n", @@ -192,7 +192,7 @@ static bool create_conf_file(const char *filename) fclose(f); - printf("success: create file\n"); + printf("OK: create file\n"); return true; } @@ -211,30 +211,29 @@ static bool torture_smbconf_txt(void) goto done; } - printf("test: init\n"); + printf("TEST: init\n"); werr = smbconf_init_txt(mem_ctx, &conf_ctx, filename); if (!W_ERROR_IS_OK(werr)) { - printf("failure: init failed: %s\n", win_errstr(werr)); + printf("FAIL: text backend\[ failed: %s\n", win_errstr(werr)); ret = false; goto done; } - printf("success: init\n"); + printf("OK: init\n"); ret &= test_get_includes(conf_ctx); smbconf_shutdown(conf_ctx); - printf("unlinking file\n"); + printf("TEST: unlink file\n"); if (unlink(filename) != 0) { - printf("failure: unlink failed: %s\n", strerror(errno)); + printf("OK: unlink failed: %s\n", strerror(errno)); ret = false; goto done; } - printf("success: unlink file\n"); - - printf("%s: text backend\n", ret ? "success" : "failure"); + printf("OK: unlink file\n"); done: + printf("%s: text backend\n", ret ? "success" : "failure"); talloc_free(mem_ctx); return ret; } @@ -248,14 +247,14 @@ static bool torture_smbconf_reg(void) printf("test: registry backend\n"); - printf("test: init\n"); + printf("TEST: init\n"); werr = smbconf_init_reg(mem_ctx, &conf_ctx, NULL); if (!W_ERROR_IS_OK(werr)) { - printf("failure: init failed: %s\n", win_errstr(werr)); + printf("FAIL: init failed: %s\n", win_errstr(werr)); ret = false; goto done; } - printf("success: init\n"); + printf("OK: init\n"); ret &= test_get_includes(conf_ctx); ret &= test_set_get_includes(conf_ctx); @@ -263,9 +262,8 @@ static bool torture_smbconf_reg(void) smbconf_shutdown(conf_ctx); - printf("%s: registry backend\n", ret ? "success" : "failure"); - done: + printf("%s: registry backend\n", ret ? "success" : "failure"); talloc_free(mem_ctx); return ret; } -- cgit From d94e9c802ceddeff93168337b6fc5533db7f2d33 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 30 Jan 2009 23:44:21 +0100 Subject: Remove the global variable "chain_size" --- source3/lib/util.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/util.c b/source3/lib/util.c index 195065a1e0..df01c0306f 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -57,9 +57,6 @@ extern unsigned int global_clobber_region_line; enum protocol_types Protocol = PROTOCOL_COREPLUS; -/* this is used by the chaining code */ -int chain_size = 0; - static enum remote_arch_types ra_type = RA_UNKNOWN; /*********************************************************************** -- cgit From 57de60a83f3f88566d356547eb20a6f0569f76ec Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 1 Feb 2009 00:30:04 +0100 Subject: cli_get_pipe_name_from_interface does not really need a talloc_ctx --- source3/lib/netapi/cm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib') diff --git a/source3/lib/netapi/cm.c b/source3/lib/netapi/cm.c index d5ef09d831..233255fed4 100644 --- a/source3/lib/netapi/cm.c +++ b/source3/lib/netapi/cm.c @@ -184,7 +184,7 @@ WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, status = pipe_cm_open(ctx, cli, interface, &result); if (!NT_STATUS_IS_OK(status)) { libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s", - cli_get_pipe_name_from_iface(debug_ctx(), interface), + get_pipe_name_from_iface(interface), get_friendly_nt_error_msg(status)); return WERR_DEST_NOT_FOUND; } -- cgit From c14b7e648bcfc4865da4b290e46977fff81d4500 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 1 Feb 2009 16:32:02 +0100 Subject: Split up async_req into a generic and a NTSTATUS specific part --- source3/lib/util_sock.c | 26 +++++++++++------------ source3/lib/wb_reqtrans.c | 50 +++++++++++++++++++++---------------------- source3/lib/wbclient.c | 54 +++++++++++++++++++++++------------------------ 3 files changed, 65 insertions(+), 65 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 3ddc4342a7..bafcdc5c5c 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -1036,7 +1036,7 @@ struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx, return result; post_status: - if (!async_post_status(result, ev, status)) { + if (!async_post_ntstatus(result, ev, status)) { goto fail; } return result; @@ -1077,12 +1077,12 @@ static void open_socket_out_connected(struct async_req *subreq) subreq = async_connect_send(state, state->ev, state->fd, (struct sockaddr *)&state->ss, state->salen); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } if (!async_req_set_timeout(subreq, state->ev, timeval_set(0, state->wait_nsec))) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); return; } subreq->async.fn = open_socket_out_connected; @@ -1098,7 +1098,7 @@ static void open_socket_out_connected(struct async_req *subreq) #endif /* real error */ - async_req_error(req, map_nt_error_from_unix(sys_errno)); + async_req_nterror(req, map_nt_error_from_unix(sys_errno)); } NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd) @@ -1107,7 +1107,7 @@ NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd) req->private_data, struct open_socket_out_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *pfd = state->fd; @@ -1183,7 +1183,7 @@ struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx, return result; post_status: - if (!async_post_status(result, ev, status)) { + if (!async_post_ntstatus(result, ev, status)) { goto fail; } return result; @@ -1198,18 +1198,18 @@ static void open_socket_out_defer_waited(struct async_req *subreq) subreq->async.priv, struct async_req); struct open_socket_out_defer_state *state = talloc_get_type_abort( req->private_data, struct open_socket_out_defer_state); - NTSTATUS status; + bool ret; - status = async_wait_recv(subreq); + ret = async_wait_recv(subreq); TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + if (!ret) { + async_req_nterror(req, NT_STATUS_INTERNAL_ERROR); return; } subreq = open_socket_out_send(state, state->ev, &state->ss, state->port, state->timeout); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } subreq->async.fn = open_socket_out_defer_connected; @@ -1227,7 +1227,7 @@ static void open_socket_out_defer_connected(struct async_req *subreq) status = open_socket_out_recv(subreq, &state->fd); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -1239,7 +1239,7 @@ NTSTATUS open_socket_out_defer_recv(struct async_req *req, int *pfd) req->private_data, struct open_socket_out_defer_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *pfd = state->fd; diff --git a/source3/lib/wb_reqtrans.c b/source3/lib/wb_reqtrans.c index 0e6e5d15c4..7bca627690 100644 --- a/source3/lib/wb_reqtrans.c +++ b/source3/lib/wb_reqtrans.c @@ -81,7 +81,7 @@ static void wb_req_read_len(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -89,14 +89,14 @@ static void wb_req_read_len(struct async_req *subreq) DEBUG(0, ("wb_req_read_len: Invalid request size received: " "%d (expected %d)\n", (int)state->wb_req->length, (int)sizeof(struct winbindd_request))); - async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + async_req_nterror(req, NT_STATUS_INVALID_BUFFER_SIZE); return; } subreq = recvall_send( req, state->ev, state->fd, (uint32 *)(state->wb_req)+1, sizeof(struct winbindd_request) - sizeof(uint32), 0); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } @@ -115,7 +115,7 @@ static void wb_req_read_main(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -124,7 +124,7 @@ static void wb_req_read_main(struct async_req *subreq) DEBUG(3, ("Got request with %d bytes extra data on " "unprivileged socket\n", (int)state->wb_req->extra_len)); - async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + async_req_nterror(req, NT_STATUS_INVALID_BUFFER_SIZE); return; } @@ -135,7 +135,7 @@ static void wb_req_read_main(struct async_req *subreq) state->wb_req->extra_data.data = TALLOC_ARRAY( state->wb_req, char, state->wb_req->extra_len + 1); - if (async_req_nomem(state->wb_req->extra_data.data, req)) { + if (async_req_ntnomem(state->wb_req->extra_data.data, req)) { return; } @@ -144,7 +144,7 @@ static void wb_req_read_main(struct async_req *subreq) subreq = recvall_send( req, state->ev, state->fd, state->wb_req->extra_data.data, state->wb_req->extra_len, 0); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } @@ -161,7 +161,7 @@ static void wb_req_read_extra(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -175,7 +175,7 @@ NTSTATUS wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, req->private_data, struct req_read_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *preq = talloc_move(mem_ctx, &state->wb_req); @@ -232,7 +232,7 @@ static void wb_req_write_main(struct async_req *subreq) status = sendall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -244,7 +244,7 @@ static void wb_req_write_main(struct async_req *subreq) subreq = sendall_send(state, state->ev, state->fd, state->wb_req->extra_data.data, state->wb_req->extra_len, 0); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } @@ -261,7 +261,7 @@ static void wb_req_write_extra(struct async_req *subreq) status = sendall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -270,7 +270,7 @@ static void wb_req_write_extra(struct async_req *subreq) NTSTATUS wb_req_write_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } struct resp_read_state { @@ -327,7 +327,7 @@ static void wb_resp_read_len(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -336,14 +336,14 @@ static void wb_resp_read_len(struct async_req *subreq) "%d (expected at least%d)\n", (int)state->wb_resp->length, (int)sizeof(struct winbindd_response))); - async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE); + async_req_nterror(req, NT_STATUS_INVALID_BUFFER_SIZE); return; } subreq = recvall_send( req, state->ev, state->fd, (uint32 *)(state->wb_resp)+1, sizeof(struct winbindd_response) - sizeof(uint32), 0); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } @@ -363,7 +363,7 @@ static void wb_resp_read_main(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -375,7 +375,7 @@ static void wb_resp_read_main(struct async_req *subreq) state->wb_resp->extra_data.data = TALLOC_ARRAY( state->wb_resp, char, extra_len+1); - if (async_req_nomem(state->wb_resp->extra_data.data, req)) { + if (async_req_ntnomem(state->wb_resp->extra_data.data, req)) { return; } ((char *)state->wb_resp->extra_data.data)[extra_len] = 0; @@ -383,7 +383,7 @@ static void wb_resp_read_main(struct async_req *subreq) subreq = recvall_send( req, state->ev, state->fd, state->wb_resp->extra_data.data, extra_len, 0); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } @@ -400,7 +400,7 @@ static void wb_resp_read_extra(struct async_req *subreq) status = recvall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } async_req_done(req); @@ -414,7 +414,7 @@ NTSTATUS wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, req->private_data, struct resp_read_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } *presp = talloc_move(mem_ctx, &state->wb_resp); @@ -471,7 +471,7 @@ static void wb_resp_write_main(struct async_req *subreq) status = sendall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -484,7 +484,7 @@ static void wb_resp_write_main(struct async_req *subreq) state, state->ev, state->fd, state->wb_resp->extra_data.data, state->wb_resp->length - sizeof(struct winbindd_response), 0); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } @@ -501,7 +501,7 @@ static void wb_resp_write_extra(struct async_req *subreq) status = sendall_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -510,5 +510,5 @@ static void wb_resp_write_extra(struct async_req *subreq) NTSTATUS wb_resp_write_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } diff --git a/source3/lib/wbclient.c b/source3/lib/wbclient.c index ea0bcb512e..cf5ce7e734 100644 --- a/source3/lib/wbclient.c +++ b/source3/lib/wbclient.c @@ -232,7 +232,7 @@ static struct async_req *wb_connect_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } - if (async_post_status(req, ev, status)) { + if (async_post_ntstatus(req, ev, status)) { return req; } TALLOC_FREE(req); @@ -295,8 +295,8 @@ static struct async_req *wb_int_trans_send(TALLOC_CTX *mem_ctx, } if (winbind_closed_fd(fd)) { - if (!async_post_status(result, ev, - NT_STATUS_PIPE_DISCONNECTED)) { + if (!async_post_ntstatus(result, ev, + NT_STATUS_PIPE_DISCONNECTED)) { goto fail; } return result; @@ -334,13 +334,13 @@ static void wb_int_trans_write_done(struct async_req *subreq) status = wb_req_write_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } subreq = wb_resp_read_send(state, state->ev, state->fd); if (subreq == NULL) { - async_req_error(req, NT_STATUS_NO_MEMORY); + async_req_nterror(req, NT_STATUS_NO_MEMORY); } subreq->async.fn = wb_int_trans_read_done; subreq->async.priv = req; @@ -357,7 +357,7 @@ static void wb_int_trans_read_done(struct async_req *subreq) status = wb_resp_read_recv(subreq, state, &state->wb_resp); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -372,7 +372,7 @@ static NTSTATUS wb_int_trans_recv(struct async_req *req, req->private_data, struct wb_int_trans_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } @@ -454,7 +454,7 @@ static void wb_open_pipe_connect_nonpriv_done(struct async_req *subreq) TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { state->wb_ctx->is_priv = true; - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -463,7 +463,7 @@ static void wb_open_pipe_connect_nonpriv_done(struct async_req *subreq) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, &state->wb_req); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } @@ -483,7 +483,7 @@ static void wb_open_pipe_ping_done(struct async_req *subreq) status = wb_int_trans_recv(subreq, state, &wb_resp); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -496,7 +496,7 @@ static void wb_open_pipe_ping_done(struct async_req *subreq) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, &state->wb_req); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } @@ -516,7 +516,7 @@ static void wb_open_pipe_getpriv_done(struct async_req *subreq) status = wb_int_trans_recv(subreq, state, &wb_resp); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } @@ -526,7 +526,7 @@ static void wb_open_pipe_getpriv_done(struct async_req *subreq) subreq = wb_connect_send(state, state->ev, state->wb_ctx, (char *)wb_resp->extra_data.data); TALLOC_FREE(wb_resp); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } @@ -545,7 +545,7 @@ static void wb_open_pipe_connect_priv_done(struct async_req *subreq) status = wb_connect_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { - async_req_error(req, status); + async_req_nterror(req, status); return; } state->wb_ctx->is_priv = true; @@ -554,7 +554,7 @@ static void wb_open_pipe_connect_priv_done(struct async_req *subreq) static NTSTATUS wb_open_pipe_recv(struct async_req *req) { - return async_req_simple_recv(req); + return async_req_simple_recv_ntstatus(req); } struct wb_trans_state { @@ -582,7 +582,7 @@ static void wb_trigger_trans(struct async_req *req) subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, state->need_priv); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } subreq->async.fn = wb_trans_connect_done; @@ -592,7 +592,7 @@ static void wb_trigger_trans(struct async_req *req) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, state->wb_req); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } subreq->async.fn = wb_trans_done; @@ -645,13 +645,13 @@ static bool wb_trans_retry(struct async_req *req, * Winbind not around or we can't connect to the pipe. Fail * immediately. */ - async_req_error(req, status); + async_req_nterror(req, status); return true; } state->num_retries -= 1; if (state->num_retries == 0) { - async_req_error(req, status); + async_req_nterror(req, status); return true; } @@ -665,7 +665,7 @@ static bool wb_trans_retry(struct async_req *req, } subreq = async_wait_send(state, state->ev, timeval_set(1, 0)); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return true; } @@ -680,18 +680,18 @@ static void wb_trans_retry_wait_done(struct async_req *subreq) subreq->async.priv, struct async_req); struct wb_trans_state *state = talloc_get_type_abort( req->private_data, struct wb_trans_state); - NTSTATUS status; + bool ret; - status = async_wait_recv(subreq); + ret = async_wait_recv(subreq); TALLOC_FREE(subreq); - if (!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - async_req_error(req, status); + if (ret) { + async_req_nterror(req, NT_STATUS_INTERNAL_ERROR); return; } subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, state->need_priv); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } subreq->async.fn = wb_trans_connect_done; @@ -715,7 +715,7 @@ static void wb_trans_connect_done(struct async_req *subreq) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, state->wb_req); - if (async_req_nomem(subreq, req)) { + if (async_req_ntnomem(subreq, req)) { return; } @@ -748,7 +748,7 @@ NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx, req->private_data, struct wb_trans_state); NTSTATUS status; - if (async_req_is_error(req, &status)) { + if (async_req_is_nterror(req, &status)) { return status; } -- cgit From d3f9b0fab67285d061719e69c1c6e9c4ce80fb36 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 2 Feb 2009 17:23:35 +0100 Subject: Next step disentangling async_req from NTSTATUS Now I need to document this :-) --- source3/lib/util_sock.c | 4 ++-- source3/lib/wb_reqtrans.c | 16 ++++++++-------- source3/lib/wbclient.c | 16 ++++++++-------- 3 files changed, 18 insertions(+), 18 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index bafcdc5c5c..78431d93c8 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -1077,7 +1077,7 @@ static void open_socket_out_connected(struct async_req *subreq) subreq = async_connect_send(state, state->ev, state->fd, (struct sockaddr *)&state->ss, state->salen); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } if (!async_req_set_timeout(subreq, state->ev, @@ -1209,7 +1209,7 @@ static void open_socket_out_defer_waited(struct async_req *subreq) subreq = open_socket_out_send(state, state->ev, &state->ss, state->port, state->timeout); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = open_socket_out_defer_connected; diff --git a/source3/lib/wb_reqtrans.c b/source3/lib/wb_reqtrans.c index 7bca627690..e779e47d28 100644 --- a/source3/lib/wb_reqtrans.c +++ b/source3/lib/wb_reqtrans.c @@ -96,7 +96,7 @@ static void wb_req_read_len(struct async_req *subreq) subreq = recvall_send( req, state->ev, state->fd, (uint32 *)(state->wb_req)+1, sizeof(struct winbindd_request) - sizeof(uint32), 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -135,7 +135,7 @@ static void wb_req_read_main(struct async_req *subreq) state->wb_req->extra_data.data = TALLOC_ARRAY( state->wb_req, char, state->wb_req->extra_len + 1); - if (async_req_ntnomem(state->wb_req->extra_data.data, req)) { + if (async_req_nomem(state->wb_req->extra_data.data, req)) { return; } @@ -144,7 +144,7 @@ static void wb_req_read_main(struct async_req *subreq) subreq = recvall_send( req, state->ev, state->fd, state->wb_req->extra_data.data, state->wb_req->extra_len, 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -244,7 +244,7 @@ static void wb_req_write_main(struct async_req *subreq) subreq = sendall_send(state, state->ev, state->fd, state->wb_req->extra_data.data, state->wb_req->extra_len, 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -343,7 +343,7 @@ static void wb_resp_read_len(struct async_req *subreq) subreq = recvall_send( req, state->ev, state->fd, (uint32 *)(state->wb_resp)+1, sizeof(struct winbindd_response) - sizeof(uint32), 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -375,7 +375,7 @@ static void wb_resp_read_main(struct async_req *subreq) state->wb_resp->extra_data.data = TALLOC_ARRAY( state->wb_resp, char, extra_len+1); - if (async_req_ntnomem(state->wb_resp->extra_data.data, req)) { + if (async_req_nomem(state->wb_resp->extra_data.data, req)) { return; } ((char *)state->wb_resp->extra_data.data)[extra_len] = 0; @@ -383,7 +383,7 @@ static void wb_resp_read_main(struct async_req *subreq) subreq = recvall_send( req, state->ev, state->fd, state->wb_resp->extra_data.data, extra_len, 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -484,7 +484,7 @@ static void wb_resp_write_main(struct async_req *subreq) state, state->ev, state->fd, state->wb_resp->extra_data.data, state->wb_resp->length - sizeof(struct winbindd_response), 0); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } diff --git a/source3/lib/wbclient.c b/source3/lib/wbclient.c index cf5ce7e734..f22b96a99a 100644 --- a/source3/lib/wbclient.c +++ b/source3/lib/wbclient.c @@ -463,7 +463,7 @@ static void wb_open_pipe_connect_nonpriv_done(struct async_req *subreq) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, &state->wb_req); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -496,7 +496,7 @@ static void wb_open_pipe_ping_done(struct async_req *subreq) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, &state->wb_req); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -526,7 +526,7 @@ static void wb_open_pipe_getpriv_done(struct async_req *subreq) subreq = wb_connect_send(state, state->ev, state->wb_ctx, (char *)wb_resp->extra_data.data); TALLOC_FREE(wb_resp); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } @@ -582,7 +582,7 @@ static void wb_trigger_trans(struct async_req *req) subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, state->need_priv); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = wb_trans_connect_done; @@ -592,7 +592,7 @@ static void wb_trigger_trans(struct async_req *req) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, state->wb_req); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = wb_trans_done; @@ -665,7 +665,7 @@ static bool wb_trans_retry(struct async_req *req, } subreq = async_wait_send(state, state->ev, timeval_set(1, 0)); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return true; } @@ -691,7 +691,7 @@ static void wb_trans_retry_wait_done(struct async_req *subreq) subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx, state->need_priv); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } subreq->async.fn = wb_trans_connect_done; @@ -715,7 +715,7 @@ static void wb_trans_connect_done(struct async_req *subreq) subreq = wb_int_trans_send(state, state->ev, state->wb_ctx->fd, state->wb_req); - if (async_req_ntnomem(subreq, req)) { + if (async_req_nomem(subreq, req)) { return; } -- cgit From 6ed02233c3d873d4aa6ee4306d61cc2aad465a5d Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Mon, 2 Feb 2009 22:14:57 +0100 Subject: s3-wbclient: Use new tevent data types --- source3/lib/wb_reqtrans.c | 16 ++++++++-------- source3/lib/wbclient.c | 14 +++++++------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/wb_reqtrans.c b/source3/lib/wb_reqtrans.c index e779e47d28..b56c0fd4d3 100644 --- a/source3/lib/wb_reqtrans.c +++ b/source3/lib/wb_reqtrans.c @@ -27,7 +27,7 @@ struct req_read_state { struct winbindd_request *wb_req; - struct event_context *ev; + struct tevent_context *ev; size_t max_extra_data; int fd; }; @@ -37,7 +37,7 @@ static void wb_req_read_main(struct async_req *subreq); static void wb_req_read_extra(struct async_req *subreq); struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, + struct tevent_context *ev, int fd, size_t max_extra_data) { struct async_req *result, *subreq; @@ -184,7 +184,7 @@ NTSTATUS wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, struct req_write_state { struct winbindd_request *wb_req; - struct event_context *ev; + struct tevent_context *ev; int fd; }; @@ -192,7 +192,7 @@ static void wb_req_write_main(struct async_req *subreq); static void wb_req_write_extra(struct async_req *subreq); struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, int fd, + struct tevent_context *ev, int fd, struct winbindd_request *wb_req) { struct async_req *result, *subreq; @@ -275,7 +275,7 @@ NTSTATUS wb_req_write_recv(struct async_req *req) struct resp_read_state { struct winbindd_response *wb_resp; - struct event_context *ev; + struct tevent_context *ev; size_t max_extra_data; int fd; }; @@ -285,7 +285,7 @@ static void wb_resp_read_main(struct async_req *subreq); static void wb_resp_read_extra(struct async_req *subreq); struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, int fd) + struct tevent_context *ev, int fd) { struct async_req *result, *subreq; struct resp_read_state *state; @@ -423,7 +423,7 @@ NTSTATUS wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx, struct resp_write_state { struct winbindd_response *wb_resp; - struct event_context *ev; + struct tevent_context *ev; int fd; }; @@ -431,7 +431,7 @@ static void wb_resp_write_main(struct async_req *subreq); static void wb_resp_write_extra(struct async_req *subreq); struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, int fd, + struct tevent_context *ev, int fd, struct winbindd_response *wb_resp) { struct async_req *result, *subreq; diff --git a/source3/lib/wbclient.c b/source3/lib/wbclient.c index f22b96a99a..ae9a034cc8 100644 --- a/source3/lib/wbclient.c +++ b/source3/lib/wbclient.c @@ -155,7 +155,7 @@ struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx) } static struct async_req *wb_connect_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, + struct tevent_context *ev, struct wb_context *wb_ctx, const char *dir) { @@ -272,7 +272,7 @@ static struct winbindd_request *winbindd_request_copy( } struct wb_int_trans_state { - struct event_context *ev; + struct tevent_context *ev; int fd; struct winbindd_request *wb_req; struct winbindd_response *wb_resp; @@ -282,7 +282,7 @@ static void wb_int_trans_write_done(struct async_req *subreq); static void wb_int_trans_read_done(struct async_req *subreq); static struct async_req *wb_int_trans_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, int fd, + struct tevent_context *ev, int fd, struct winbindd_request *wb_req) { struct async_req *result; @@ -396,7 +396,7 @@ static const char *winbindd_socket_dir(void) struct wb_open_pipe_state { struct wb_context *wb_ctx; - struct event_context *ev; + struct tevent_context *ev; bool need_priv; struct winbindd_request wb_req; }; @@ -407,7 +407,7 @@ static void wb_open_pipe_getpriv_done(struct async_req *subreq); static void wb_open_pipe_connect_priv_done(struct async_req *subreq); static struct async_req *wb_open_pipe_send(TALLOC_CTX *mem_ctx, - struct event_context *ev, + struct tevent_context *ev, struct wb_context *wb_ctx, bool need_priv) { @@ -560,7 +560,7 @@ static NTSTATUS wb_open_pipe_recv(struct async_req *req) struct wb_trans_state { struct wb_trans_state *prev, *next; struct wb_context *wb_ctx; - struct event_context *ev; + struct tevent_context *ev; struct winbindd_request *wb_req; struct winbindd_response *wb_resp; int num_retries; @@ -599,7 +599,7 @@ static void wb_trigger_trans(struct async_req *req) subreq->async.priv = req; } -struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct event_context *ev, +struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct wb_context *wb_ctx, bool need_priv, const struct winbindd_request *wb_req) { -- cgit From 553818add80818909268557665e2760a16f2d8a0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 2 Feb 2009 17:10:27 -0800 Subject: Fix bug #6082 - smbd_gpfs_getacl failed: Windows client can´t rename or delete file This fixes the generic rename/delete problem for 3.3.0 and above. Fixed slightly differently to discussions, user viewable modified ACLs are not a good idea :-). Jeremy. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/lib/util_seaccess.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/lib') diff --git a/source3/lib/util_seaccess.c b/source3/lib/util_seaccess.c index fdc10f20ab..0da7442d19 100644 --- a/source3/lib/util_seaccess.c +++ b/source3/lib/util_seaccess.c @@ -149,7 +149,9 @@ static uint32_t access_check_max_allowed(const struct security_descriptor *sd, } /* - the main entry point for access checking. + The main entry point for access checking. If returning ACCESS_DENIED + this function returns the denied bits in the uint32_t pointed + to by the access_granted pointer. */ NTSTATUS se_access_check(const struct security_descriptor *sd, const NT_USER_TOKEN *token, @@ -238,6 +240,7 @@ NTSTATUS se_access_check(const struct security_descriptor *sd, done: if (bits_remaining != 0) { + *access_granted = bits_remaining; return NT_STATUS_ACCESS_DENIED; } -- cgit From 83cf98f113541acca5a9b4d6ad084d401b64706f Mon Sep 17 00:00:00 2001 From: Aravind Srinivasan Date: Wed, 4 Feb 2009 16:05:36 -0800 Subject: Have nmbd check all available interfaces for WINS before failing When nmbd is acting as WINS, it picks the first interface's IP as WINS server's IP. If the first interface's IP is zero, we will just quit (even though we might have other interfaces with valid IPs). This patch makes nmbd look at all interfaces and pick the first interface with a valid IP as the WINS server's IP. --- source3/lib/interface.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/lib') diff --git a/source3/lib/interface.c b/source3/lib/interface.c index 48fa4d32a9..b32ccb9c56 100644 --- a/source3/lib/interface.c +++ b/source3/lib/interface.c @@ -151,7 +151,8 @@ int iface_count_v4_nl(void) } /**************************************************************************** - Return a pointer to the in_addr of the first IPv4 interface. + Return a pointer to the in_addr of the first IPv4 interface that's + not 0.0.0.0. **************************************************************************/ const struct in_addr *first_ipv4_iface(void) @@ -159,7 +160,9 @@ const struct in_addr *first_ipv4_iface(void) struct interface *i; for (i=local_interfaces;i ;i=i->next) { - if (i->ip.ss_family == AF_INET) { + if ((i->ip.ss_family == AF_INET) && + (!is_zero_ip_v4(((struct sockaddr_in *)&i->ip)->sin_addr))) + { break; } } -- cgit