- /* store it back in the database */
- if (data->u.num_share_mode_entries == 0) {
- if (tdb_delete(tdb, locking_key(dev, inode)) == -1)
- count = -1;
- } else {
- if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1)
- count = -1;
+struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
+ SMB_DEV_T dev, SMB_INO_T ino,
+ const char *servicepath,
+ const char *fname)
+{
+ struct share_mode_lock *lck;
+ TDB_DATA key = locking_key(dev, ino);
+ TDB_DATA data;
+
+ lck = TALLOC_P(mem_ctx, struct share_mode_lock);
+ if (lck == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return NULL;
+ }
+
+ /* Ensure we set every field here as the destructor must be
+ valid even if parse_share_modes fails. */
+
+ lck->servicepath = NULL;
+ lck->filename = NULL;
+ lck->dev = dev;
+ lck->ino = ino;
+ lck->num_share_modes = 0;
+ lck->share_modes = NULL;
+ lck->delete_token = NULL;
+ lck->delete_on_close = False;
+ lck->initial_delete_on_close = False;
+ lck->fresh = False;
+ lck->modified = False;
+
+ if (tdb_chainlock(tdb, key) != 0) {
+ DEBUG(3, ("Could not lock share entry\n"));
+ TALLOC_FREE(lck);
+ return NULL;
+ }
+
+ /* We must set the destructor immediately after the chainlock
+ ensure the lock is cleaned up on any of the error return
+ paths below. */
+
+ talloc_set_destructor(lck, share_mode_lock_destructor);
+
+ data = tdb_fetch(tdb, key);
+ lck->fresh = (data.dptr == NULL);
+
+ if (lck->fresh) {
+
+ if (fname == NULL || servicepath == NULL) {
+ TALLOC_FREE(lck);
+ return NULL;
+ }
+ lck->filename = talloc_strdup(lck, fname);
+ lck->servicepath = talloc_strdup(lck, servicepath);
+ if (lck->filename == NULL || lck->servicepath == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(lck);
+ return NULL;
+ }
+ } else {
+ if (!parse_share_modes(data, lck)) {
+ DEBUG(0, ("Could not parse share modes\n"));
+ TALLOC_FREE(lck);
+ SAFE_FREE(data.dptr);
+ return NULL;