Fix the overwriting of errno before use in a DEBUG statement and use the return value...
[samba.git] / source3 / modules / onefs_system.c
index b8b059bce9504737ae36924c6337ab21294ea92a..07272cc86b5ffc9e9bf5d223079aceba224fbcab 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include "includes.h"
+#include "smbd/smbd.h"
 #include "onefs.h"
 #include "onefs_config.h"
 #include "oplock_onefs.h"
@@ -94,23 +95,39 @@ int onefs_sys_create_file(connection_struct *conn,
        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;
@@ -146,7 +163,7 @@ int onefs_sys_create_file(connection_struct *conn,
                         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. */
@@ -162,34 +179,34 @@ int onefs_sys_create_file(connection_struct *conn,
                             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",
@@ -204,6 +221,7 @@ int onefs_sys_create_file(connection_struct *conn,
  out:
        END_PROFILE(syscall_createfile);
        aclu_free_sd(pifs_sd, false);
+       TALLOC_FREE(mapped_name);
 
        return ret_fd;
 }
@@ -212,7 +230,7 @@ int onefs_sys_create_file(connection_struct *conn,
  * 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;
@@ -231,7 +249,7 @@ static ssize_t onefs_sys_do_sendfile(int tofd, int fromfd,
 
        /* 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;
@@ -240,7 +258,7 @@ static ssize_t onefs_sys_do_sendfile(int tofd, int fromfd,
 
        total = count;
        while (total + hdtrl.iov_len) {
-               SMB_OFF_T nwritten;
+               off_t nwritten;
                int ret;
 
                /*
@@ -252,7 +270,11 @@ static ssize_t onefs_sys_do_sendfile(int tofd, int fromfd,
                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) {
@@ -293,7 +315,7 @@ static ssize_t onefs_sys_do_sendfile(int tofd, int fromfd,
                                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;
                        }
@@ -308,7 +330,7 @@ static ssize_t onefs_sys_do_sendfile(int tofd, int fromfd,
  * 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;
@@ -328,7 +350,7 @@ ssize_t onefs_sys_sendfile(connection_struct *conn, int tofd, int fromfd,
 
        /* 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;
        }
@@ -418,7 +440,7 @@ ssize_t onefs_sys_sendfile(connection_struct *conn, int tofd, int fromfd,
                }
 
                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));
                }
 
@@ -514,7 +536,7 @@ static char *get_spill_buffer(size_t new_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;
@@ -580,7 +602,7 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
 
        /* 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);
@@ -591,8 +613,8 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
         */
        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
@@ -603,9 +625,13 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
                               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;
@@ -624,7 +650,7 @@ ssize_t onefs_sys_recvfile(int fromfd, int tofd, SMB_OFF_T offset,
         */
        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);
@@ -660,3 +686,97 @@ out:
 
        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;
+}
+