mirror of
https://github.com/samba-team/samba.git
synced 2025-02-15 05:57:49 +03:00
vfs_fruit: let fruit_open_meta() with O_CREAT return a fake-fd
This is the final step in implementing the needed macOS semantics on the FinderInfo stream: as long as the client hasn't written a non-zero FinderInfo blob to the stream, there mustn't be a visible filesystem entry for other openers. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org> Autobuild-User(master): Jeremy Allison <jra@samba.org> Autobuild-Date(master): Thu Nov 1 01:14:23 CET 2018 on sn-devel-144 (cherry picked from commit 1b2de44ea8114cf2025e8b8c843131e2f2dbed27)
This commit is contained in:
parent
cbbd530968
commit
0eebb6e0a4
@ -1,5 +1,2 @@
|
||||
^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\)
|
||||
^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\)
|
||||
^samba3.vfs.fruit metadata_netatalk.empty_stream\(nt4_dc\)
|
||||
^samba3.vfs.fruit metadata_stream.empty_stream\(nt4_dc\)
|
||||
^samba3.vfs.fruit streams_depot.empty_stream\(nt4_dc\)
|
||||
|
@ -3403,66 +3403,68 @@ static int fruit_connect(vfs_handle_struct *handle,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int fruit_fake_fd(void)
|
||||
{
|
||||
int pipe_fds[2];
|
||||
int fd;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Return a valid fd, but ensure any attempt to use it returns
|
||||
* an error (EPIPE). Once we get a write on the handle, we open
|
||||
* the real fd.
|
||||
*/
|
||||
ret = pipe(pipe_fds);
|
||||
if (ret != 0) {
|
||||
return -1;
|
||||
}
|
||||
fd = pipe_fds[0];
|
||||
close(pipe_fds[1]);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int fruit_open_meta_stream(vfs_handle_struct *handle,
|
||||
struct smb_filename *smb_fname,
|
||||
files_struct *fsp,
|
||||
int flags,
|
||||
mode_t mode)
|
||||
{
|
||||
AfpInfo *ai = NULL;
|
||||
char afpinfo_buf[AFP_INFO_SIZE];
|
||||
ssize_t len, written;
|
||||
int hostfd = -1;
|
||||
int rc = -1;
|
||||
struct fruit_config_data *config = NULL;
|
||||
struct fio *fio = NULL;
|
||||
int open_flags = flags & ~O_CREAT;
|
||||
int fd;
|
||||
|
||||
hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
|
||||
if (hostfd == -1) {
|
||||
DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname));
|
||||
|
||||
SMB_VFS_HANDLE_GET_DATA(handle, config,
|
||||
struct fruit_config_data, return -1);
|
||||
|
||||
fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL);
|
||||
fio->type = ADOUBLE_META;
|
||||
fio->config = config;
|
||||
|
||||
fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, open_flags, mode);
|
||||
if (fd != -1) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
if (!(flags & O_CREAT)) {
|
||||
VFS_REMOVE_FSP_EXTENSION(handle, fsp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(flags & (O_CREAT | O_TRUNC))) {
|
||||
return hostfd;
|
||||
fd = fruit_fake_fd();
|
||||
if (fd == -1) {
|
||||
VFS_REMOVE_FSP_EXTENSION(handle, fsp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ai = afpinfo_new(talloc_tos());
|
||||
if (ai == NULL) {
|
||||
rc = -1;
|
||||
goto fail;
|
||||
}
|
||||
fio->fake_fd = true;
|
||||
fio->flags = flags;
|
||||
fio->mode = mode;
|
||||
|
||||
len = afpinfo_pack(ai, afpinfo_buf);
|
||||
if (len != AFP_INFO_SIZE) {
|
||||
rc = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set fd, needed in SMB_VFS_NEXT_PWRITE() */
|
||||
fsp->fh->fd = hostfd;
|
||||
|
||||
written = SMB_VFS_NEXT_PWRITE(handle, fsp, afpinfo_buf,
|
||||
AFP_INFO_SIZE, 0);
|
||||
fsp->fh->fd = -1;
|
||||
if (written != AFP_INFO_SIZE) {
|
||||
DBG_ERR("bad write [%zd/%d]\n", written, AFP_INFO_SIZE);
|
||||
rc = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
fail:
|
||||
DBG_DEBUG("rc=%d, fd=%d\n", rc, hostfd);
|
||||
|
||||
if (rc != 0) {
|
||||
int saved_errno = errno;
|
||||
if (hostfd >= 0) {
|
||||
fsp->fh->fd = hostfd;
|
||||
SMB_VFS_NEXT_CLOSE(handle, fsp);
|
||||
}
|
||||
hostfd = -1;
|
||||
errno = saved_errno;
|
||||
}
|
||||
return hostfd;
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int fruit_open_meta_netatalk(vfs_handle_struct *handle,
|
||||
@ -3471,56 +3473,42 @@ static int fruit_open_meta_netatalk(vfs_handle_struct *handle,
|
||||
int flags,
|
||||
mode_t mode)
|
||||
{
|
||||
int rc;
|
||||
int fakefd = -1;
|
||||
struct fruit_config_data *config = NULL;
|
||||
struct fio *fio = NULL;
|
||||
struct adouble *ad = NULL;
|
||||
int fds[2];
|
||||
bool meta_exists = false;
|
||||
int fd;
|
||||
|
||||
DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname));
|
||||
|
||||
/*
|
||||
* Return a valid fd, but ensure any attempt to use it returns an error
|
||||
* (EPIPE). All operations on the smb_fname or the fsp will use path
|
||||
* based syscalls.
|
||||
*/
|
||||
rc = pipe(fds);
|
||||
if (rc != 0) {
|
||||
goto exit;
|
||||
}
|
||||
fakefd = fds[0];
|
||||
close(fds[1]);
|
||||
|
||||
if (flags & (O_CREAT | O_TRUNC)) {
|
||||
/*
|
||||
* The attribute does not exist or needs to be truncated,
|
||||
* create an AppleDouble EA
|
||||
*/
|
||||
ad = ad_init(fsp, handle, ADOUBLE_META);
|
||||
if (ad == NULL) {
|
||||
rc = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = ad_set(ad, fsp->fsp_name);
|
||||
if (rc != 0) {
|
||||
rc = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
TALLOC_FREE(ad);
|
||||
ad = ad_get(talloc_tos(), handle, smb_fname, ADOUBLE_META);
|
||||
if (ad != NULL) {
|
||||
meta_exists = true;
|
||||
}
|
||||
|
||||
exit:
|
||||
DEBUG(10, ("fruit_open meta rc=%d, fd=%d\n", rc, fakefd));
|
||||
if (rc != 0) {
|
||||
int saved_errno = errno;
|
||||
if (fakefd >= 0) {
|
||||
close(fakefd);
|
||||
}
|
||||
fakefd = -1;
|
||||
errno = saved_errno;
|
||||
TALLOC_FREE(ad);
|
||||
|
||||
if (!meta_exists && !(flags & O_CREAT)) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
return fakefd;
|
||||
|
||||
fd = fruit_fake_fd();
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SMB_VFS_HANDLE_GET_DATA(handle, config,
|
||||
struct fruit_config_data, return -1);
|
||||
|
||||
fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL);
|
||||
fio->type = ADOUBLE_META;
|
||||
fio->config = config;
|
||||
fio->fake_fd = true;
|
||||
fio->flags = flags;
|
||||
fio->mode = mode;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int fruit_open_meta(vfs_handle_struct *handle,
|
||||
@ -3529,7 +3517,6 @@ static int fruit_open_meta(vfs_handle_struct *handle,
|
||||
{
|
||||
int fd;
|
||||
struct fruit_config_data *config = NULL;
|
||||
struct fio *fio = NULL;
|
||||
|
||||
DBG_DEBUG("path [%s]\n", smb_fname_str_dbg(smb_fname));
|
||||
|
||||
@ -3554,14 +3541,6 @@ static int fruit_open_meta(vfs_handle_struct *handle,
|
||||
|
||||
DBG_DEBUG("path [%s] fd [%d]\n", smb_fname_str_dbg(smb_fname), fd);
|
||||
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL);
|
||||
fio->type = ADOUBLE_META;
|
||||
fio->config = config;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user