BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) { TDB_DATA dbuf; struct locking_data *data; char *p=NULL; int size; BOOL ret = True; /* read in the existing share modes if any */ dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); if (!dbuf.dptr) { size_t offset; /* we'll need to create a new record */ pstring fname; pstrcpy(fname, fsp->conn->connectpath); pstrcat(fname, "/"); pstrcat(fname, fsp->fsp_name); size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1; p = (char *)malloc(size); if (!p) return False; data = (struct locking_data *)p; data->u.num_share_mode_entries = 1; DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n", fsp->fsp_name )); offset = sizeof(*data) + sizeof(share_mode_entry); safe_strcpy(p + offset, fname, size - offset - 1); fill_share_mode(p + sizeof(*data), fsp, port, op_type); dbuf.dptr = p; dbuf.dsize = size; if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) ret = False; print_share_mode_table((struct locking_data *)p); SAFE_FREE(p); return ret; } /* we're adding to an existing entry - this is a bit fiddly */ data = (struct locking_data *)dbuf.dptr; data->u.num_share_mode_entries++; DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n", fsp->fsp_name, data->u.num_share_mode_entries )); size = dbuf.dsize + sizeof(share_mode_entry); p = malloc(size); if (!p) return False; memcpy(p, dbuf.dptr, sizeof(*data)); fill_share_mode(p + sizeof(*data), fsp, port, op_type); memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data), dbuf.dsize - sizeof(*data)); SAFE_FREE(dbuf.dptr); dbuf.dptr = p; dbuf.dsize = size; if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) ret = False; print_share_mode_table((struct locking_data *)p); SAFE_FREE(p); return ret; }
static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) { TDB_DATA result; int num_valid = 0; int i; struct locking_data *data; ssize_t offset; ssize_t sp_len; uint32 delete_token_size; result.dptr = NULL; result.dsize = 0; for (i=0; i<lck->num_share_modes; i++) { if (!is_unused_share_mode_entry(&lck->share_modes[i])) { num_valid += 1; } } if (num_valid == 0) { return result; } sp_len = strlen(lck->servicepath); delete_token_size = (lck->delete_token ? (sizeof(uid_t) + sizeof(gid_t) + (lck->delete_token->ngroups*sizeof(gid_t))) : 0); result.dsize = sizeof(*data) + lck->num_share_modes * sizeof(struct share_mode_entry) + delete_token_size + sp_len + 1 + strlen(lck->filename) + 1; result.dptr = talloc_size(lck, result.dsize); if (result.dptr == NULL) { smb_panic("talloc failed\n"); } data = (struct locking_data *)result.dptr; ZERO_STRUCTP(data); data->u.s.num_share_mode_entries = lck->num_share_modes; data->u.s.delete_on_close = lck->delete_on_close; data->u.s.initial_delete_on_close = lck->initial_delete_on_close; data->u.s.delete_token_size = delete_token_size; DEBUG(10, ("unparse_share_modes: del: %d, initial del %d, tok = %u, num: %d\n", data->u.s.delete_on_close, data->u.s.initial_delete_on_close, (unsigned int)data->u.s.delete_token_size, data->u.s.num_share_mode_entries)); memcpy(result.dptr + sizeof(*data), lck->share_modes, sizeof(struct share_mode_entry)*lck->num_share_modes); offset = sizeof(*data) + sizeof(struct share_mode_entry)*lck->num_share_modes; /* Store any delete on close token. */ if (lck->delete_token) { char *p = result.dptr + offset; memcpy(p, &lck->delete_token->uid, sizeof(uid_t)); p += sizeof(uid_t); memcpy(p, &lck->delete_token->gid, sizeof(gid_t)); p += sizeof(gid_t); for (i = 0; i < lck->delete_token->ngroups; i++) { memcpy(p, &lck->delete_token->groups[i], sizeof(gid_t)); p += sizeof(gid_t); } offset = p - result.dptr; } safe_strcpy(result.dptr + offset, lck->servicepath, result.dsize - offset - 1); offset += sp_len + 1; safe_strcpy(result.dptr + offset, lck->filename, result.dsize - offset - 1); if (DEBUGLEVEL >= 10) { print_share_mode_table(data); } return result; }
ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry, share_mode_entry **ppse) { TDB_DATA dbuf; struct locking_data *data; int i, del_count=0; share_mode_entry *shares; ssize_t count = 0; if (ppse) *ppse = NULL; /* read in the existing share modes */ dbuf = tdb_fetch(tdb, locking_key(dev, inode)); if (!dbuf.dptr) return -1; data = (struct locking_data *)dbuf.dptr; shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); /* * Find any with this pid and delete it * by overwriting with the rest of the data * from the record. */ DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.num_share_mode_entries )); for (i=0;i<data->u.num_share_mode_entries;) { if (share_modes_identical(&shares[i], entry)) { DEBUG(10,("del_share_entry: deleted %s\n", share_mode_str(i, &shares[i]) )); if (ppse) *ppse = memdup(&shares[i], sizeof(*shares)); data->u.num_share_mode_entries--; memmove(&shares[i], &shares[i+1], dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); del_count++; DEBUG(10,("del_share_entry: deleting entry %d\n", i )); } else { i++; } } if (del_count) { /* the record may have shrunk a bit */ dbuf.dsize -= del_count * sizeof(*shares); count = (ssize_t)data->u.num_share_mode_entries; /* 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; } } DEBUG(10,("del_share_entry: Remaining table.\n")); print_share_mode_table((struct locking_data *)dbuf.dptr); SAFE_FREE(dbuf.dptr); return count; }