s3-talloc Change TALLOC_ZERO_P() to talloc_zero()
[samba.git] / source3 / smbd / notify_internal.c
index 973db7b7b1d1bca4ff0443965fda61a5977d36db..3aea1625eb6923f2303b45b03e0f749ada1be572 100644 (file)
 */
 
 #include "includes.h"
+#include "system/filesys.h"
 #include "librpc/gen_ndr/ndr_notify.h"
+#include "dbwrap.h"
+#include "smbd/smbd.h"
+#include "messages.h"
+#include "lib/util/tdb_wrap.h"
+#include "util_tdb.h"
 
 struct notify_context {
        struct db_context *db_recursive;
@@ -93,7 +99,7 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
        }
 
        notify->db_recursive = db_open(notify, lock_path("notify.tdb"),
-                                      0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
+                                      0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
                                       O_RDWR|O_CREAT, 0644);
        if (notify->db_recursive == NULL) {
                talloc_free(notify);
@@ -101,7 +107,7 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
        }
 
        notify->db_onelevel = db_open(notify, lock_path("notify_onelevel.tdb"),
-                                     0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
+                                     0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
                                      O_RDWR|O_CREAT, 0644);
        if (notify->db_onelevel == NULL) {
                talloc_free(notify);
@@ -128,6 +134,38 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
        return notify;
 }
 
+bool notify_internal_parent_init(TALLOC_CTX *mem_ctx)
+{
+       struct tdb_wrap *db1, *db2;
+
+       if (lp_clustering()) {
+               return true;
+       }
+
+       /*
+        * Open the tdbs in the parent process (smbd) so that our
+        * CLEAR_IF_FIRST optimization in tdb_reopen_all can properly
+        * work.
+        */
+
+       db1 = tdb_wrap_open(mem_ctx, lock_path("notify.tdb"),
+                           0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
+                          O_RDWR|O_CREAT, 0644);
+       if (db1 == NULL) {
+               DEBUG(1, ("could not open notify.tdb: %s\n", strerror(errno)));
+               return false;
+       }
+       db2 = tdb_wrap_open(mem_ctx, lock_path("notify_onelevel.tdb"),
+                           0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, O_RDWR|O_CREAT, 0644);
+       if (db2 == NULL) {
+               DEBUG(1, ("could not open notify_onelevel.tdb: %s\n",
+                         strerror(errno)));
+               TALLOC_FREE(db1);
+               return false;
+       }
+       return true;
+}
+
 /*
   lock and fetch the record
 */
@@ -160,7 +198,7 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec
        notify->seqnum = seqnum;
 
        talloc_free(notify->array);
