LIBSMBSHAREMODES=bin/libsmbsharemodes.a @LIBSMBSHAREMODES_SHARED@
LIBSMBSHAREMODES_MAJOR=0
-LIBSMBSHAREMODES_MINOR=1
+LIBSMBSHAREMODES_MINOR=2
FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/tdb @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir) -D_SAMBA_BUILD_
FLAGS2 =
};
struct share_mode_lock {
+ const char *servicepath; /* canonicalized. */
const char *filename;
SMB_DEV_T dev;
SMB_INO_T ino;
* Create an entry in the Samba share mode db.
*/
-int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx,
+int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
uint64_t dev,
uint64_t ino,
const struct smb_share_mode_entry *new_entry,
- const char *filename) /* Must be abolute utf8 path. */
+ const char *sharepath, /* Must be absolute utf8 path. */
+ const char *filename) /* Must be relative utf8 path. */
{
TDB_DATA db_data;
TDB_DATA locking_key = get_locking_key(dev, ino);
db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
if (!db_data.dptr) {
/* We must create the entry. */
- db_data.dptr = malloc((2*sizeof(struct share_mode_entry)) + strlen(filename) + 1);
+ db_data.dptr = malloc((2*sizeof(struct share_mode_entry)) +
+ strlen(sharepath) + 1 +
+ strlen(filename) + 1);
if (!db_data.dptr) {
return -1;
}
ld->u.s.delete_on_close = 0;
shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry));
create_share_mode_entry(shares, new_entry);
+
memcpy(db_data.dptr + 2*sizeof(struct share_mode_entry),
+ sharepath,
+ strlen(sharepath) + 1);
+ memcpy(db_data.dptr + 2*sizeof(struct share_mode_entry) +
+ strlen(sharepath) + 1,
filename,
strlen(filename) + 1);
- db_data.dsize = 2*sizeof(struct share_mode_entry) + strlen(filename) + 1;
+ db_data.dsize = 2*sizeof(struct share_mode_entry) +
+ strlen(sharepath) + 1 +
+ strlen(filename) + 1;
if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_INSERT) == -1) {
free(db_data.dptr);
return -1;
return 0;
}
+/*
+ * Create an entry in the Samba share mode db. Original interface - doesn't
+ * Distinguish between share path and filename. Fudge this by using a
+ * sharepath of / and a relative filename of (filename+1).
+ */
+
+int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx,
+ uint64_t dev,
+ uint64_t ino,
+ const struct smb_share_mode_entry *new_entry,
+ const char *filename) /* Must be absolute utf8 path. */
+{
+ if (*filename != '/') {
+ abort();
+ }
+ return smb_create_share_mode_entry_ex(db_ctx, dev, ino, new_entry,
+ "/", &filename[1]);
+}
+
int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
uint64_t dev,
uint64_t ino,
}
}
- /* Save off the associated filename. */
+ /* 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->filename = 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)) +
+ strlen(lck->servicepath) + 1 );
/*
* Ensure that each entry has a real process attached.
int i;
struct locking_data *data;
ssize_t offset;
+ ssize_t sp_len;
result.dptr = NULL;
result.dsize = 0;
return result;
}
+ sp_len = strlen(lck->servicepath);
+
result.dsize = sizeof(*data) +
lck->num_share_modes * sizeof(struct share_mode_entry) +
+ sp_len + 1 +
strlen(lck->filename) + 1;
result.dptr = talloc_size(lck, result.dsize);
sizeof(struct share_mode_entry)*lck->num_share_modes);
offset = sizeof(*data) +
sizeof(struct share_mode_entry)*lck->num_share_modes;
+ 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);
}
struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
- SMB_DEV_T dev, SMB_INO_T ino,
- const char *fname)
+ SMB_DEV_T dev, SMB_INO_T ino,
+ const char *servicepath,
+ const char *fname)
{
struct share_mode_lock *lck;
TDB_DATA key = locking_key(dev, ino);
lck->fresh = (data.dptr == NULL);
if (lck->fresh) {
- if (fname == NULL) {
- DEBUG(0, ("New file, but no filename supplied\n"));
+
+ if (fname == NULL || servicepath == NULL) {
+ DEBUG(0, ("New file, but no filename or servicepath supplied\n"));
talloc_free(lck);
return NULL;
}
lck->filename = talloc_strdup(lck, fname);
- if (lck->filename == NULL) {
+ lck->servicepath = talloc_strdup(lck, servicepath);
+ if (lck->filename == NULL || lck->servicepath == NULL) {
DEBUG(0, ("talloc failed\n"));
talloc_free(lck);
return NULL;
return lck;
}
-BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode,
- const char *fname)
+/*******************************************************************
+ Sets the service name and filename for rename.
+ At this point we should emit "rename" smbd messages to all
+ interested process id's.
+********************************************************************/
+
+BOOL rename_share_filename(struct share_mode_lock *lck,
+ const char *servicepath,
+ const char *newname)
+{
+ /*
+ * rename_internal_fsp() and rename_internals() add './' to
+ * head of newname if newname does not contain a '/'.
+ */
+ while (newname[0] && newname[1] && newname[0] == '.' && newname[1] == '/') {
+ newname += 2;
+ }
+
+ lck->filename = talloc_strdup(lck, newname);
+ lck->servicepath = talloc_strdup(lck, servicepath);
+ if (lck->filename == NULL || lck->servicepath == NULL) {
+ DEBUG(0, ("rename_share_filename: talloc failed\n"));
+ return False;
+ }
+ lck->modified = True;
+ return True;
+}
+
+BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode)
{
BOOL result;
- struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode,
- fname);
+ struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, NULL, NULL);
+ if (!lck) {
+ return False;
+ }
result = lck->delete_on_close;
talloc_free(lck);
return result;
return True;
}
- lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
return False;
}
{
struct locking_data *data;
struct share_mode_entry *shares;
- char *name;
+ const char *sharepath;
+ const char *fname;
int i;
- void (*traverse_callback)(struct share_mode_entry *, char *) = state;
+ void (*traverse_callback)(struct share_mode_entry *, const char *, const char *) = state;
/* Ensure this is a locking_key record. */
if (kbuf.dsize != sizeof(struct locking_key))
data = (struct locking_data *)dbuf.dptr;
shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data));
- name = dbuf.dptr + sizeof(*data) +
+ sharepath = dbuf.dptr + sizeof(*data) +
data->u.s.num_share_mode_entries*sizeof(*shares);
+ fname = dbuf.dptr + sizeof(*data) +
+ data->u.s.num_share_mode_entries*sizeof(*shares) +
+ strlen(sharepath) + 1;
for (i=0;i<data->u.s.num_share_mode_entries;i++) {
- traverse_callback(&shares[i], name);
+ traverse_callback(&shares[i], sharepath, fname);
}
return 0;
}
share mode system.
********************************************************************/
-int share_mode_forall(void (*fn)(const struct share_mode_entry *, char *))
+int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *, const char *))
{
if (tdb == NULL)
return 0;
* This prevents race conditions with the file being created. JRA.
*/
- lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0, ("close_file: Could not get share mode lock for file %s\n", fsp->fsp_name));
* reference to a directory also.
*/
- lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
spurious oplock break. */
/* Now remove the deferred open entry under lock. */
- lck = get_share_mode_lock(NULL, state->dev, state->inode,
- fname);
+ lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0, ("could not get share mode lock\n"));
} else {
dev = psbuf->st_dev;
inode = psbuf->st_ino;
- lck = get_share_mode_lock(NULL, dev, inode, fname);
+ lck = get_share_mode_lock(NULL, dev, inode,
+ conn->connectpath,
+ fname);
if (lck == NULL) {
DEBUG(0, ("Could not get share mode lock\n"));
dev = fsp->dev;
inode = fsp->inode;
- lck = get_share_mode_lock(NULL, dev, inode, fname);
+ lck = get_share_mode_lock(NULL, dev, inode,
+ conn->connectpath,
+ fname);
if (lck == NULL) {
DEBUG(0, ("open_file_ntcreate: Could not get share mode lock for %s\n", fname));
fsp->is_stat = False;
string_set(&fsp->fsp_name,fname);
- lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fname);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode,
+ conn->connectpath,
+ fname);
if (lck == NULL) {
DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname));
struct share_mode_lock *lck;
/* Remove the oplock flag from the sharemode. */
- lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0,("remove_oplock: failed to lock share entry for "
"file %s\n", fsp->fsp_name ));
BOOL ret;
struct share_mode_lock *lck;
- lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0,("downgrade_oplock: failed to lock share entry for "
"file %s\n", fsp->fsp_name ));
if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
return;
- lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0,("release_level_2_oplocks_on_change: failed to lock "
"share mode entry for file %s.\n", fsp->fsp_name ));
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
- delete_pending =
- get_delete_on_close_flag(sbuf.st_dev,
- sbuf.st_ino,
- fname);
+ delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
} else {
/*
* Original code - this is an open file.
return(UNIXERROR(ERRDOS,ERRbadfid));
}
pos = fsp->fh->position_information;
- delete_pending =
- get_delete_on_close_flag(sbuf.st_dev,
- sbuf.st_ino,
- fname);
+ delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
access_mask = fsp->access_mask;
}
} else {
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
- delete_pending = get_delete_on_close_flag(sbuf.st_dev,
- sbuf.st_ino,
- fname);
+ delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
if (delete_pending) {
return ERROR_NT(NT_STATUS_DELETE_PENDING);
}
return True;
}
-static void print_share_mode(const struct share_mode_entry *e, char *fname)
+static void print_share_mode(const struct share_mode_entry *e, const char *sharepath, const char *fname)
{
static int count;
if (count==0) {
d_printf("Locked files:\n");
- d_printf("Pid DenyMode Access R/W Oplock Name\n");
- d_printf("--------------------------------------------------------------\n");
+ d_printf("Pid DenyMode Access R/W Oplock SharePath Name\n");
+ d_printf("----------------------------------------------------------------------------------\n");
}
count++;
d_printf("NONE ");
}
- d_printf(" %s %s",fname, asctime(localtime((time_t *)&e->time.tv_sec)));
+ d_printf(" %s %s %s",sharepath, fname, asctime(localtime((time_t *)&e->time.tv_sec)));
}
}
return buf;
}
-static void print_share_mode(const struct share_mode_entry *e, char *fname)
+static void print_share_mode(const struct share_mode_entry *e, const char *sharepath, const char *fname)
{
char *utf8_fname;
int deny_mode = map_share_mode_to_deny_mode(e->share_access,