s3: VFS: Add SMB_VFS_FCNTL
[samba.git] / source3 / lib / system.c
index 5baa8f7d3ff0e841389d0e430508350e94902045..679332255c008aa3300ef5c7cef38d80d30d23b3 100644 (file)
@@ -108,6 +108,20 @@ int sys_fcntl_long(int fd, int cmd, long arg)
        return ret;
 }
 
+/*******************************************************************
+A fcntl wrapper that will deal with EINTR.
+********************************************************************/
+
+int sys_fcntl_int(int fd, int cmd, int arg)
+{
+       int ret;
+
+       do {
+               ret = fcntl(fd, cmd, arg);
+       } while (ret == -1 && errno == EINTR);
+       return ret;
+}
+
 /****************************************************************************
  Get/Set all the possible time fields from a stat struct as a timespec.
 ****************************************************************************/
@@ -291,7 +305,7 @@ static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
                dst->st_ex_btime.tv_nsec = 0;
        }
 
-       dst->st_ex_calculated_birthtime = false;
+       dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_BTIME;
 
 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
        dst->st_ex_btime = pst->st_birthtimespec;
@@ -303,7 +317,7 @@ static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
        dst->st_ex_btime.tv_nsec = 0;
 #else
        dst->st_ex_btime = calc_create_time_stat(pst);
-       dst->st_ex_calculated_birthtime = true;
+       dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_BTIME;
 #endif
 
        /* Deal with systems that don't initialize birthtime correctly.
@@ -311,8 +325,11 @@ static void make_create_timespec(const struct stat *pst, struct stat_ex *dst,
         */
        if (null_timespec(dst->st_ex_btime)) {
                dst->st_ex_btime = calc_create_time_stat(pst);
-               dst->st_ex_calculated_birthtime = true;
+               dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_BTIME;
        }
+
+       dst->st_ex_itime = dst->st_ex_btime;
+       dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_ITIME;
 }
 
 /****************************************************************************
@@ -327,7 +344,7 @@ void update_stat_ex_mtime(struct stat_ex *dst,
        dst->st_ex_mtime = write_ts;
 
        /* We may have to recalculate btime. */
-       if (dst->st_ex_calculated_birthtime) {
+       if (dst->st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME) {
                dst->st_ex_btime = calc_create_time_stat_ex(dst);
        }
 }
@@ -336,7 +353,40 @@ void update_stat_ex_create_time(struct stat_ex *dst,
                                 struct timespec create_time)
 {
        dst->st_ex_btime = create_time;
-       dst->st_ex_calculated_birthtime = false;
+       dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_BTIME;
+}
+
+void update_stat_ex_itime(struct stat_ex *dst,
+                         struct timespec itime)
+{
+       dst->st_ex_itime = itime;
+       dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_ITIME;
+}
+
+void update_stat_ex_file_id(struct stat_ex *dst, uint64_t file_id)
+{
+       dst->st_ex_file_id = file_id;
+       dst->st_ex_iflags &= ~ST_EX_IFLAG_CALCULATED_FILE_ID;
+}
+
+void update_stat_ex_from_saved_stat(struct stat_ex *dst,
+                                   const struct stat_ex *src)
+{
+       if (!VALID_STAT(*src)) {
+               return;
+       }
+
+       if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_BTIME)) {
+               update_stat_ex_create_time(dst, src->st_ex_btime);
+       }
+
+       if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME)) {
+               update_stat_ex_itime(dst, src->st_ex_itime);
+       }
+
+       if (!(src->st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID)) {
+               update_stat_ex_file_id(dst, src->st_ex_file_id);
+       }
 }
 
 void init_stat_ex_from_stat (struct stat_ex *dst,
@@ -354,6 +404,7 @@ void init_stat_ex_from_stat (struct stat_ex *dst,
        dst->st_ex_atime = get_atimespec(src);
        dst->st_ex_mtime = get_mtimespec(src);
        dst->st_ex_ctime = get_ctimespec(src);
+       dst->st_ex_iflags = 0;
        make_create_timespec(src, dst, fake_dir_create_times);
 #ifdef HAVE_STAT_ST_BLKSIZE
        dst->st_ex_blksize = src->st_blksize;
@@ -372,6 +423,8 @@ void init_stat_ex_from_stat (struct stat_ex *dst,
 #else
        dst->st_ex_flags = 0;
 #endif
+       dst->st_ex_file_id = dst->st_ex_ino;
+       dst->st_ex_iflags |= ST_EX_IFLAG_CALCULATED_FILE_ID;
 }
 
 /*******************************************************************
@@ -509,7 +562,7 @@ int sys_fallocate(int fd, uint32_t mode, off_t offset, off_t len)
 #endif /* HAVE_LINUX_FALLOCATE */
 }
 
-#if HAVE_KERNEL_SHARE_MODES
+#ifdef HAVE_KERNEL_SHARE_MODES
 #ifndef LOCK_MAND
 #define LOCK_MAND      32      /* This is a mandatory flock */
 #define LOCK_READ      64      /* ... Which allows concurrent read operations */
@@ -524,7 +577,7 @@ int sys_fallocate(int fd, uint32_t mode, off_t offset, off_t len)
 
 void kernel_flock(int fd, uint32_t share_mode, uint32_t access_mask)
 {
-#if HAVE_KERNEL_SHARE_MODES
+#ifdef HAVE_KERNEL_SHARE_MODES
        int kernel_mode = 0;
        if (share_mode == FILE_SHARE_WRITE) {
                kernel_mode = LOCK_MAND|LOCK_WRITE;
@@ -571,6 +624,21 @@ int sys_mknod(const char *path, mode_t mode, SMB_DEV_T dev)
 #endif
 }
 
+/*******************************************************************
+ A mknodat() wrapper.
+********************************************************************/
+
+int sys_mknodat(int dirfd, const char *path, mode_t mode, SMB_DEV_T dev)
+{
+#if defined(HAVE_MKNODAT)
+       return mknodat(dirfd, path, mode, dev);
+#else
+       /* No mknod system call. */
+       errno = ENOSYS;
+       return -1;
+#endif
+}
+
 /*******************************************************************
  System wrapper for getwd. Always returns MALLOC'ed memory, or NULL
  on error (malloc fail usually).
@@ -580,7 +648,7 @@ char *sys_getwd(void)
 {
 #ifdef GETCWD_TAKES_NULL
        return getcwd(NULL, 0);
-#elif HAVE_GETCWD
+#elif defined(HAVE_GETCWD)
        char *wd = NULL, *s = NULL;
        size_t allocated = PATH_MAX;
 
@@ -594,7 +662,9 @@ char *sys_getwd(void)
                        break;
                }
                if (errno != ERANGE) {
+                       int saved_errno = errno;
                        SAFE_FREE(s);
+                       errno = saved_errno;
                        break;
                }
                allocated *= 2;
@@ -612,7 +682,9 @@ char *sys_getwd(void)
        }
        wd = getwd(s);
        if (wd == NULL) {
+               int saved_errno = errno;
                SAFE_FREE(s);
+               errno = saved_errno;
        }
        return wd;
 #endif