-       notify->array = TALLOC_ZERO_P(notify, struct notify_array);
+       notify->array = talloc_zero(notify, struct notify_array);
        NT_STATUS_HAVE_NO_MEMORY(notify->array);
 
        if (!rec) {
@@ -178,17 +216,28 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec
        status = NT_STATUS_OK;
        if (blob.length > 0) {
                enum ndr_err_code ndr_err;
-               ndr_err = ndr_pull_struct_blob(&blob, notify->array, NULL, notify->array,
+               ndr_err = ndr_pull_struct_blob(&blob, notify->array, notify->array,
                                               (ndr_pull_flags_fn_t)ndr_pull_notify_array);
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-                       status = ndr_map_error2ntstatus(ndr_err);
+                       /* 1. log that we got a corrupt notify_array
+                        * 2. clear the variable the garbage was stored into to not trip
+                        *  over it next time this method is entered with the same seqnum
+                        * 3. delete it from the database */
+                       DEBUG(2, ("notify_array is corrupt, discarding it\n"));
+
+                       ZERO_STRUCTP(notify->array);
+                       if (rec != NULL) {
+                               rec->delete_rec(rec);
+                       }
+
+               } else {
+                       if (DEBUGLEVEL >= 10) {
+                               DEBUG(10, ("notify_load:\n"));
+                               NDR_PRINT_DEBUG(notify_array, notify->array);
+                       }
                }
        }
 
-       if (DEBUGLEVEL >= 10) {
-               DEBUG(10, ("notify_load:\n"));
-               NDR_PRINT_DEBUG(notify_array, notify->array);
-       }
 
        if (!rec) {
                talloc_free(dbuf.dptr);
@@ -200,10 +249,8 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec
 /*
   compare notify entries for sorting
 */
-static int notify_compare(const void *p1, const void *p2)
+static int notify_compare(const struct notify_entry *e1, const struct notify_entry *e2)
 {
-       const struct notify_entry *e1 = (const struct notify_entry *)p1;
-       const struct notify_entry *e2 = (const struct notify_entry *)p2;
        return strcmp(e1->path, e2->path);
 }
 
@@ -232,7 +279,7 @@ static NTSTATUS notify_save(struct notify_context *notify, struct db_record *rec
        tmp_ctx = talloc_new(notify);
        NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
 
-       ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL, notify->array,
+       ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, notify->array,
                                      (ndr_push_flags_fn_t)ndr_push_notify_array);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                talloc_free(tmp_ctx);
@@ -270,7 +317,7 @@ static void notify_handler(struct messaging_context *msg_ctx, void *private_data
                return;
        }
 
-       ndr_err = ndr_pull_struct_blob(data, tmp_ctx, NULL, &ev,
+       ndr_err = ndr_pull_struct_blob(data, tmp_ctx, &ev,
                                       (ndr_pull_flags_fn_t)ndr_pull_notify_event);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                talloc_free(tmp_ctx);
@@ -339,9 +386,7 @@ static NTSTATUS notify_add_array(struct notify_context *notify, struct db_record
        d->max_mask |= e->filter;
        d->max_mask_subdir |= e->subdir_filter;
 
-       if (d->num_entries > 1) {
-               qsort(d->entries, d->num_entries, sizeof(d->entries[0]), notify_compare);
-       }
+       TYPESAFE_QSORT(d->entries, d->num_entries, notify_compare);
 
        /* recalculate the maximum masks */
        d->max_mask = 0;
@@ -388,8 +433,7 @@ static void notify_add_onelevel(struct notify_context *notify,
        blob.length = rec->value.dsize;
 
        if (blob.length > 0) {
-               ndr_err = ndr_pull_struct_blob(
-                       &blob, array, NULL, array,
+               ndr_err = ndr_pull_struct_blob(&blob, array, array,
                        (ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",
@@ -415,8 +459,7 @@ static void notify_add_onelevel(struct notify_context *notify,
        array->entries[array->num_entries].server = notify->server;
        array->num_entries += 1;
 
-       ndr_err = ndr_push_struct_blob(
-               &blob, rec, NULL, array,
+       ndr_err = ndr_push_struct_blob(&blob, rec, array,
                (ndr_push_flags_fn_t)ndr_push_notify_entry_array);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                DEBUG(10, ("ndr_push_notify_entry_array failed: %s\n",
@@ -488,7 +531,7 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0,
 
        depth = count_chars(e.path, '/');
 
-       listel = TALLOC_ZERO_P(notify, struct notify_list);
+       listel = talloc_zero(notify, struct notify_list);
        if (listel == NULL) {
                status = NT_STATUS_NO_MEMORY;
                goto done;
@@ -545,14 +588,18 @@ NTSTATUS notify_remove_onelevel(struct notify_context *notify,
        NTSTATUS status;
        int i;
 
+       if (notify == NULL) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
        array = talloc_zero(talloc_tos(), struct notify_entry_array);
        if (array == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
 
        rec = notify->db_onelevel->fetch_locked(
-               notify->db_onelevel, talloc_tos(),
-               make_tdb_data((uint8_t *)fid, sizeof(*fid)));
+               notify->db_onelevel, array,
+               make_tdb_data((const uint8_t *)fid, sizeof(*fid)));
        if (rec == NULL) {
                DEBUG(10, ("notify_remove_onelevel: fetch_locked for %s failed"
                           "\n", file_id_string_tos(fid)));
@@ -564,8 +611,7 @@ NTSTATUS notify_remove_onelevel(struct notify_context *notify,
        blob.length = rec->value.dsize;
 
        if (blob.length > 0) {
-               ndr_err = ndr_pull_struct_blob(
-                       &blob, array, NULL, array,
+               ndr_err = ndr_pull_struct_blob(&blob, array, array,
                        (ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",
@@ -601,8 +647,7 @@ NTSTATUS notify_remove_onelevel(struct notify_context *notify,
                return NT_STATUS_OK;
        }
 
-       ndr_err = ndr_push_struct_blob(
-               &blob, rec, NULL, array,
+       ndr_err = ndr_push_struct_blob(&blob, rec, array,
                (ndr_push_flags_fn_t)ndr_push_notify_entry_array);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                DEBUG(10, ("ndr_push_notify_entry_array failed: %s\n",
@@ -764,7 +809,7 @@ static NTSTATUS notify_send(struct notify_context *notify, struct notify_entry *
 
        tmp_ctx = talloc_new(notify);
 
-       ndr_err = ndr_push_struct_blob(&data, tmp_ctx, NULL, &ev,
+       ndr_err = ndr_push_struct_blob(&data, tmp_ctx, &ev,
                                       (ndr_push_flags_fn_t)ndr_push_notify_event);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                talloc_free(tmp_ctx);
@@ -808,8 +853,7 @@ void notify_onelevel(struct notify_context *notify, uint32_t action,
 
        if (blob.length > 0) {
                enum ndr_err_code ndr_err;
-               ndr_err = ndr_pull_struct_blob(
-                       &blob, array, NULL, array,
+               ndr_err = ndr_pull_struct_blob(&blob, array, array,
                        (ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
                if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                        DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",