summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2017-05-18 13:59:20 +0200
committerVolker Lendecke <vl@samba.org>2017-06-15 13:19:14 +0200
commit4d404f23c9dff8bafd408b2d9566e179afef74bc (patch)
treea39db04524b2bb85bf46096802d60d9ea000f23d /source3/lib
parent4422124e096a80da3d585d831fee136149c36b0d (diff)
downloadsamba-4d404f23c9dff8bafd408b2d9566e179afef74bc.tar.gz
g_lock: Reformat to allow userdata
The next patches will make g_locks carry data. This prepares the on-disk format. Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/g_lock.c129
1 files changed, 98 insertions, 31 deletions
diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
index 542abe4f24f..ef950d60249 100644
--- a/source3/lib/g_lock.c
+++ b/source3/lib/g_lock.c
@@ -63,7 +63,8 @@ static void g_lock_rec_get(struct g_lock_rec *rec,
static ssize_t g_lock_put(uint8_t *buf, size_t buflen,
const struct g_lock_rec *locks,
- size_t num_locks)
+ size_t num_locks,
+ const uint8_t *data, size_t datalen)
{
size_t i, len, ofs;
@@ -73,46 +74,106 @@ static ssize_t g_lock_put(uint8_t *buf, size_t buflen,
len = num_locks * G_LOCK_REC_LENGTH;
+ len += sizeof(uint32_t);
+ if (len < sizeof(uint32_t)) {
+ return -1;
+ }
+
+ len += datalen;
+ if (len < datalen) {
+ return -1;
+ }
+
if (len > buflen) {
return len;
}
ofs = 0;
+ SIVAL(buf, ofs, num_locks);
+ ofs += sizeof(uint32_t);
for (i=0; i<num_locks; i++) {
g_lock_rec_put(buf+ofs, locks[i]);
ofs += G_LOCK_REC_LENGTH;
}
+ if ((data != NULL) && (datalen != 0)) {
+ memcpy(buf+ofs, data, datalen);
+ }
+
return len;
}
-static bool g_lock_get(TALLOC_CTX *mem_ctx, TDB_DATA data,
- unsigned *pnum_locks, struct g_lock_rec **plocks)
+static ssize_t g_lock_get(TDB_DATA recval,
+ struct g_lock_rec *locks, size_t num_locks,
+ uint8_t **data, size_t *datalen)
{
- size_t i, num_locks;
- struct g_lock_rec *locks;
+ size_t found_locks;
- if ((data.dsize % G_LOCK_REC_LENGTH) != 0) {
- DEBUG(1, ("invalid lock record length %zu\n", data.dsize));
- return false;
+ if (recval.dsize < sizeof(uint32_t)) {
+ /* Fresh or invalid record */
+ found_locks = 0;
+ goto done;
}
- num_locks = data.dsize / G_LOCK_REC_LENGTH;
- locks = talloc_array(mem_ctx, struct g_lock_rec, num_locks);
- if (locks == NULL) {
- DEBUG(1, ("talloc_memdup failed\n"));
- return false;
+ found_locks = IVAL(recval.dptr, 0);
+ recval.dptr += sizeof(uint32_t);
+ recval.dsize -= sizeof(uint32_t);
+
+ if (found_locks > recval.dsize/G_LOCK_REC_LENGTH) {
+ /* Invalid record */
+ return 0;
}
- for (i=0; i<num_locks; i++) {
- g_lock_rec_get(&locks[i], data.dptr);
- data.dptr += G_LOCK_REC_LENGTH;
+ if (found_locks <= num_locks) {
+ size_t i;
+
+ for (i=0; i<found_locks; i++) {
+ g_lock_rec_get(&locks[i], recval.dptr);
+ recval.dptr += G_LOCK_REC_LENGTH;
+ recval.dsize -= G_LOCK_REC_LENGTH;
+ }
+ } else {
+ /*
+ * Not enough space passed in by the caller, don't
+ * parse the locks.
+ */
+ recval.dptr += found_locks * G_LOCK_REC_LENGTH;
+ recval.dsize -= found_locks * G_LOCK_REC_LENGTH;
}
+done:
+ if (data != NULL) {
+ *data = recval.dptr;
+ }
+ if (datalen != NULL) {
+ *datalen = recval.dsize;
+ }
+ return found_locks;
+}
+
+static NTSTATUS g_lock_get_talloc(TALLOC_CTX *mem_ctx, TDB_DATA recval,
+ struct g_lock_rec **plocks,
+ size_t *pnum_locks,
+ uint8_t **data, size_t *datalen)
+{
+ struct g_lock_rec *locks;
+ ssize_t num_locks;
+
+ num_locks = g_lock_get(recval, NULL, 0, NULL, NULL);
+ if (num_locks == -1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ locks = talloc_array(mem_ctx, struct g_lock_rec, num_locks);
+ if (locks == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ g_lock_get(recval, locks, num_locks, data, datalen);
+
*plocks = locks;
*pnum_locks = num_locks;
- return true;
+
+ return NT_STATUS_OK;
}
struct g_lock_ctx *g_lock_ctx_init(TALLOC_CTX *mem_ctx,
@@ -175,7 +236,7 @@ static NTSTATUS g_lock_record_store(struct db_record *rec,
uint8_t *buf;
NTSTATUS status;
- len = g_lock_put(NULL, 0, locks, num_locks);
+ len = g_lock_put(NULL, 0, locks, num_locks, NULL, 0);
if (len == -1) {
return NT_STATUS_BUFFER_TOO_SMALL;
}
@@ -185,7 +246,7 @@ static NTSTATUS g_lock_record_store(struct db_record *rec,
return NT_STATUS_NO_MEMORY;
}
- g_lock_put(buf, len, locks, num_locks);
+ g_lock_put(buf, len, locks, num_locks, NULL, 0);
status = dbwrap_record_store(
rec, (TDB_DATA) { .dptr = buf, .dsize = len }, 0);
@@ -200,15 +261,17 @@ static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self,
struct server_id *blocker)
{
TDB_DATA data;
- unsigned i, num_locks;
+ size_t i, num_locks;
struct g_lock_rec *locks, *tmp;
NTSTATUS status;
bool modified = false;
data = dbwrap_record_get_value(rec);
- if (!g_lock_get(talloc_tos(), data, &num_locks, &locks)) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ status = g_lock_get_talloc(talloc_tos(), data, &locks, &num_locks,
+ NULL, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
for (i=0; i<num_locks; i++) {
@@ -432,7 +495,7 @@ NTSTATUS g_lock_unlock(struct g_lock_ctx *ctx, const char *name)
struct server_id self = messaging_server_id(ctx->msg);
struct db_record *rec = NULL;
struct g_lock_rec *locks = NULL;
- unsigned i, num_locks;
+ size_t i, num_locks;
NTSTATUS status;
TDB_DATA value;
@@ -446,8 +509,11 @@ NTSTATUS g_lock_unlock(struct g_lock_ctx *ctx, const char *name)
value = dbwrap_record_get_value(rec);
- if (!g_lock_get(talloc_tos(), value, &num_locks, &locks)) {
- DEBUG(10, ("g_lock_get for %s failed\n", name));
+ status = g_lock_get_talloc(talloc_tos(), value, &locks, &num_locks,
+ NULL, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("g_lock_get for %s failed: %s\n", name,
+ nt_errstr(status));
status = NT_STATUS_FILE_INVALID;
goto done;
}
@@ -457,7 +523,7 @@ NTSTATUS g_lock_unlock(struct g_lock_ctx *ctx, const char *name)
}
}
if (i == num_locks) {
- DBG_DEBUG("Lock not found, num_locks=%u\n", num_locks);
+ DBG_DEBUG("Lock not found, num_locks=%zu\n", num_locks);
status = NT_STATUS_NOT_FOUND;
goto done;
}
@@ -525,9 +591,8 @@ NTSTATUS g_lock_dump(struct g_lock_ctx *ctx, const char *name,
void *private_data)
{
TDB_DATA data;
- unsigned i, num_locks;
+ size_t i, num_locks;
struct g_lock_rec *locks = NULL;
- bool ret;
NTSTATUS status;
status = dbwrap_fetch_bystring(ctx->db, talloc_tos(), name, &data);
@@ -539,12 +604,14 @@ NTSTATUS g_lock_dump(struct g_lock_ctx *ctx, const char *name,
return NT_STATUS_OK;
}
- ret = g_lock_get(talloc_tos(), data, &num_locks, &locks);
+ status = g_lock_get_talloc(talloc_tos(), data, &locks, &num_locks,
+ NULL, NULL);
TALLOC_FREE(data.dptr);
- if (!ret) {
- DEBUG(10, ("g_lock_get for %s failed\n", name));
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("g_lock_get for %s failed: %s\n", name,
+ nt_errstr(status));
return NT_STATUS_INTERNAL_ERROR;
}