2 Samba share mode database library external interface library.
3 Used by non-Samba products needing access to the Samba share mode db.
5 Copyright (C) Jeremy Allison 2005.
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "smb_share_modes.h"
25 /* Remove the paranoid malloc checker. */
31 * open/close sharemode database.
34 struct smbdb_ctx *smb_share_mode_db_open(const char *db_path)
36 struct smbdb_ctx *smb_db = (struct smbdb_ctx *)malloc(sizeof(struct smbdb_ctx));
42 memset(smb_db, '\0', sizeof(struct smbdb_ctx));
44 smb_db->smb_tdb = tdb_open(db_path,
45 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST,
49 if (!smb_db->smb_tdb) {
54 /* Should check that this is the correct version.... */
58 /* key and data records in the tdb locking database */
64 int smb_share_mode_db_close(struct smbdb_ctx *db_ctx)
66 int ret = tdb_close(db_ctx->smb_tdb);
71 static TDB_DATA get_locking_key(uint64_t dev, uint64_t ino)
73 static struct locking_key lk;
76 memset(&lk, '\0', sizeof(struct locking_key));
77 lk.dev = (SMB_DEV_T)dev;
78 lk.inode = (SMB_INO_T)ino;
79 ld.dptr = (char *)&lk;
80 ld.dsize = sizeof(lk);
85 * lock/unlock entry in sharemode database.
88 int smb_lock_share_mode_entry(struct smbdb_ctx *db_ctx,
92 return tdb_chainlock(db_ctx->smb_tdb, get_locking_key(dev, ino));
95 int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx,
99 return tdb_chainunlock(db_ctx->smb_tdb, get_locking_key(dev, ino));
102 /* Internal structure of Samba share mode db. */
103 /* FIXME ! This should be moved into a Samba include file. */
105 struct locking_data {
108 int num_share_mode_entries;
109 BOOL delete_on_close;
111 struct share_mode_entry dummy; /* Needed for alignment. */
113 /* the following two entries are implicit
114 struct share_mode_entry modes[num_share_mode_entries];
120 * Check if an external smb_share_mode_entry and an internal share_mode entry match.
123 static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, const struct share_mode_entry *entry)
125 return (procid_equal(&e_entry->pid, &entry->pid) &&
126 e_entry->file_id == (uint32_t)entry->share_file_id &&
127 e_entry->open_time.tv_sec == entry->time.tv_sec &&
128 e_entry->open_time.tv_usec == entry->time.tv_usec &&
129 e_entry->share_access == (uint32_t)entry->share_access &&
130 e_entry->access_mask == (uint32_t)entry->access_mask &&
131 e_entry->dev == (uint64_t)entry->dev &&
132 e_entry->ino == (uint64_t)entry->inode);
136 * Create an internal Samba share_mode entry from an external smb_share_mode_entry.
139 static void create_share_mode_entry(struct share_mode_entry *out, const struct smb_share_mode_entry *in)
141 memset(out, '\0', sizeof(struct share_mode_entry));
144 out->share_file_id = (unsigned long)in->file_id;
145 out->time.tv_sec = in->open_time.tv_sec;
146 out->time.tv_usec = in->open_time.tv_usec;
147 out->share_access = in->share_access;
148 out->access_mask = in->access_mask;
149 out->dev = (SMB_DEV_T)in->dev;
150 out->inode = (SMB_INO_T)in->ino;
154 * Return the current share mode list for an open file.
155 * This uses similar (but simplified) logic to locking/locking.c
158 int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
161 struct smb_share_mode_entry **pp_list,
162 unsigned char *p_delete_on_close)
165 struct smb_share_mode_entry *list = NULL;
166 int num_share_modes = 0;
167 struct locking_data *ld = NULL; /* internal samba db state. */
168 struct share_mode_entry *shares = NULL;
173 *p_delete_on_close = 0;
175 db_data = tdb_fetch(db_ctx->smb_tdb, get_locking_key(dev, ino));
180 ld = (struct locking_data *)db_data.dptr;
181 num_share_modes = ld->u.s.num_share_mode_entries;
183 if (!num_share_modes) {
188 list = (struct smb_share_mode_entry *)malloc(sizeof(struct smb_share_mode_entry)*num_share_modes);
194 memset(list, '\0', num_share_modes * sizeof(struct smb_share_mode_entry));
196 shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry));
199 for (i = 0; i < num_share_modes; i++) {
200 struct share_mode_entry *share = &shares[i];
201 struct smb_share_mode_entry *sme = &list[list_num];
202 struct process_id pid = share->pid;
204 /* Check this process really exists. */
205 if (kill(procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
206 continue; /* No longer exists. */
209 /* Ignore deferred open entries. */
210 if (share->op_type == DEFERRED_OPEN_ENTRY) {
214 /* Copy into the external list. */
215 sme->dev = (uint64_t)share->dev;
216 sme->ino = (uint64_t)share->inode;
217 sme->share_access = (uint32_t)share->share_access;
218 sme->access_mask = (uint32_t)share->access_mask;
219 sme->open_time.tv_sec = share->time.tv_sec;
220 sme->open_time.tv_usec = share->time.tv_usec;
221 sme->file_id = (uint32_t)share->share_file_id;
222 sme->pid = share->pid;
232 *p_delete_on_close = ld->u.s.delete_on_close;
239 * Create an entry in the Samba share mode db.
242 int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx,
245 const struct smb_share_mode_entry *new_entry,
246 const char *filename) /* Must be abolute utf8 path. */
249 TDB_DATA locking_key = get_locking_key(dev, ino);
250 int orig_num_share_modes = 0;
251 struct locking_data *ld = NULL; /* internal samba db state. */
252 struct share_mode_entry *shares = NULL;
253 char *new_data_p = NULL;
254 size_t new_data_size = 0;
256 db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
258 /* We must create the entry. */
259 db_data.dptr = malloc((2*sizeof(struct share_mode_entry)) + strlen(filename) + 1);
263 ld = (struct locking_data *)db_data.dptr;
264 ld->u.s.num_share_mode_entries = 1;
265 ld->u.s.delete_on_close = 0;
266 shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry));
267 create_share_mode_entry(shares, new_entry);
268 memcpy(db_data.dptr + 2*sizeof(struct share_mode_entry),
270 strlen(filename) + 1);
272 db_data.dsize = 2*sizeof(struct share_mode_entry) + strlen(filename) + 1;
273 if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_INSERT) == -1) {
281 /* Entry exists, we must add a new entry. */
282 new_data_p = malloc(db_data.dsize + sizeof(struct share_mode_entry));
288 ld = (struct locking_data *)db_data.dptr;
289 orig_num_share_modes = ld->u.s.num_share_mode_entries;
291 /* Copy the original data. */
292 memcpy(new_data_p, db_data.dptr, (orig_num_share_modes+1)*sizeof(struct share_mode_entry));
294 /* Add in the new share mode */
295 shares = (struct share_mode_entry *)(new_data_p +
296 ((orig_num_share_modes+1)*sizeof(struct share_mode_entry)));
298 create_share_mode_entry(shares, new_entry);
300 ld = (struct locking_data *)new_data_p;
301 ld->u.s.num_share_mode_entries++;
303 /* Append the original filename */
304 memcpy(new_data_p + ((ld->u.s.num_share_mode_entries+1)*sizeof(struct share_mode_entry)),
305 db_data.dptr + ((orig_num_share_modes+1)*sizeof(struct share_mode_entry)),
306 db_data.dsize - ((orig_num_share_modes+1) * sizeof(struct share_mode_entry)));
308 new_data_size = db_data.dsize + sizeof(struct share_mode_entry);
312 db_data.dptr = new_data_p;
313 db_data.dsize = new_data_size;
315 if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) == -1) {
323 int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
326 const struct smb_share_mode_entry *del_entry)
329 TDB_DATA locking_key = get_locking_key(dev, ino);
330 int orig_num_share_modes = 0;
331 struct locking_data *ld = NULL; /* internal samba db state. */
332 struct share_mode_entry *shares = NULL;
333 char *new_data_p = NULL;
334 size_t filename_size = 0;
335 size_t i, num_share_modes;
336 const char *fname_ptr = NULL;
338 db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
340 return -1; /* Error - missing entry ! */
343 ld = (struct locking_data *)db_data.dptr;
344 orig_num_share_modes = ld->u.s.num_share_mode_entries;
345 shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry));
347 if (orig_num_share_modes == 1) {
348 /* Only one entry - better be ours... */
349 if (!share_mode_entry_equal(del_entry, shares)) {
350 /* Error ! We can't delete someone else's entry ! */
354 /* It's ours - just remove the entire record. */
356 return tdb_delete(db_ctx->smb_tdb, locking_key);
359 /* More than one - allocate a new record minus the one we'll delete. */
360 new_data_p = malloc(db_data.dsize - sizeof(struct share_mode_entry));
366 /* Copy the header. */
367 memcpy(new_data_p, db_data.dptr, sizeof(struct share_mode_entry));
370 for (i = 0; i < orig_num_share_modes; i++) {
371 struct share_mode_entry *share = &shares[i];
372 struct process_id pid = share->pid;
374 /* Check this process really exists. */
375 if (kill(procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
376 continue; /* No longer exists. */
379 if (share_mode_entry_equal(del_entry, share)) {
380 continue; /* This is our delete taget. */
383 memcpy(new_data_p + ((num_share_modes+1)*sizeof(struct share_mode_entry)),
384 share, sizeof(struct share_mode_entry) );
389 if (num_share_modes == 0) {
390 /* None left after pruning. Delete record. */
393 return tdb_delete(db_ctx->smb_tdb, locking_key);
396 /* Copy the terminating filename. */
397 fname_ptr = db_data.dptr + ((orig_num_share_modes+1) * sizeof(struct share_mode_entry));
398 filename_size = db_data.dsize - (fname_ptr - db_data.dptr);
400 memcpy(new_data_p + ((num_share_modes+1)*sizeof(struct share_mode_entry)),
406 db_data.dptr = new_data_p;
408 /* Re-save smaller record. */
409 ld = (struct locking_data *)db_data.dptr;
410 ld->u.s.num_share_mode_entries = num_share_modes;
412 db_data.dsize = ((num_share_modes+1)*sizeof(struct share_mode_entry)) + filename_size;
414 if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) == -1) {
422 int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx,
425 const struct smb_share_mode_entry *set_entry,
426 const struct smb_share_mode_entry *new_entry)
429 TDB_DATA locking_key = get_locking_key(dev, ino);
430 int num_share_modes = 0;
431 struct locking_data *ld = NULL; /* internal samba db state. */
432 struct share_mode_entry *shares = NULL;
436 db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
438 return -1; /* Error - missing entry ! */
441 ld = (struct locking_data *)db_data.dptr;
442 num_share_modes = ld->u.s.num_share_mode_entries;
443 shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry));
445 for (i = 0; i < num_share_modes; i++) {
446 struct share_mode_entry *share = &shares[i];
447 struct process_id pid = share->pid;
449 /* Check this process really exists. */
450 if (kill(procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
451 continue; /* No longer exists. */
454 if (share_mode_entry_equal(set_entry, share)) {
455 create_share_mode_entry(share, new_entry);
466 /* Save modified data. */
467 if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) == -1) {