/* the locking database handle */
static TDB_CONTEXT *tdb;
-struct locking_data {
- union {
- struct {
- int num_share_mode_entries;
- BOOL delete_on_close;
- } s;
- struct share_mode_entry dummy; /* Needed for alignment. */
- } u;
- /* the following two entries are implicit
- struct share_mode_entry modes[num_share_mode_entries];
- char file_name[];
- */
-};
-
/****************************************************************************
Debugging aid :-).
****************************************************************************/
{
static pstring share_str;
- slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: "
+ slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: %s "
"pid = %s, share_access = 0x%x, private_options = 0x%x, "
"access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, "
"dev = 0x%x, inode = %.0f",
- num, procid_str_static(&e->pid),
+ num,
+ e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "",
+ procid_str_static(&e->pid),
e->share_access, e->private_options,
e->access_mask, e->op_mid, e->op_type, e->share_file_id,
(unsigned int)e->dev, (double)e->inode );
int i;
for (i = 0; i < num_share_modes; i++) {
- struct share_mode_entry *entry_p = &shares[i];
+ struct share_mode_entry entry;
+
+ memcpy(&entry, &shares[i], sizeof(struct share_mode_entry));
DEBUG(10,("print_share_mode_table: %s\n",
- share_mode_str(i, entry_p)));
+ share_mode_str(i, &entry)));
}
}
int i;
if (dbuf.dsize < sizeof(struct locking_data)) {
- DEBUG(0, ("parse_share_modes: buffer too short\n"));
- return False;
+ smb_panic("PANIC: parse_share_modes: buffer too short.\n");
}
data = (struct locking_data *)dbuf.dptr;
lck->delete_on_close = data->u.s.delete_on_close;
+ lck->initial_delete_on_close = data->u.s.initial_delete_on_close;
lck->num_share_modes = data->u.s.num_share_mode_entries;
DEBUG(10, ("parse_share_modes: delete_on_close: %d, "
- "num_share_modes: %d\n", lck->delete_on_close,
- lck->num_share_modes));
+ "initial_delete_on_close: %d, "
+ "num_share_modes: %d\n",
+ lck->delete_on_close,
+ lck->initial_delete_on_close,
+ lck->num_share_modes));
if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) {
DEBUG(0, ("invalid number of share modes: %d\n",
lck->num_share_modes));
- return False;
+ smb_panic("PANIC: invalid number of share modes");
}
lck->share_modes = NULL;
-
+
if (lck->num_share_modes != 0) {
if (dbuf.dsize < (sizeof(struct locking_data) +
(lck->num_share_modes *
sizeof(struct share_mode_entry)))) {
- DEBUG(0, ("parse_share_modes: buffer too short\n"));
- return False;
+ smb_panic("PANIC: parse_share_modes: buffer too short.\n");
}
lck->share_modes = talloc_memdup(lck, dbuf.dptr+sizeof(*data),
sizeof(struct share_mode_entry));
if (lck->share_modes == NULL) {
- DEBUG(0, ("talloc failed\n"));
- return False;
+ smb_panic("talloc failed\n");
}
}
+ /* Get any delete token. */
+ if (data->u.s.delete_token_size) {
+ char *p = dbuf.dptr + sizeof(*data) +
+ (lck->num_share_modes *
+ sizeof(struct share_mode_entry));
+
+ if ((data->u.s.delete_token_size < sizeof(uid_t) + sizeof(gid_t)) ||
+ ((data->u.s.delete_token_size - sizeof(uid_t)) % sizeof(gid_t)) != 0) {
+ DEBUG(0, ("parse_share_modes: invalid token size %d\n",
+ data->u.s.delete_token_size));
+ smb_panic("parse_share_modes: invalid token size\n");
+ }
+
+ lck->delete_token = TALLOC_P(lck, UNIX_USER_TOKEN);
+ if (!lck->delete_token) {
+ smb_panic("talloc failed\n");
+ }
+
+ /* Copy out the uid and gid. */
+ memcpy(&lck->delete_token->uid, p, sizeof(uid_t));
+ p += sizeof(uid_t);
+ memcpy(&lck->delete_token->gid, p, sizeof(gid_t));
+ p += sizeof(gid_t);
+
+ /* Any supplementary groups ? */
+ lck->delete_token->ngroups = (data->u.s.delete_token_size > (sizeof(uid_t) + sizeof(gid_t))) ?
+ ((data->u.s.delete_token_size -
+ (sizeof(uid_t) + sizeof(gid_t)))/sizeof(gid_t)) : 0;
+
+ if (lck->delete_token->ngroups) {
+ /* Make this a talloc child of lck->delete_token. */
+ lck->delete_token->groups = TALLOC_ARRAY(lck->delete_token, gid_t,
+ lck->delete_token->ngroups);
+ if (!lck->delete_token) {
+ smb_panic("talloc failed\n");
+ }
+
+ for (i = 0; i < lck->delete_token->ngroups; i++) {
+ memcpy(&lck->delete_token->groups[i], p, sizeof(gid_t));
+ p += sizeof(gid_t);
+ }
+ }
+
+ } else {
+ lck->delete_token = NULL;
+ }
+
/* Save off the associated service path and filename. */
lck->servicepath = talloc_strdup(lck, dbuf.dptr + sizeof(*data) +
- (lck->num_share_modes *
- sizeof(struct share_mode_entry)));
+ (lck->num_share_modes *
+ sizeof(struct share_mode_entry)) +
+ data->u.s.delete_token_size );
lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) +
- (lck->num_share_modes *
- sizeof(struct share_mode_entry)) +
- strlen(lck->servicepath) + 1 );
+ (lck->num_share_modes *
+ sizeof(struct share_mode_entry)) +
+ data->u.s.delete_token_size +
+ strlen(lck->servicepath) + 1 );
/*
* Ensure that each entry has a real process attached.
struct locking_data *data;
ssize_t offset;
ssize_t sp_len;
+ uint32 delete_token_size;
result.dptr = NULL;
result.dsize = 0;
}
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);
ZERO_STRUCTP(data);
data->u.s.num_share_mode_entries = lck->num_share_modes;
data->u.s.delete_on_close = lck->delete_on_close;
- DEBUG(10, ("unparse_share_modes: del: %d, num: %d\n",
- data->u.s.delete_on_close,
- data->u.s.num_share_mode_entries));
+ 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));
+
+ 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);
- print_share_mode_table(data);
+
+ if (DEBUGLEVEL >= 10) {
+ print_share_mode_table(data);
+ }
+
return result;
}
lck->ino = ino;
lck->num_share_modes = 0;
lck->share_modes = NULL;
+ lck->delete_token = NULL;
lck->delete_on_close = False;
+ lck->initial_delete_on_close = False;
lck->fresh = False;
lck->modified = False;
if (tdb_chainlock(tdb, key) != 0) {
DEBUG(3, ("Could not lock share entry\n"));
- talloc_free(lck);
+ TALLOC_FREE(lck);
return NULL;
}
if (lck->fresh) {
if (fname == NULL || servicepath == NULL) {
- DEBUG(0, ("New file, but no filename or servicepath supplied\n"));
- talloc_free(lck);
+ TALLOC_FREE(lck);
return NULL;
}
lck->filename = talloc_strdup(lck, fname);
lck->servicepath = talloc_strdup(lck, servicepath);
if (lck->filename == NULL || lck->servicepath == NULL) {
DEBUG(0, ("talloc failed\n"));
- talloc_free(lck);
+ TALLOC_FREE(lck);
return NULL;
}
} else {
if (!parse_share_modes(data, lck)) {
DEBUG(0, ("Could not parse share modes\n"));
- talloc_free(lck);
+ TALLOC_FREE(lck);
SAFE_FREE(data.dptr);
return NULL;
}
const char *servicepath,
const char *newname)
{
- struct file_renamed_message *frm = NULL;
size_t sp_len;
size_t fn_len;
size_t msg_len;
+ char *frm = NULL;
int i;
if (!lck) {
sp_len = strlen(lck->servicepath);
fn_len = strlen(lck->filename);
- msg_len = sizeof(*frm) + sp_len + 1 + fn_len + 1;
+ msg_len = MSG_FILE_RENAMED_MIN_SIZE + sp_len + 1 + fn_len + 1;
/* Set up the name changed message. */
frm = TALLOC(lck, msg_len);
if (!frm) {
return False;
}
- frm->dev = lck->dev;
- frm->inode = lck->ino;
+
+ SDEV_T_VAL(frm,0,lck->dev);
+ SINO_T_VAL(frm,8,lck->ino);
DEBUG(10,("rename_share_filename: msg_len = %d\n", msg_len ));
- safe_strcpy(&frm->names[0], lck->servicepath, sp_len);
- safe_strcpy(&frm->names[sp_len + 1], lck->filename, fn_len);
+ safe_strcpy(&frm[16], lck->servicepath, sp_len);
+ safe_strcpy(&frm[16 + sp_len + 1], lck->filename, fn_len);
/* Send the messages. */
for (i=0; i<lck->num_share_modes; i++) {
DEBUG(10,("rename_share_filename: sending rename message to pid %u "
"dev %x, inode %.0f sharepath %s newname %s\n",
(unsigned int)procid_to_pid(&se->pid),
- (unsigned int)frm->dev, (double)frm->inode,
+ (unsigned int)lck->dev, (double)lck->ino,
lck->servicepath, lck->filename ));
+ become_root();
message_send_pid(se->pid, MSG_SMB_FILE_RENAME,
frm, msg_len, True);
+ unbecome_root();
}
return True;
return False;
}
result = lck->delete_on_close;
- talloc_free(lck);
+ TALLOC_FREE(lck);
return result;
}
{
struct share_mode_entry entry, *e;
- fill_share_mode_entry(&entry, fsp, 0, 0);
+ fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK);
e = find_share_mode_entry(lck, &entry);
if (e == NULL) {
{
struct share_mode_entry entry, *e;
- fill_share_mode_entry(&entry, fsp, 0, 0);
+ fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK);
e = find_share_mode_entry(lck, &entry);
if (e == NULL) {
{
struct share_mode_entry entry, *e;
- fill_share_mode_entry(&entry, fsp, 0, 0);
+ fill_share_mode_entry(&entry, fsp, 0, NO_OPLOCK);
e = find_share_mode_entry(lck, &entry);
if (e == NULL) {
return True;
}
-
-/*******************************************************************
- We've just told all the smbd's that our level2 or fake level2 has been
- written to.
-********************************************************************/
-BOOL remove_all_share_oplocks(struct share_mode_lock *lck, files_struct *fsp)
-{
- int i;
- for (i=0; i<lck->num_share_modes; i++) {
- struct share_mode_entry *e = &lck->share_modes[i];
- if (!is_valid_share_mode_entry(e)) {
- continue;
- }
- if (e->op_type == NO_OPLOCK) {
- continue;
- }
- e->op_type = NO_OPLOCK;
- lck->modified = True;
- }
- return True;
-}
-
/****************************************************************************
Deal with the internal needs of setting the delete on close flag. Note that
as the tdb locking is recursive, it is safe to call this from within
return NT_STATUS_OK;
}
+/*************************************************************************
+ Return a talloced copy of a UNIX_USER_TOKEN. NULL on fail.
+ (Should this be in locking.c.... ?).
+*************************************************************************/
+
+static UNIX_USER_TOKEN *copy_unix_token(TALLOC_CTX *ctx, UNIX_USER_TOKEN *tok)
+{
+ UNIX_USER_TOKEN *cpy;
+
+ if (tok == NULL) {
+ return NULL;
+ }
+
+ cpy = TALLOC_P(ctx, UNIX_USER_TOKEN);
+ if (!cpy) {
+ return NULL;
+ }
+
+ cpy->uid = tok->uid;
+ cpy->gid = tok->gid;
+ cpy->ngroups = tok->ngroups;
+ if (tok->ngroups) {
+ /* Make this a talloc child of cpy. */
+ cpy->groups = TALLOC_ARRAY(cpy, gid_t, tok->ngroups);
+ if (!cpy->groups) {
+ return NULL;
+ }
+ memcpy(cpy->groups, tok->groups, tok->ngroups * sizeof(gid_t));
+ }
+ return cpy;
+}
+
+/****************************************************************************
+ Replace the delete on close token.
+****************************************************************************/
+
+void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok)
+{
+ /* Ensure there's no token. */
+ if (lck->delete_token) {
+ TALLOC_FREE(lck->delete_token); /* Also deletes groups... */
+ lck->delete_token = NULL;
+ }
+
+ /* Copy the new token (can be NULL). */
+ lck->delete_token = copy_unix_token(lck, tok);
+ lck->modified = True;
+}
+
/****************************************************************************
Sets the delete on close flag over all share modes on this file.
Modify the share mode entry for all files open
changed the delete on close flag. This will be noticed
in the close code, the last closer will delete the file
if flag is set.
+ Note that setting this to any value clears the initial_delete_on_close flag.
+ If delete_on_close is True this makes a copy of any UNIX_USER_TOKEN into the
+ lck entry.
****************************************************************************/
-BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close)
+BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close, UNIX_USER_TOKEN *tok)
{
struct share_mode_lock *lck;
if (lck == NULL) {
return False;
}
+
if (lck->delete_on_close != delete_on_close) {
+ set_delete_on_close_token(lck, tok);
lck->delete_on_close = delete_on_close;
+ if (delete_on_close) {
+ SMB_ASSERT(lck->delete_token != NULL);
+ }
lck->modified = True;
}
- talloc_free(lck);
+ if (lck->initial_delete_on_close) {
+ lck->initial_delete_on_close = False;
+ lck->modified = True;
+ }
+
+ TALLOC_FREE(lck);
return True;
}
data = (struct locking_data *)dbuf.dptr;
shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data));
sharepath = dbuf.dptr + sizeof(*data) +
- data->u.s.num_share_mode_entries*sizeof(*shares);
+ data->u.s.num_share_mode_entries*sizeof(*shares) +
+ data->u.s.delete_token_size;
fname = dbuf.dptr + sizeof(*data) +
data->u.s.num_share_mode_entries*sizeof(*shares) +
+ data->u.s.delete_token_size +
strlen(sharepath) + 1;
for (i=0;i<data->u.s.num_share_mode_entries;i++) {