* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "includes.h"
+#include "smbd/smbd.h"
#include "onefs.h"
+#include "onefs_config.h"
+#include "oplock_onefs.h"
#include <ifs/ifs_syscalls.h>
#include <isi_acl/isi_acl_util.h>
+#include <sys/isi_acl.h>
/*
* Initialize the sm_lock struct before passing it to ifs_createfile.
enum oplock_type onefs_oplock;
enum oplock_type onefs_granted_oplock = OPLOCK_NONE;
struct ifs_security_descriptor ifs_sd = {}, *pifs_sd = NULL;
- int secinfo = 0;
+ uint32_t sec_info_effective = 0;
int ret_fd = -1;
uint32_t onefs_dos_attributes;
struct ifs_createfile_flags cf_flags = CF_FLAGS_NONE;
+ char *mapped_name = NULL;
+ NTSTATUS result;
+
+ START_PROFILE(syscall_createfile);
+
+ /* Translate the name to UNIX before calling ifs_createfile */
+ mapped_name = talloc_strdup(talloc_tos(), path);
+ if (mapped_name == NULL) {
+ errno = ENOMEM;
+ goto out;
+ }
+ result = SMB_VFS_TRANSLATE_NAME(conn, &mapped_name,
+ vfs_translate_to_unix);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto out;
+ }
/* Setup security descriptor and get secinfo. */
if (sd != NULL) {
NTSTATUS status;
+ uint32_t sec_info_sent = 0;
- secinfo = (get_sec_info(sd) & IFS_SEC_INFO_KNOWN_MASK);
+ sec_info_sent = (get_sec_info(sd) & IFS_SEC_INFO_KNOWN_MASK);
- status = onefs_samba_sd_to_sd(secinfo, sd, &ifs_sd, SNUM(conn));
+ status = onefs_samba_sd_to_sd(sec_info_sent, sd, &ifs_sd,
+ SNUM(conn), &sec_info_effective);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1, ("SD initialization failure: %s",
+ DEBUG(1, ("SD initialization failure: %s\n",
nt_errstr(status)));
errno = EINVAL;
goto out;
PARM_ALLOW_EXECUTE_ALWAYS_DEFAULT) &&
(open_access_mask & FILE_EXECUTE)) {
- DEBUG(3, ("Stripping execute bit from %s: (0x%x)\n", path,
+ DEBUG(3, ("Stripping execute bit from %s: (0x%x)\n", mapped_name,
open_access_mask));
/* Strip execute. */
open_access_mask));
}
- DEBUG(10,("onefs_sys_create_file: base_fd = %d, "
+ DEBUG(10,("onefs_sys_create_file: base_fd = %d, fname = %s "
"open_access_mask = 0x%x, flags = 0x%x, mode = 0%o, "
"desired_oplock = %s, id = 0x%x, secinfo = 0x%x, sd = %p, "
"dos_attributes = 0x%x, path = %s, "
- "default_acl=%s\n", base_fd,
+ "default_acl=%s\n", base_fd, mapped_name,
(unsigned int)open_access_mask,
(unsigned int)flags,
(unsigned int)mode,
onefs_oplock_str(onefs_oplock),
(unsigned int)id,
- (unsigned int)secinfo, sd,
- (unsigned int)onefs_dos_attributes, path,
+ sec_info_effective, sd,
+ (unsigned int)onefs_dos_attributes, mapped_name,
cf_flags_and_bool(cf_flags, CF_FLAGS_DEFAULT_ACL) ?
"true" : "false"));
/* Initialize smlock struct for files/dirs but not internal opens */
if (!(oplock_request & INTERNAL_OPEN_ONLY)) {
- smlock_init(conn, &sml, is_executable(path), access_mask,
+ smlock_init(conn, &sml, is_executable(mapped_name), access_mask,
share_access, create_options);
psml = &sml;
}
smlock_dump(10, psml);
- ret_fd = ifs_createfile(base_fd, path,
+ ret_fd = ifs_createfile(base_fd, mapped_name,
(enum ifs_ace_rights)open_access_mask, flags & ~O_ACCMODE, mode,
- onefs_oplock, id, psml, secinfo, pifs_sd, onefs_dos_attributes,
- cf_flags, &onefs_granted_oplock);
+ onefs_oplock, id, psml, sec_info_effective, pifs_sd,
+ onefs_dos_attributes, cf_flags, &onefs_granted_oplock);
DEBUG(10,("onefs_sys_create_file(%s): ret_fd = %d, "
"onefs_granted_oplock = %s\n",
}
out:
+ END_PROFILE(syscall_createfile);
aclu_free_sd(pifs_sd, false);
+ TALLOC_FREE(mapped_name);
return ret_fd;
}
/* Set up the header iovec. */
if (header) {
- hdtrl.iov_base = header->data;
+ hdtrl.iov_base = (void *)header->data;
hdtrl.iov_len = hdr_len = header->length;
} else {
hdtrl.iov_base = NULL;
do {
ret = sendfile(fromfd, tofd, offset, total, &hdr,
&nwritten, flags);
- } while (ret == -1 && errno == EINTR);
+#if defined(EWOULDBLOCK)
+ } while (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
+#else
+ } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+#endif
/* On error we're done. */
if (ret == -1) {
hdtrl.iov_len = 0;
} else {
hdtrl.iov_base =
- (caddr_t)hdtrl.iov_base + nwritten;
+ (void *)((caddr_t)hdtrl.iov_base + nwritten);
hdtrl.iov_len -= nwritten;
nwritten = 0;
}
bool atomic = false;
ssize_t ret = 0;
+ START_PROFILE_BYTES(syscall_sendfile, count);
+
if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
PARM_ATOMIC_SENDFILE,
PARM_ATOMIC_SENDFILE_DEFAULT)) {
/* If the sendfile wasn't atomic, we're done. */
if (!atomic) {
- DEBUG(10, ("non-atomic sendfile read %ul bytes", ret));
+ DEBUG(10, ("non-atomic sendfile read %ul bytes\n", ret));
+ END_PROFILE(syscall_sendfile);
return ret;
}
/* Handle case 1: short read -> truncated file. */
if (ret == 0) {
+ END_PROFILE(syscall_sendfile);
return ret;
}
PARM_SENDFILE_LARGE_READS_DEFAULT)) {
DEBUG(3, ("Not attempting non-atomic large sendfile: "
"%lu bytes\n", count));
+ END_PROFILE(syscall_sendfile);
return 0;
}
if (count < 0x10000) {
- DEBUG(0, ("Count < 2^16 and E2BIG was returned! %lu",
+ DEBUG(0, ("Count < 2^16 and E2BIG was returned! %lu\n",
count));
}
DEBUG(1, ("error on non-atomic large sendfile "
"(%lu bytes): %s\n", count,
strerror(errno)));
+ END_PROFILE(syscall_sendfile);
return ret;
}
if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
PARM_SENDFILE_SAFE,
PARM_SENDFILE_SAFE_DEFAULT)) {
+ END_PROFILE(syscall_sendfile);
return -1;
}
+ END_PROFILE(syscall_sendfile);
return ret;
}
count, strerror(errno)));
}
+ END_PROFILE(syscall_sendfile);
return ret;
}
off_t rbytes;
off_t wbytes;
+ START_PROFILE_BYTES(syscall_recvfile, count);
+
DEBUG(10,("onefs_recvfile: from = %d, to = %d, offset=%llu, count = "
"%lu\n", fromfd, tofd, offset, count));
if (count == 0) {
+ END_PROFILE(syscall_recvfile);
return 0;
}
/* Log if recvfile didn't write everything it read. */
if (total_rbytes != total_wbytes) {
- DEBUG(0, ("partial recvfile: total_rbytes=%llu but "
+ DEBUG(3, ("partial recvfile: total_rbytes=%llu but "
"total_wbytes=%llu, diff = %llu\n", total_rbytes,
total_wbytes, total_rbytes - total_wbytes));
SMB_ASSERT(total_rbytes > total_wbytes);
*/
while (total_rbytes < count) {
- DEBUG(0, ("shallow recvfile, reading %llu\n",
- count - total_rbytes));
+ DEBUG(3, ("shallow recvfile (%s), reading %llu\n",
+ strerror(errno), count - total_rbytes));
/*
* Read the remaining data into the spill buffer. recvfile
spill_buffer + (total_rbytes - total_wbytes),
count - total_rbytes);
- if (ret == -1) {
- DEBUG(0, ("shallow recvfile read failed: %s\n",
- strerror(errno)));
+ if (ret <= 0) {
+ if (ret == 0) {
+ DEBUG(0, ("shallow recvfile read: EOF\n"));
+ } else {
+ DEBUG(0, ("shallow recvfile read failed: %s\n",
+ strerror(errno)));
+ }
/* Socket is dead, so treat as if it were drained. */
socket_drained = true;
goto out;
*/
while (total_wbytes < count) {
- DEBUG(0, ("partial recvfile, writing %llu\n", count - total_wbytes));
+ DEBUG(3, ("partial recvfile, writing %llu\n", count - total_wbytes));
ret = sys_pwrite(tofd, spill_buffer, count - total_wbytes,
offset + total_wbytes);
ret = total_wbytes;
out:
+
+ END_PROFILE(syscall_recvfile);
+
/* Make sure we always try to drain the socket. */
if (!socket_drained && count - total_rbytes) {
int saved_errno = errno;
return ret;
}
+
+void init_stat_ex_from_onefs_stat(struct stat_ex *dst, const struct stat *src)
+{
+ ZERO_STRUCT(*dst);
+
+ dst->st_ex_dev = src->st_dev;
+ dst->st_ex_ino = src->st_ino;
+ dst->st_ex_mode = src->st_mode;
+ dst->st_ex_nlink = src->st_nlink;
+ dst->st_ex_uid = src->st_uid;
+ dst->st_ex_gid = src->st_gid;
+ dst->st_ex_rdev = src->st_rdev;
+ dst->st_ex_size = src->st_size;
+ dst->st_ex_atime = src->st_atimespec;
+ dst->st_ex_mtime = src->st_mtimespec;
+ dst->st_ex_ctime = src->st_ctimespec;
+ dst->st_ex_btime = src->st_birthtimespec;
+ dst->st_ex_blksize = src->st_blksize;
+ dst->st_ex_blocks = src->st_blocks;
+
+ dst->st_ex_flags = src->st_flags;
+
+ dst->vfs_private = src->st_snapid;
+}
+
+int onefs_sys_stat(const char *fname, SMB_STRUCT_STAT *sbuf)
+{
+ int ret;
+ struct stat onefs_sbuf;
+
+ ret = stat(fname, &onefs_sbuf);
+
+ if (ret == 0) {
+ /* we always want directories to appear zero size */
+ if (S_ISDIR(onefs_sbuf.st_mode)) {
+ onefs_sbuf.st_size = 0;
+ }
+ init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf);
+ }
+ return ret;
+}
+
+int onefs_sys_fstat(int fd, SMB_STRUCT_STAT *sbuf)
+{
+ int ret;
+ struct stat onefs_sbuf;
+
+ ret = fstat(fd, &onefs_sbuf);
+
+ if (ret == 0) {
+ /* we always want directories to appear zero size */
+ if (S_ISDIR(onefs_sbuf.st_mode)) {
+ onefs_sbuf.st_size = 0;
+ }
+ init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf);
+ }
+ return ret;
+}
+
+int onefs_sys_fstat_at(int base_fd, const char *fname, SMB_STRUCT_STAT *sbuf,
+ int flags)
+{
+ int ret;
+ struct stat onefs_sbuf;
+
+ ret = enc_fstatat(base_fd, fname, ENC_DEFAULT, &onefs_sbuf, flags);
+
+ if (ret == 0) {
+ /* we always want directories to appear zero size */
+ if (S_ISDIR(onefs_sbuf.st_mode)) {
+ onefs_sbuf.st_size = 0;
+ }
+ init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf);
+ }
+ return ret;
+}
+
+int onefs_sys_lstat(const char *fname, SMB_STRUCT_STAT *sbuf)
+{
+ int ret;
+ struct stat onefs_sbuf;
+
+ ret = lstat(fname, &onefs_sbuf);
+
+ if (ret == 0) {
+ /* we always want directories to appear zero size */
+ if (S_ISDIR(onefs_sbuf.st_mode)) {
+ onefs_sbuf.st_size = 0;
+ }
+ init_stat_ex_from_onefs_stat(sbuf, &onefs_sbuf);
+ }
+ return ret;
+}
+