*/
#include "includes.h"
+#include "smbd/smbd.h"
#include "onefs.h"
#include "onefs_config.h"
#include "oplock_onefs.h"
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;
}
* FreeBSD based sendfile implementation that allows for atomic semantics.
*/
static ssize_t onefs_sys_do_sendfile(int tofd, int fromfd,
- const DATA_BLOB *header, SMB_OFF_T offset, size_t count, bool atomic)
+ const DATA_BLOB *header, off_t offset, size_t count, bool atomic)
{
size_t total=0;
struct sf_hdtr hdr;
/* 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;
total = count;
while (total + hdtrl.iov_len) {
- SMB_OFF_T nwritten;
+ off_t nwritten;
int ret;
/*
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;
}
* Handles the subtleties of using sendfile with CIFS.
*/
ssize_t onefs_sys_sendfile(connection_struct *conn, int tofd, int fromfd,
- const DATA_BLOB *header, SMB_OFF_T offset,
+ const DATA_BLOB *header, off_t offset,
size_t count)
{
bool atomic = false;
/* 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;
}
}
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));
}
* from the socket into the buffer, the spill buffer is then written with a
* standard pwrite.
*/
-ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
+ssize_t onefs_sys_recvfile(int fromfd, int tofd, off_t offset,
size_t count)
{
char *spill_buffer = NULL;
/* 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);
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;
+}
+