Extend NTIMES to allow setting create_time
[metze/samba/wip.git] / source3 / modules / vfs_recycle.c
index a20e09f0108d65dffcb69e5029d441c697e181df..2b0edcdb4a198aaa2a9ce382c694902b77e526f0 100644 (file)
@@ -10,7 +10,7 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -19,8 +19,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "includes.h"
@@ -76,9 +75,9 @@ static const char *recycle_repository(vfs_handle_struct *handle)
        return tmp_str;
 }
 
-static BOOL recycle_keep_dir_tree(vfs_handle_struct *handle)
+static bool recycle_keep_dir_tree(vfs_handle_struct *handle)
 {
-       BOOL ret;
+       bool ret;
        
        ret = lp_parm_bool(SNUM(handle->conn), "recycle", "keeptree", False);
 
@@ -87,9 +86,9 @@ static BOOL recycle_keep_dir_tree(vfs_handle_struct *handle)
        return ret;
 }
 
-static BOOL recycle_versions(vfs_handle_struct *handle)
+static bool recycle_versions(vfs_handle_struct *handle)
 {
-       BOOL ret;
+       bool ret;
 
        ret = lp_parm_bool(SNUM(handle->conn), "recycle", "versions", False);
 
@@ -98,9 +97,9 @@ static BOOL recycle_versions(vfs_handle_struct *handle)
        return ret;
 }
 
-static BOOL recycle_touch(vfs_handle_struct *handle)
+static bool recycle_touch(vfs_handle_struct *handle)
 {
-       BOOL ret;
+       bool ret;
 
        ret = lp_parm_bool(SNUM(handle->conn), "recycle", "touch", False);
 
@@ -109,9 +108,9 @@ static BOOL recycle_touch(vfs_handle_struct *handle)
        return ret;
 }
 
-static BOOL recycle_touch_mtime(vfs_handle_struct *handle)
+static bool recycle_touch_mtime(vfs_handle_struct *handle)
 {
-       BOOL ret;
+       bool ret;
 
        ret = lp_parm_bool(SNUM(handle->conn), "recycle", "touch_mtime", False);
 
@@ -211,7 +210,7 @@ static mode_t recycle_subdir_mode(vfs_handle_struct *handle)
        return (mode_t)dirmode;
 }
 
