static int atalk_rename(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldname, const char *newname) { int ret = 0; char *adbl_path = 0; char *orig_path = 0; SMB_STRUCT_STAT adbl_info; SMB_STRUCT_STAT orig_info; TALLOC_CTX *ctx; ret = SMB_VFS_NEXT_RENAME(handle, conn, oldname, newname); if (!conn || !oldname) return ret; if (!(ctx = talloc_init("rename_file"))) return ret; if (atalk_build_paths(ctx, conn->origpath, oldname, &adbl_path, &orig_path, &adbl_info, &orig_info) != 0) return ret; if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) { DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); goto exit_rename; } atalk_unlink_file(adbl_path); exit_rename: talloc_destroy(ctx); return ret; }
static int cap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *oldname, const char *newname) { pstring capold, capnew; capencode(capold, oldname); capencode(capnew, newname); return SMB_VFS_NEXT_RENAME(handle, conn, capold, capnew); }
static int audit_rename(vfs_handle_struct *handle, const char *oldname, const char *newname) { int result; result = SMB_VFS_NEXT_RENAME(handle, oldname, newname); syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n", oldname, newname, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); return result; }
static int greyhole_rename(vfs_handle_struct *handle, const struct smb_filename *oldname, const struct smb_filename *newname) { int result; result = SMB_VFS_NEXT_RENAME(handle, oldname, newname); if (result >= 0) { gh_spoolf("rename\n%s\n%s\n%s\n\n", lp_servicename(talloc_tos(), handle->conn->params->service), oldname->base_name, newname->base_name); } return result; }
static int audit_rename(vfs_handle_struct *handle, const struct smb_filename *smb_fname_src, const struct smb_filename *smb_fname_dst) { int result; result = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n", smb_fname_src->base_name, smb_fname_dst->base_name, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); return result; }
/* rename needs special handling, as we may need to fsync two directories */ static int syncops_rename(vfs_handle_struct *handle, const struct smb_filename *smb_fname_src, const struct smb_filename *smb_fname_dst) { int ret; struct syncops_config_data *config; SMB_VFS_HANDLE_GET_DATA(handle, config, struct syncops_config_data, return -1); ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); if (ret == 0 && config->onmeta && !config->disable) { syncops_two_names(smb_fname_src->base_name, smb_fname_dst->base_name); } return ret; }
static int greyhole_rename(vfs_handle_struct *handle, const char *oldname, const char *newname) { int result; FILE *spoolf; char filename[38]; struct timeval tp; result = SMB_VFS_NEXT_RENAME(handle, oldname, newname); if (result >= 0) { gettimeofday(&tp, (struct timezone *) NULL); snprintf(filename, 37, "/var/spool/greyhole/%.0f", ((double) (tp.tv_sec)*1000000.0) + (((double) tp.tv_usec))); spoolf = fopen(filename, "wt"); fprintf(spoolf, "rename\n%s\n%s\n%s\n\n", lp_servicename(handle->conn->params->service), oldname, newname); fclose(spoolf); } return result; }
static int audit_rename(vfs_handle_struct *handle, const struct smb_filename *smb_fname_src, const struct smb_filename *smb_fname_dst) { int result; result = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); if (lp_syslog() > 0) { syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n", smb_fname_src->base_name, smb_fname_dst->base_name, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); } DEBUG(1, ("vfs_extd_audit: rename old: %s newname: %s %s %s\n", smb_fname_str_dbg(smb_fname_src), smb_fname_str_dbg(smb_fname_dst), (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : "")); return result; }
static int atalk_rename(struct vfs_handle_struct *handle, const struct smb_filename *smb_fname_src, const struct smb_filename *smb_fname_dst) { int ret = 0; char *oldname = NULL; char *adbl_path = NULL; char *orig_path = NULL; SMB_STRUCT_STAT adbl_info; SMB_STRUCT_STAT orig_info; NTSTATUS status; ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); status = get_full_smb_filename(talloc_tos(), smb_fname_src, &oldname); if (!NT_STATUS_IS_OK(status)) { return ret; } if (atalk_build_paths(talloc_tos(), handle->conn->cwd, oldname, &adbl_path, &orig_path, &adbl_info, &orig_info) != 0) goto exit_rename; if (S_ISDIR(orig_info.st_ex_mode) || S_ISREG(orig_info.st_ex_mode)) { DEBUG(3, ("ATALK: %s has passed..\n", adbl_path)); goto exit_rename; } atalk_unlink_file(adbl_path); exit_rename: TALLOC_FREE(oldname); TALLOC_FREE(adbl_path); TALLOC_FREE(orig_path); return ret; }
static int skel_rename(vfs_handle_struct *handle, const struct smb_filename *smb_fname_src, const struct smb_filename *smb_fname_dst) { return SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); }
static int streams_xattr_rename(vfs_handle_struct *handle, const struct smb_filename *smb_fname_src, const struct smb_filename *smb_fname_dst) { NTSTATUS status; int ret = -1; char *src_xattr_name = NULL; char *dst_xattr_name = NULL; bool src_is_stream, dst_is_stream; ssize_t oret; ssize_t nret; struct ea_struct ea; src_is_stream = is_ntfs_stream_smb_fname(smb_fname_src); dst_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst); if (!src_is_stream && !dst_is_stream) { return SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); } /* For now don't allow renames from or to the default stream. */ if (is_ntfs_default_stream_smb_fname(smb_fname_src) || is_ntfs_default_stream_smb_fname(smb_fname_dst)) { errno = ENOSYS; goto done; } /* Don't rename if the streams are identical. */ if (strcasecmp_m(smb_fname_src->stream_name, smb_fname_dst->stream_name) == 0) { goto done; } /* Get the xattr names. */ status = streams_xattr_get_name(handle, talloc_tos(), smb_fname_src->stream_name, &src_xattr_name); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); goto fail; } status = streams_xattr_get_name(handle, talloc_tos(), smb_fname_dst->stream_name, &dst_xattr_name); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); goto fail; } /* read the old stream */ status = get_ea_value(talloc_tos(), handle->conn, NULL, smb_fname_src, src_xattr_name, &ea); if (!NT_STATUS_IS_OK(status)) { errno = ENOENT; goto fail; } /* (over)write the new stream */ nret = SMB_VFS_SETXATTR(handle->conn, smb_fname_src, dst_xattr_name, ea.value.data, ea.value.length, 0); if (nret < 0) { if (errno == ENOATTR) { errno = ENOENT; } goto fail; } /* remove the old stream */ oret = SMB_VFS_REMOVEXATTR(handle->conn, smb_fname_src, src_xattr_name); if (oret < 0) { if (errno == ENOATTR) { errno = ENOENT; } goto fail; } done: errno = 0; ret = 0; fail: TALLOC_FREE(src_xattr_name); TALLOC_FREE(dst_xattr_name); return ret; }
/** * Check if file should be recycled **/ static int recycle_unlink(vfs_handle_struct *handle, const struct smb_filename *smb_fname) { connection_struct *conn = handle->conn; char *path_name = NULL; char *temp_name = NULL; char *final_name = NULL; struct smb_filename *smb_fname_final = NULL; const char *base; char *repository = NULL; int i = 1; SMB_OFF_T maxsize, minsize; SMB_OFF_T file_size; /* space_avail; */ bool exist; NTSTATUS status; int rc = -1; repository = talloc_sub_advanced(NULL, lp_servicename(SNUM(conn)), conn->session_info->unix_name, conn->connectpath, conn->session_info->utok.gid, conn->session_info->sanitized_username, conn->session_info->info3->base.domain.string, recycle_repository(handle)); ALLOC_CHECK(repository, done); /* shouldn't we allow absolute path names here? --metze */ /* Yes :-). JRA. */ trim_char(repository, '\0', '/'); if(!repository || *(repository) == '\0') { DEBUG(3, ("recycle: repository path not set, purging %s...\n", smb_fname_str_dbg(smb_fname))); rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } /* we don't recycle the recycle bin... */ if (strncmp(smb_fname->base_name, repository, strlen(repository)) == 0) { DEBUG(3, ("recycle: File is within recycling bin, unlinking ...\n")); rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } file_size = recycle_get_file_size(handle, smb_fname); /* it is wrong to purge filenames only because they are empty imho * --- simo * if(fsize == 0) { DEBUG(3, ("recycle: File %s is empty, purging...\n", file_name)); rc = SMB_VFS_NEXT_UNLINK(handle,file_name); goto done; } */ /* FIXME: this is wrong, we should check the whole size of the recycle bin is * not greater then maxsize, not the size of the single file, also it is better * to remove older files */ maxsize = recycle_maxsize(handle); if(maxsize > 0 && file_size > maxsize) { DEBUG(3, ("recycle: File %s exceeds maximum recycle size, " "purging... \n", smb_fname_str_dbg(smb_fname))); rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } minsize = recycle_minsize(handle); if(minsize > 0 && file_size < minsize) { DEBUG(3, ("recycle: File %s lowers minimum recycle size, " "purging... \n", smb_fname_str_dbg(smb_fname))); rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } /* FIXME: this is wrong: moving files with rename does not change the disk space * allocation * space_avail = SMB_VFS_NEXT_DISK_FREE(handle, ".", True, &bsize, &dfree, &dsize) * 1024L; DEBUG(5, ("space_avail = %Lu, file_size = %Lu\n", space_avail, file_size)); if(space_avail < file_size) { DEBUG(3, ("recycle: Not enough diskspace, purging file %s\n", file_name)); rc = SMB_VFS_NEXT_UNLINK(handle, file_name); goto done; } */ /* extract filename and path */ base = strrchr(smb_fname->base_name, '/'); if (base == NULL) { base = smb_fname->base_name; path_name = SMB_STRDUP("/"); ALLOC_CHECK(path_name, done); } else { path_name = SMB_STRDUP(smb_fname->base_name); ALLOC_CHECK(path_name, done); path_name[base - smb_fname->base_name] = '\0'; base++; } /* original filename with path */ DEBUG(10, ("recycle: fname = %s\n", smb_fname_str_dbg(smb_fname))); /* original path */ DEBUG(10, ("recycle: fpath = %s\n", path_name)); /* filename without path */ DEBUG(10, ("recycle: base = %s\n", base)); if (matchparam(recycle_exclude(handle), base)) { DEBUG(3, ("recycle: file %s is excluded \n", base)); rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } if (matchdirparam(recycle_exclude_dir(handle), path_name)) { DEBUG(3, ("recycle: directory %s is excluded \n", path_name)); rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } if (recycle_keep_dir_tree(handle) == True) { if (asprintf(&temp_name, "%s/%s", repository, path_name) == -1) { ALLOC_CHECK(temp_name, done); } } else { temp_name = SMB_STRDUP(repository); } ALLOC_CHECK(temp_name, done); exist = recycle_directory_exist(handle, temp_name); if (exist) { DEBUG(10, ("recycle: Directory already exists\n")); } else { DEBUG(10, ("recycle: Creating directory %s\n", temp_name)); if (recycle_create_dir(handle, temp_name) == False) { DEBUG(3, ("recycle: Could not create directory, " "purging %s...\n", smb_fname_str_dbg(smb_fname))); rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } } if (asprintf(&final_name, "%s/%s", temp_name, base) == -1) { ALLOC_CHECK(final_name, done); } /* Create smb_fname with final base name and orig stream name. */ status = create_synthetic_smb_fname(talloc_tos(), final_name, smb_fname->stream_name, NULL, &smb_fname_final); if (!NT_STATUS_IS_OK(status)) { rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } /* new filename with path */ DEBUG(10, ("recycle: recycled file name: %s\n", smb_fname_str_dbg(smb_fname_final))); /* check if we should delete file from recycle bin */ if (recycle_file_exist(handle, smb_fname_final)) { if (recycle_versions(handle) == False || matchparam(recycle_noversions(handle), base) == True) { DEBUG(3, ("recycle: Removing old file %s from recycle " "bin\n", smb_fname_str_dbg(smb_fname_final))); if (SMB_VFS_NEXT_UNLINK(handle, smb_fname_final) != 0) { DEBUG(1, ("recycle: Error deleting old file: %s\n", strerror(errno))); } } } /* rename file we move to recycle bin */ i = 1; while (recycle_file_exist(handle, smb_fname_final)) { SAFE_FREE(final_name); if (asprintf(&final_name, "%s/Copy #%d of %s", temp_name, i++, base) == -1) { ALLOC_CHECK(final_name, done); } TALLOC_FREE(smb_fname_final->base_name); smb_fname_final->base_name = talloc_strdup(smb_fname_final, final_name); if (smb_fname_final->base_name == NULL) { rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } } DEBUG(10, ("recycle: Moving %s to %s\n", smb_fname_str_dbg(smb_fname), smb_fname_str_dbg(smb_fname_final))); rc = SMB_VFS_NEXT_RENAME(handle, smb_fname, smb_fname_final); if (rc != 0) { DEBUG(3, ("recycle: Move error %d (%s), purging file %s " "(%s)\n", errno, strerror(errno), smb_fname_str_dbg(smb_fname), smb_fname_str_dbg(smb_fname_final))); rc = SMB_VFS_NEXT_UNLINK(handle, smb_fname); goto done; } /* touch access date of moved file */ if (recycle_touch(handle) == True || recycle_touch_mtime(handle)) recycle_do_touch(handle, smb_fname_final, recycle_touch_mtime(handle)); done: SAFE_FREE(path_name); SAFE_FREE(temp_name); SAFE_FREE(final_name); TALLOC_FREE(smb_fname_final); TALLOC_FREE(repository); return rc; }
static int skel_rename(vfs_handle_struct *handle, const char *oldname, const char *newname) { return SMB_VFS_NEXT_RENAME(handle, oldname, newname); }
int onefs_rename(vfs_handle_struct *handle, const struct smb_filename *smb_fname_src, const struct smb_filename *smb_fname_dst) { struct smb_filename *smb_fname_src_onefs = NULL; struct smb_filename *smb_fname_dst_onefs = NULL; NTSTATUS status; int saved_errno; int dir_fd = -1; int ret = -1; START_PROFILE(syscall_rename_at); if (!is_ntfs_stream_smb_fname(smb_fname_src) && !is_ntfs_stream_smb_fname(smb_fname_dst)) { ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst); goto done; } /* For now don't allow renames from or to the default stream. */ if (is_ntfs_default_stream_smb_fname(smb_fname_src) || is_ntfs_default_stream_smb_fname(smb_fname_dst)) { DEBUG(3, ("Unable to rename to/from a default stream: %s -> " "%s\n", smb_fname_str_dbg(smb_fname_src), smb_fname_str_dbg(smb_fname_dst))); errno = ENOSYS; goto done; } /* prep stream smb_filename structs. */ status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname_src, &smb_fname_src_onefs); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); goto done; } status = onefs_stream_prep_smb_fname(talloc_tos(), smb_fname_dst, &smb_fname_dst_onefs); if (!NT_STATUS_IS_OK(status)) { errno = map_errno_from_nt_status(status); goto done; } dir_fd = get_stream_dir_fd(handle->conn, smb_fname_src->base_name, NULL); if (dir_fd < -1) { goto done; } DEBUG(8, ("onefs_rename called for %s => %s\n", smb_fname_str_dbg(smb_fname_src_onefs), smb_fname_str_dbg(smb_fname_dst_onefs))); /* Handle rename of stream to default stream specially. */ if (smb_fname_dst_onefs->stream_name == NULL) { ret = enc_renameat(dir_fd, smb_fname_src_onefs->stream_name, ENC_DEFAULT, AT_FDCWD, smb_fname_dst_onefs->base_name, ENC_DEFAULT); } else { ret = enc_renameat(dir_fd, smb_fname_src_onefs->stream_name, ENC_DEFAULT, dir_fd, smb_fname_dst_onefs->stream_name, ENC_DEFAULT); } done: END_PROFILE(syscall_rename_at); TALLOC_FREE(smb_fname_src_onefs); TALLOC_FREE(smb_fname_dst_onefs); saved_errno = errno; if (dir_fd >= 0) { close(dir_fd); } errno = saved_errno; return ret; }
static ssize_t vfs_my_module_pwrite(vfs_handle_struct *handle, files_struct *fsp, const void *data, size_t n, off_t offset) { connection_struct *conn = handle->conn; char *path_name = NULL; char *temp_name = NULL; char *final_name = NULL; const struct smb_filename *smb_fname = fsp->fsp_name; struct smb_filename *smb_fname_final = NULL; const char *base; char *repository,*repositoryTemp = NULL; int i = 1; SMB_OFF_T maxsize, minsize; SMB_OFF_T file_size; /* space_avail; */ bool exist; NTSTATUS status; ssize_t rc = -1; int count = 0; const char *share = "/mnt/share"; repository = talloc_sub_advanced(NULL, lp_servicename(SNUM(conn)), conn->session_info->unix_name, conn->connectpath, conn->session_info->utok.gid, conn->session_info->sanitized_username, conn->session_info->info3->base.domain.string, sharevolume(handle)); ALLOC_CHECK(repository, done); trim_char(repository, '\0', '/'); if(!repository || *(repository) == '\0') { rc = SMB_VFS_NEXT_PWRITE(handle, fsp,data,n,offset); goto done; } file_size = vfs_my_module_get_file_size(handle, smb_fname); maxsize = vfs_my_module_maxsize(handle); if(maxsize > 0 && file_size > maxsize){ repository = talloc_sub_advanced(NULL, lp_servicename(SNUM(conn)), conn->session_info->unix_name, conn->connectpath, conn->session_info->utok.gid, conn->session_info->sanitized_username, conn->session_info->info3->base.domain.string, stripevolume(handle)); ALLOC_CHECK(repository, done); trim_char(repository, '\0', '/'); if(!repository || *(repository) == '\0') { rc = SMB_VFS_NEXT_PWRITE(handle, fsp,data,n,offset); goto done; } } if (strncmp(smb_fname->base_name, repository, strlen(repository)) == 0) { rc = SMB_VFS_NEXT_PWRITE(handle, fsp,data,n,offset); goto done; } base = strrchr(smb_fname->base_name, '/'); if (base == NULL) { base = smb_fname->base_name; path_name = SMB_STRDUP("/"); ALLOC_CHECK(path_name, done); } else { path_name = SMB_STRDUP(smb_fname->base_name); ALLOC_CHECK(path_name, done); path_name[base - smb_fname->base_name] = '\0'; base++; } /* original filename with path */ DEBUG(10, ("file transaction: fname = %s\n", smb_fname_str_dbg(smb_fname))); /* original path */ DEBUG(10, ("file transaction: fpath = %s\n", path_name)); /* filename without path */ DEBUG(10, ("file transaction: base = %s\n", base)); if (vfs_my_module_keep_dir_tree(handle) == True) { if (asprintf(&temp_name, "%s/%s", repository, path_name) == -1) { ALLOC_CHECK(temp_name, done); } } else { temp_name = SMB_STRDUP(repository); } ALLOC_CHECK(temp_name, done); exist = vfs_my_module_directory_exist(handle, temp_name); if (exist) { DEBUG(10, ("file transaction: Directory already exists\n")); } else { DEBUG(10, ("file transaction: Creating directory %s\n", temp_name)); count = vfs_my_module_create_dir(handle, temp_name, smb_fname); } if (asprintf(&final_name, "%s/%s", temp_name, base) == -1) { ALLOC_CHECK(final_name, done); } /* Create smb_fname with final base name and orig stream name. */ status = create_synthetic_smb_fname(talloc_tos(), final_name, smb_fname->stream_name, NULL, &smb_fname_final); if (!NT_STATUS_IS_OK(status)) { rc = SMB_VFS_NEXT_PWRITE(handle, fsp,data,n,offset); goto done; } TALLOC_FREE(smb_fname_final->base_name); smb_fname_final->base_name = talloc_strdup(smb_fname_final, final_name); if (smb_fname_final->base_name == NULL) { rc = SMB_VFS_NEXT_PWRITE(handle, fsp,data,n,offset); goto done; } SMB_VFS_NEXT_RENAME(handle, smb_fname, smb_fname_final); rc = SMB_VFS_NEXT_PWRITE(handle, fsp,data,n,offset); if (rc != 0) { rc = SMB_VFS_NEXT_PWRITE(handle, fsp,data,n,offset); goto done; } done: vfs_my_module_delete_dir(handle,path_name,smb_fname); while(count !=0){ vfs_my_module_delete_dir(handle,path_name,smb_fname); SMB_VFS_NEXT_RMDIR(handle, path_name); count--; } SAFE_FREE(path_name); SAFE_FREE(temp_name); SAFE_FREE(final_name); TALLOC_FREE(smb_fname_final); TALLOC_FREE(repository); return rc; }
/** * Check if file should be recycled **/ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *file_name) { char *path_name = NULL; char *temp_name = NULL; char *final_name = NULL; const char *base; char *repository = NULL; int i = 1; int maxsize; SMB_OFF_T file_size; /* space_avail; */ BOOL exist; int rc = -1; repository = alloc_sub_conn(conn, recycle_repository(handle)); ALLOC_CHECK(repository, done); /* shouldn't we allow absolute path names here? --metze */ trim_char(repository, '/', '/'); if(!repository || *(repository) == '\0') { DEBUG(3, ("recycle: repository path not set, purging %s...\n", file_name)); rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } /* we don't recycle the recycle bin... */ if (strncmp(file_name, repository, strlen(repository)) == 0) { DEBUG(3, ("recycle: File is within recycling bin, unlinking ...\n")); rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } file_size = recycle_get_file_size(handle, file_name); /* it is wrong to purge filenames only because they are empty imho * --- simo * if(fsize == 0) { DEBUG(3, ("recycle: File %s is empty, purging...\n", file_name)); rc = SMB_VFS_NEXT_UNLINK(handle,conn,file_name); goto done; } */ /* FIXME: this is wrong, we should check the hole size of the recycle bin is * not greater then maxsize, not the size of the single file, also it is better * to remove older files */ maxsize = recycle_maxsize(handle); if(maxsize > 0 && file_size > maxsize) { DEBUG(3, ("recycle: File %s exceeds maximum recycle size, purging... \n", file_name)); rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } /* FIXME: this is wrong: moving files with rename does not change the disk space * allocation * space_avail = SMB_VFS_NEXT_DISK_FREE(handle, conn, ".", True, &bsize, &dfree, &dsize) * 1024L; DEBUG(5, ("space_avail = %Lu, file_size = %Lu\n", space_avail, file_size)); if(space_avail < file_size) { DEBUG(3, ("recycle: Not enough diskspace, purging file %s\n", file_name)); rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } */ /* extract filename and path */ base = strrchr(file_name, '/'); if (base == NULL) { base = file_name; path_name = SMB_STRDUP("/"); ALLOC_CHECK(path_name, done); } else { path_name = SMB_STRDUP(file_name); ALLOC_CHECK(path_name, done); path_name[base - file_name] = '\0'; base++; } DEBUG(10, ("recycle: fname = %s\n", file_name)); /* original filename with path */ DEBUG(10, ("recycle: fpath = %s\n", path_name)); /* original path */ DEBUG(10, ("recycle: base = %s\n", base)); /* filename without path */ if (matchparam(recycle_exclude(handle), base)) { DEBUG(3, ("recycle: file %s is excluded \n", base)); rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } /* FIXME: this check will fail if we have more than one level of directories, * we shoud check for every level 1, 1/2, 1/2/3, 1/2/3/4 .... * ---simo */ if (checkparam(recycle_exclude_dir(handle), path_name)) { DEBUG(3, ("recycle: directory %s is excluded \n", path_name)); rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } if (recycle_keep_dir_tree(handle) == True) { asprintf(&temp_name, "%s/%s", repository, path_name); } else { temp_name = SMB_STRDUP(repository); } ALLOC_CHECK(temp_name, done); exist = recycle_directory_exist(handle, temp_name); if (exist) { DEBUG(10, ("recycle: Directory already exists\n")); } else { DEBUG(10, ("recycle: Creating directory %s\n", temp_name)); if (recycle_create_dir(handle, temp_name) == False) { DEBUG(3, ("recycle: Could not create directory, purging %s...\n", file_name)); rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } } asprintf(&final_name, "%s/%s", temp_name, base); 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 */ if (recycle_file_exist(handle, final_name)) { if (recycle_versions(handle) == False || matchparam(recycle_noversions(handle), base) == True) { DEBUG(3, ("recycle: Removing old file %s from recycle bin\n", final_name)); if (SMB_VFS_NEXT_UNLINK(handle, conn, final_name) != 0) { DEBUG(1, ("recycle: Error deleting old file: %s\n", strerror(errno))); } } } /* rename file we move to recycle bin */ 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); } DEBUG(10, ("recycle: Moving %s to %s\n", file_name, final_name)); rc = SMB_VFS_NEXT_RENAME(handle, conn, file_name, final_name); if (rc != 0) { DEBUG(3, ("recycle: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name)); rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } /* touch access date of moved file */ if (recycle_touch(handle) == True ) recycle_do_touch(handle, final_name); done: SAFE_FREE(path_name); SAFE_FREE(temp_name); SAFE_FREE(final_name); SAFE_FREE(repository); return rc; }