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 int smb_share_mode_db_close(struct smbdb_ctx *db_ctx)
60 int ret = tdb_close(db_ctx->smb_tdb);
65 static TDB_DATA get_locking_key(uint64_t dev, uint64_t ino)
67 static struct locking_key lk;
70 memset(&lk, '\0', sizeof(struct locking_key));
71 lk.dev = (SMB_DEV_T)dev;
72 lk.inode = (SMB_INO_T)ino;
73 ld.dptr = (char *)&lk;
74 ld.dsize = sizeof(lk);
79 * lock/unlock entry in sharemode database.
82 int smb_lock_share_mode_entry(struct smbdb_ctx *db_ctx,
86 return tdb_chainlock(db_ctx->smb_tdb, get_locking_key(dev, ino));
89 int smb_unlock_share_mode_entry(struct smbdb_ctx *db_ctx,
93 return tdb_chainunlock(db_ctx->smb_tdb, get_locking_key(dev, ino));
96 /* Internal structure of Samba share mode db. */
97 /* FIXME ! This should be moved into a Samba include file. */
102 int num_share_mode_entries;
103 BOOL delete_on_close;
105 share_mode_entry dummy; /* Needed for alignment. */
107 /* the following two entries are implicit
108 share_mode_entry modes[num_share_mode_entries];
114 * Check if an external smb_share_mode_entry and an internal share_mode entry match.
117 static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, const share_mode_entry *entry)
119 return (e_entry->pid == entry->pid &&
120 e_entry->file_id == (uint32_t)entry->share_file_id &&
121 e_entry->open_time.tv_sec == entry->time.tv_sec &&
122 e_entry->open_time.tv_usec == entry->time.tv_usec &&
123 e_entry->share_access == (uint32_t)entry->share_access &&
124 e_entry->access_mask == (uint32_t)entry->access_mask &&
125 e_entry->dev == (uint64_t)entry->dev &&
126 e_entry->ino == (uint64_t)entry->inode);
130 * Create an internal Samba share_mode entry from an external smb_share_mode_entry.
133 static void create_share_mode_entry(share_mode_entry *out, const struct smb_share_mode_entry *in)
135 memset(out, '\0', sizeof(share_mode_entry));
138 out->share_file_id = (unsigned long)in->file_id;
139 out->time.tv_sec = in->open_time.tv_sec;
140 out->time.tv_usec = in->open_time.tv_usec;
141 out->share_access = in->share_access;
142 out->access_mask = in->access_mask;
143 out->dev = (SMB_DEV_T)in->dev;
144 out->inode = (SMB_INO_T)in->ino;
148 * Return the current share mode list for an open file.
149 * This uses similar (but simplified) logic to locking/locking.c
152 int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
155 struct smb_share_mode_entry **pp_list,
156 unsigned char *p_delete_on_close)
159 struct smb_share_mode_entry *list = NULL;
160 int num_share_modes = 0;
161 struct locking_data *ld = NULL; /* internal samba db state. */
162 share_mode_entry *shares = NULL;
167 *p_delete_on_close = 0;
169 db_data = tdb_fetch(db_ctx->smb_tdb, get_locking_key(dev, ino));
174 ld = (struct locking_data *)db_data.dptr;
175 num_share_modes = ld->u.s.num_share_mode_entries;
177 if (!num_share_modes) {
182 list = (struct smb_share_mode_entry *)malloc(sizeof(struct smb_share_mode_entry)*num_share_modes);
188 memset(list, '\0', num_share_modes * sizeof(struct smb_share_mode_entry));
190 shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry));
193 for (i = 0; i < num_share_modes; i++) {
194 share_mode_entry *share = &shares[i];
195 struct smb_share_mode_entry *sme = &list[list_num];
196 pid_t pid = share->pid;
198 /* Check this process really exists. */
199 if (kill(pid, 0) == -1 && (errno == ESRCH)) {
200 continue; /* No longer exists. */
203 /* Copy into the external list. */
204 sme->dev = (uint64_t)share->dev;
205 sme->ino = (uint64_t)share->inode;
206 sme->share_access = (uint32_t)share->share_access;
207 sme->access_mask = (uint32_t)share->access_mask;
208 sme->open_time.tv_sec = share->time.tv_sec;
209 sme->open_time.tv_usec = share->time.tv_usec;
210 sme->file_id = (uint32_t)share->share_file_id;
211 sme->pid = share->pid;
221 *p_delete_on_close = ld->u.s.delete_on_close;
228 * Create an entry in the Samba share mode db.
231 int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx,
234 const struct smb_share_mode_entry *new_entry,
235 const char *filename) /* Must be abolute utf8 path. */
238 TDB_DATA locking_key = get_locking_key(dev, ino);
239 int orig_num_share_modes = 0;
240 struct locking_data *ld = NULL; /* internal samba db state. */
241 share_mode_entry *shares = NULL;
242 char *new_data_p = NULL;
243 size_t new_data_size = 0;
245 db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
247 /* We must create the entry. */
248 db_data.dptr = malloc((2*sizeof(share_mode_entry)) + strlen(filename) + 1);
252 ld = (struct locking_data *)db_data.dptr;
253 ld->u.s.num_share_mode_entries = 1;
254 ld->u.s.delete_on_close = 0;
255 shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry));
256 create_share_mode_entry(shares, new_entry);
257 memcpy(db_data.dptr + 2*sizeof(share_mode_entry),
259 strlen(filename) + 1);
261 db_data.dsize = 2*sizeof(share_mode_entry) + strlen(filename) + 1;
262 if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_INSERT) == -1) {
270 /* Entry exists, we must add a new entry. */
271 new_data_p = malloc(db_data.dsize + sizeof(share_mode_entry));
277 ld = (struct locking_data *)db_data.dptr;
278 orig_num_share_modes = ld->u.s.num_share_mode_entries;
280 /* Copy the original data. */
281 memcpy(new_data_p, db_data.dptr, (orig_num_share_modes+1)*sizeof(share_mode_entry));
283 /* Add in the new share mode */
284 shares = (share_mode_entry *)(new_data_p +
285 ((orig_num_share_modes+1)*sizeof(share_mode_entry)));
287 create_share_mode_entry(shares, new_entry);
289 ld = (struct locking_data *)new_data_p;
290 ld->u.s.num_share_mode_entries++;
292 /* Append the original filename */
293 memcpy(new_data_p + ((ld->u.s.num_share_mode_entries+1)*sizeof(share_mode_entry)),
294 db_data.dptr + ((orig_num_share_modes+1)*sizeof(share_mode_entry)),
295 db_data.dsize - ((orig_num_share_modes+1) * sizeof(share_mode_entry)));
297 new_data_size = db_data.dsize + sizeof(share_mode_entry);
301 db_data.dptr = new_data_p;
302 db_data.dsize = new_data_size;
304 if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) == -1) {
312 int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
315 const struct smb_share_mode_entry *del_entry)
318 TDB_DATA locking_key = get_locking_key(dev, ino);
319 int orig_num_share_modes = 0;
320 struct locking_data *ld = NULL; /* internal samba db state. */
321 share_mode_entry *shares = NULL;
322 char *new_data_p = NULL;
323 size_t filename_size = 0;
324 size_t i, num_share_modes;
325 const char *fname_ptr = NULL;
327 db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
329 return -1; /* Error - missing entry ! */
332 ld = (struct locking_data *)db_data.dptr;
333 orig_num_share_modes = ld->u.s.num_share_mode_entries;
334 shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry));
336 if (orig_num_share_modes == 1) {
337 /* Only one entry - better be ours... */
338 if (!share_mode_entry_equal(del_entry, shares)) {
339 /* Error ! We can't delete someone else's entry ! */
343 /* It's ours - just remove the entire record. */
345 return tdb_delete(db_ctx->smb_tdb, locking_key);
348 /* More than one - allocate a new record minus the one we'll delete. */
349 new_data_p = malloc(db_data.dsize - sizeof(share_mode_entry));
355 /* Copy the header. */
356 memcpy(new_data_p, db_data.dptr, sizeof(share_mode_entry));
359 for (i = 0; i < orig_num_share_modes; i++) {
360 share_mode_entry *share = &shares[i];
361 pid_t pid = share->pid;
363 /* Check this process really exists. */
364 if (kill(pid, 0) == -1 && (errno == ESRCH)) {
365 continue; /* No longer exists. */
368 if (share_mode_entry_equal(del_entry, share)) {
369 continue; /* This is our delete taget. */
372 memcpy(new_data_p + ((num_share_modes+1)*sizeof(share_mode_entry)),
373 share, sizeof(share_mode_entry) );
378 if (num_share_modes == 0) {
379 /* None left after pruning. Delete record. */
382 return tdb_delete(db_ctx->smb_tdb, locking_key);
385 /* Copy the terminating filename. */
386 fname_ptr = db_data.dptr + ((orig_num_share_modes+1) * sizeof(share_mode_entry));
387 filename_size = db_data.dsize - (fname_ptr - db_data.dptr);
389 memcpy(new_data_p + ((num_share_modes+1)*sizeof(share_mode_entry)),
395 db_data.dptr = new_data_p;
397 /* Re-save smaller record. */
398 ld = (struct locking_data *)db_data.dptr;
399 ld->u.s.num_share_mode_entries = num_share_modes;
401 db_data.dsize = ((num_share_modes+1)*sizeof(share_mode_entry)) + filename_size;
403 if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) == -1) {
411 int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx,
414 const struct smb_share_mode_entry *set_entry,
415 const struct smb_share_mode_entry *new_entry)
418 TDB_DATA locking_key = get_locking_key(dev, ino);
419 int num_share_modes = 0;
420 struct locking_data *ld = NULL; /* internal samba db state. */
421 share_mode_entry *shares = NULL;
425 db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
427 return -1; /* Error - missing entry ! */
430 ld = (struct locking_data *)db_data.dptr;
431 num_share_modes = ld->u.s.num_share_mode_entries;
432 shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry));
434 for (i = 0; i < num_share_modes; i++) {
435 share_mode_entry *share = &shares[i];
436 pid_t pid = share->pid;
438 /* Check this process really exists. */
439 if (kill(pid, 0) == -1 && (errno == ESRCH)) {
440 continue; /* No longer exists. */
443 if (share_mode_entry_equal(set_entry, share)) {
444 create_share_mode_entry(share, new_entry);
455 /* Save modified data. */
456 if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) == -1) {