-static BOOL recycle_directory_exist(vfs_handle_struct *handle, const char *dname)
+static bool recycle_directory_exist(vfs_handle_struct *handle, const char *dname)
 {
        SMB_STRUCT_STAT st;
 
@@ -224,7 +223,7 @@ static BOOL recycle_directory_exist(vfs_handle_struct *handle, const char *dname
        return False;
 }
 
-static BOOL recycle_file_exist(vfs_handle_struct *handle, const char *fname)
+static bool recycle_file_exist(vfs_handle_struct *handle, const char *fname)
 {
        SMB_STRUCT_STAT st;
 
@@ -261,7 +260,7 @@ static SMB_OFF_T recycle_get_file_size(vfs_handle_struct *handle, const char *fn
  * @param dname Directory tree to be created
  * @return Returns True for success
  **/
-static BOOL recycle_create_dir(vfs_handle_struct *handle, const char *dname)
+static bool recycle_create_dir(vfs_handle_struct *handle, const char *dname)
 {
        size_t len;
        mode_t mode;
@@ -269,7 +268,8 @@ static BOOL recycle_create_dir(vfs_handle_struct *handle, const char *dname)
        char *tmp_str = NULL;
        char *token;
        char *tok_str;
-       BOOL ret = False;
+       bool ret = False;
+       char *saveptr;
 
        mode = recycle_directory_mode(handle);
 
@@ -287,7 +287,8 @@ static BOOL recycle_create_dir(vfs_handle_struct *handle, const char *dname)
        }
 
        /* Create directory tree if neccessary */
-       for(token = strtok(tok_str, "/"); token; token = strtok(NULL, "/")) {
+       for(token = strtok_r(tok_str, "/", &saveptr); token;
+           token = strtok_r(NULL, "/", &saveptr)) {
                safe_strcat(new_dir, token, len);
                if (recycle_directory_exist(handle, new_dir))
                        DEBUG(10, ("recycle: dir %s already exists\n", new_dir));
@@ -315,7 +316,7 @@ done:
  * Return True if found
  **/
 
-static BOOL matchdirparam(const char **dir_exclude_list, char *path)
+static bool matchdirparam(const char **dir_exclude_list, char *path)
 {
        char *startp = NULL, *endp = NULL;
 
@@ -365,7 +366,7 @@ static BOOL matchdirparam(const char **dir_exclude_list, char *path)
  * @param needle string to be matched exectly to haystack including pattern matching
  * @return True if found
  **/
-static BOOL matchparam(const char **haystack_list, const char *needle)
+static bool matchparam(const char **haystack_list, const char *needle)
 {
        int i;
 
@@ -386,25 +387,33 @@ static BOOL matchparam(const char **haystack_list, const char *needle)
 /**
  * Touch access or modify date
  **/
-static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, BOOL touch_mtime)
+static void recycle_do_touch(vfs_handle_struct *handle, const char *fname,
+                            bool touch_mtime)
 {
        SMB_STRUCT_STAT st;
-       struct timespec ts[2];
-       
+       struct smb_file_time ft;
+       int ret, err;
+
+       ZERO_STRUCT(ft);
+
        if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) {
-               DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno)));
+               DEBUG(0,("recycle: stat for %s returned %s\n",
+                        fname, strerror(errno)));
                return;
        }
-       ts[0] = timespec_current(); /* atime */
-       ts[1] = touch_mtime ? ts[0] : get_mtimespec(&st); /* mtime */
-
-       if (SMB_VFS_NEXT_NTIMES(handle, fname, ts) == -1 ) {
-               DEBUG(0, ("recycle: touching %s failed, reason = %s\n", fname, strerror(errno)));
+       ft.atime = timespec_current(); /* atime */
+       ft.mtime = touch_mtime ? ft.atime : get_mtimespec(&st); /* mtime */
+
+       become_root();
+       ret = SMB_VFS_NEXT_NTIMES(handle, fname, &ft);
+       err = errno;
+       unbecome_root();
+       if (ret == -1 ) {
+               DEBUG(0, ("recycle: touching %s failed, reason = %s\n",
+                         fname, strerror(err)));
        }
 }
 
-extern userdom_struct current_user_info;
-
 /**
  * Check if file should be recycled
  **/
@@ -419,14 +428,15 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name)
        int i = 1;
        SMB_OFF_T maxsize, minsize;
        SMB_OFF_T file_size; /* space_avail;    */
-       BOOL exist;
+       bool exist;
        int rc = -1;
 
        repository = talloc_sub_advanced(NULL, lp_servicename(SNUM(conn)),
-                                       conn->user,
-                                       conn->connectpath, conn->gid,
-                                       get_current_username(),
-                                       current_user_info.domain,
+                                       conn->server_info->unix_name,
+                                       conn->connectpath,
+                                       conn->server_info->utok.gid,
+                                       conn->server_info->sanitized_username,
+                                       pdb_get_domain(conn->server_info->sam_account),
                                        recycle_repository(handle));
        ALLOC_CHECK(repository, done);
        /* shouldn't we allow absolute path names here? --metze */
@@ -517,7 +527,9 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name)
        }
 
        if (recycle_keep_dir_tree(handle) == True) {
-               asprintf(&temp_name, "%s/%s", repository, path_name);
+               if (asprintf(&temp_name, "%s/%s", repository, path_name) == -1) {
+                       ALLOC_CHECK(temp_name, done);
+               }
        } else {
                temp_name = SMB_STRDUP(repository);
        }
@@ -535,8 +547,9 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name)
                }
        }
 
-       asprintf(&final_name, "%s/%s", temp_name, base);
-       ALLOC_CHECK(final_name, done);
+       if (asprintf(&final_name, "%s/%s", temp_name, base) == -1) {
+               ALLOC_CHECK(final_name, done);
+       }
        DEBUG(10, ("recycle: recycled file name: %s\n", final_name));           /* new filename with path */
 
        /* check if we should delete file from recycle bin */
@@ -553,7 +566,9 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name)
        i = 1;
        while (recycle_file_exist(handle, final_name)) {
                SAFE_FREE(final_name);
-               asprintf(&final_name, "%s/Copy #%d of %s", temp_name, i++, base);
+               if (asprintf(&final_name, "%s/Copy #%d of %s", temp_name, i++, base) == -1) {
+                       ALLOC_CHECK(final_name, done);
+               }
        }
 
        DEBUG(10, ("recycle: Moving %s to %s\n", file_name, final_name));