diff options
author | Volker Lendecke <vl@samba.org> | 2017-05-17 05:52:56 +0200 |
---|---|---|
committer | Volker Lendecke <vl@samba.org> | 2017-06-15 13:19:13 +0200 |
commit | 49a80e5a0c1b6ec4ff5529587e068121e045dbc7 (patch) | |
tree | 396323ba79c92c88adc125f8f4f6d61055e295b7 /source3/lib | |
parent | 96771018509a9f61467e64a920b00775e31177c4 (diff) | |
download | samba-49a80e5a0c1b6ec4ff5529587e068121e045dbc7.tar.gz |
g_lock: Make it endian-neutral
Add explicit parsing
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.c | 98 |
1 files changed, 85 insertions, 13 deletions
diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c index 37cf70c5f12..f9eb5ef7e9f 100644 --- a/source3/lib/g_lock.c +++ b/source3/lib/g_lock.c @@ -45,6 +45,22 @@ struct g_lock_rec { struct server_id pid; }; +#define G_LOCK_REC_LENGTH (SERVER_ID_BUF_LENGTH+1) + +static void g_lock_rec_put(uint8_t buf[G_LOCK_REC_LENGTH], + const struct g_lock_rec rec) +{ + SCVAL(buf, 0, rec.lock_type); + server_id_put(buf+1, rec.pid); +} + +static void g_lock_rec_get(struct g_lock_rec *rec, + const uint8_t buf[G_LOCK_REC_LENGTH]) +{ + rec->lock_type = CVAL(buf, 0); + server_id_get(&rec->pid, buf+1); +} + struct g_lock_ctx *g_lock_ctx_init(TALLOC_CTX *mem_ctx, struct messaging_context *msg) { @@ -100,24 +116,85 @@ static bool g_lock_conflicts(enum g_lock_type l1, enum g_lock_type l2) static bool g_lock_parse(TALLOC_CTX *mem_ctx, TDB_DATA data, unsigned *pnum_locks, struct g_lock_rec **plocks) { - unsigned num_locks; + size_t i, num_locks; struct g_lock_rec *locks; - if ((data.dsize % sizeof(struct g_lock_rec)) != 0) { + if ((data.dsize % G_LOCK_REC_LENGTH) != 0) { DEBUG(1, ("invalid lock record length %zu\n", data.dsize)); return false; } - num_locks = data.dsize / sizeof(struct g_lock_rec); - locks = talloc_memdup(mem_ctx, data.dptr, data.dsize); + 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; } + + for (i=0; i<num_locks; i++) { + g_lock_rec_get(&locks[i], data.dptr); + data.dptr += G_LOCK_REC_LENGTH; + } + *plocks = locks; *pnum_locks = num_locks; return true; } +static ssize_t g_lock_unparse(uint8_t *buf, size_t buflen, + const struct g_lock_rec *locks, + size_t num_locks) +{ + size_t i, len, ofs; + + if (num_locks > UINT32_MAX/G_LOCK_REC_LENGTH) { + return -1; + } + + len = num_locks * G_LOCK_REC_LENGTH; + + if (len > buflen) { + return len; + } + + ofs = 0; + + for (i=0; i<num_locks; i++) { + g_lock_rec_put(buf+ofs, locks[i]); + ofs += G_LOCK_REC_LENGTH; + } + + return len; +} + +static NTSTATUS g_lock_record_store(struct db_record *rec, + const struct g_lock_rec *locks, + size_t num_locks) +{ + ssize_t len; + uint8_t *buf; + NTSTATUS status; + + len = g_lock_unparse(NULL, 0, locks, num_locks); + if (len == -1) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + buf = talloc_array(rec, uint8_t, len); + if (buf == NULL) { + return NT_STATUS_NO_MEMORY; + } + + g_lock_unparse(buf, len, locks, num_locks); + + status = dbwrap_record_store( + rec, (TDB_DATA) { .dptr = buf, .dsize = len }, 0); + + TALLOC_FREE(buf); + + return status; +} + static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self, enum g_lock_type type, struct server_id *blocker) @@ -182,12 +259,10 @@ static NTSTATUS g_lock_trylock(struct db_record *rec, struct server_id self, done: if (modified) { NTSTATUS store_status; - - data = make_tdb_data((uint8_t *)locks, num_locks * sizeof(*locks)); - store_status = dbwrap_record_store(rec, data, 0); + store_status = g_lock_record_store(rec, locks, num_locks); if (!NT_STATUS_IS_OK(store_status)) { - DEBUG(1, ("rec->store failed: %s\n", - nt_errstr(store_status))); + DBG_WARNING("g_lock_record_store failed: %s\n", + nt_errstr(store_status)); status = store_status; } } @@ -393,10 +468,7 @@ NTSTATUS g_lock_unlock(struct g_lock_ctx *ctx, const char *name) if (num_locks == 0) { status = dbwrap_record_delete(rec); } else { - TDB_DATA data; - data = make_tdb_data((uint8_t *)locks, - sizeof(struct g_lock_rec) * num_locks); - status = dbwrap_record_store(rec, data, 0); + status = g_lock_record_store(rec, locks, num_locks); } if (!NT_STATUS_IS_OK(status)) { DBG_WARNING("Could not store record: %s\n", nt_errstr(status)); |