/* Copies file/directory overwriting destination files if requested. Returns * non-zero on error, otherwise zero is returned. */ static int op_cp(void *data, const char src[], const char dst[], int overwrite) { #ifndef _WIN32 char *escaped_src, *escaped_dst; char cmd[6 + PATH_MAX*2 + 1]; int result; escaped_src = escape_filename(src, 0); escaped_dst = escape_filename(dst, 0); if(escaped_src == NULL || escaped_dst == NULL) { free(escaped_dst); free(escaped_src); return -1; } snprintf(cmd, sizeof(cmd), "cp %s -R " PRESERVE_FLAGS " %s %s", overwrite ? "" : NO_CLOBBER, escaped_src, escaped_dst); LOG_INFO_MSG("Running cp command: \"%s\"", cmd); result = background_and_wait_for_errors(cmd); free(escaped_dst); free(escaped_src); return result; #else int ret; if(is_dir(src)) { char cmd[6 + PATH_MAX*2 + 1]; snprintf(cmd, sizeof(cmd), "xcopy \"%s\" \"%s\" ", src, dst); to_back_slash(cmd); if(is_vista_and_above()) strcat(cmd, "/B "); if(overwrite) { strcat(cmd, "/Y "); } strcat(cmd, "/E /I /H /R > NUL"); ret = system(cmd); } else { ret = (CopyFileA(src, dst, 0) == 0); } return ret; #endif }
static int op_removesl(void *data, const char *src, const char *dst) { #ifndef _WIN32 char *escaped; char cmd[16 + PATH_MAX]; int result; escaped = escape_filename(src, 0); if(escaped == NULL) return -1; snprintf(cmd, sizeof(cmd), "rm -rf %s", escaped); LOG_INFO_MSG("Running rm command: \"%s\"", cmd); result = background_and_wait_for_errors(cmd); free(escaped); return result; #else if(is_dir(src)) { char buf[PATH_MAX]; int err; int i; snprintf(buf, sizeof(buf), "%s%c", src, '\0'); for(i = 0; buf[i] != '\0'; i++) if(buf[i] == '/') buf[i] = '\\'; SHFILEOPSTRUCTA fo = { .hwnd = NULL, .wFunc = FO_DELETE, .pFrom = buf, .pTo = NULL, .fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI, }; err = SHFileOperation(&fo); log_msg("Error: %d", err); return err; } else { int ok; DWORD attributes = GetFileAttributesA(src); if(attributes & FILE_ATTRIBUTE_READONLY) SetFileAttributesA(src, attributes & ~FILE_ATTRIBUTE_READONLY); ok = DeleteFile(src); if(!ok) LOG_WERROR(GetLastError()); return !ok; } #endif }
static int op_chmod(void *data, const char *src, const char *dst) { char cmd[128 + PATH_MAX]; char *escaped; escaped = escape_filename(src, 0); snprintf(cmd, sizeof(cmd), "chmod %s %s", (char *)data, escaped); free(escaped); LOG_INFO_MSG("Running chmod command: \"%s\"", cmd); return background_and_wait_for_errors(cmd); }
static int op_rmdir(void *data, const char *src, const char *dst) { #ifndef _WIN32 char cmd[128 + PATH_MAX]; char *escaped; escaped = escape_filename(src, 0); snprintf(cmd, sizeof(cmd), "rmdir %s", escaped); free(escaped); LOG_INFO_MSG("Running rmdir command: \"%s\"", cmd); return background_and_wait_for_errors(cmd); #else return RemoveDirectory(src) == 0; #endif }
static int op_mkdir(void *data, const char *src, const char *dst) { #ifndef _WIN32 char cmd[128 + PATH_MAX]; char *escaped; escaped = escape_filename(src, 0); snprintf(cmd, sizeof(cmd), "mkdir %s %s", (data == NULL) ? "" : "-p", escaped); free(escaped); LOG_INFO_MSG("Running mkdir command: \"%s\"", cmd); return background_and_wait_for_errors(cmd); #else if(data == NULL) { return CreateDirectory(src, NULL) == 0; } else { char *p; char t; p = strchr(src + 2, '/'); do { t = *p; *p = '\0'; if(!is_dir(src)) { if(!CreateDirectory(src, NULL)) { *p = t; return -1; } } *p = t; if((p = strchr(p + 1, '/')) == NULL) p = (char *)src + strlen(src); } while(t != '\0'); return 0; } #endif }
/* Moves file/directory overwriting destination files if requested. Returns * non-zero on error, otherwise zero is returned. */ static int op_mv(void *data, const char src[], const char dst[], int overwrite) { #ifndef _WIN32 struct stat st; char *escaped_src, *escaped_dst; char cmd[6 + PATH_MAX*2 + 1]; int result; if(lstat(dst, &st) == 0) return -1; escaped_src = escape_filename(src, 0); escaped_dst = escape_filename(dst, 0); if(escaped_src == NULL || escaped_dst == NULL) { free(escaped_dst); free(escaped_src); return -1; } snprintf(cmd, sizeof(cmd), "mv %s %s %s", overwrite ? "" : NO_CLOBBER, escaped_src, escaped_dst); free(escaped_dst); free(escaped_src); LOG_INFO_MSG("Running mv command: \"%s\"", cmd); if((result = background_and_wait_for_errors(cmd)) != 0) return result; if(path_starts_with(dst, cfg.trash_dir)) add_to_trash(src, strrchr(dst, '/') + 1); else if(path_starts_with(src, cfg.trash_dir)) remove_from_trash(strrchr(src, '/') + 1); return 0; #else BOOL ret = MoveFile(src, dst); if(!ret && GetLastError() == 5) { int r = op_cp(data, src, dst, overwrite); if(r != 0) return r; return op_removesl(data, src, NULL); } return ret == 0; #endif }
static int op_chgrp(void *data, const char *src, const char *dst) { #ifndef _WIN32 char cmd[10 + 32 + PATH_MAX]; char *escaped; gid_t gid = (gid_t)(long)data; escaped = escape_filename(src, 0); snprintf(cmd, sizeof(cmd), "chown -fR :%u %s", gid, escaped); free(escaped); LOG_INFO_MSG("Running chgrp command: \"%s\"", cmd); return background_and_wait_for_errors(cmd); #else return -1; #endif }
static int op_symlink(void *data, const char *src, const char *dst) { char *escaped_src, *escaped_dst; char cmd[6 + PATH_MAX*2 + 1]; int result; #ifdef _WIN32 char buf[PATH_MAX + 2]; #endif escaped_src = escape_filename(src, 0); escaped_dst = escape_filename(dst, 0); if(escaped_src == NULL || escaped_dst == NULL) { free(escaped_dst); free(escaped_src); return -1; } #ifndef _WIN32 snprintf(cmd, sizeof(cmd), "ln -s %s %s", escaped_src, escaped_dst); LOG_INFO_MSG("Running ln command: \"%s\"", cmd); result = background_and_wait_for_errors(cmd); #else if(GetModuleFileNameA(NULL, buf, ARRAY_LEN(buf)) == 0) { free(escaped_dst); free(escaped_src); return -1; } *strrchr(buf, '\\') = '\0'; snprintf(cmd, sizeof(cmd), "%s\\win_helper -s %s %s", buf, escaped_src, escaped_dst); result = system(cmd); #endif free(escaped_dst); free(escaped_src); return result; }
static int op_mkfile(void *data, const char *src, const char *dst) { #ifndef _WIN32 char cmd[128 + PATH_MAX]; char *escaped; escaped = escape_filename(src, 0); snprintf(cmd, sizeof(cmd), "touch %s", escaped); free(escaped); LOG_INFO_MSG("Running touch command: \"%s\"", cmd); return background_and_wait_for_errors(cmd); #else HANDLE hfile; hfile = CreateFileA(src, 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if(hfile == INVALID_HANDLE_VALUE) return -1; CloseHandle(hfile); return 0; #endif }
static int op_removesl(ops_t *ops, void *data, const char *src, const char *dst) { if(cfg.delete_prg[0] != '\0') { #ifndef _WIN32 char *escaped; char cmd[2*PATH_MAX + 1]; const int cancellable = (data == NULL); escaped = shell_like_escape(src, 0); if(escaped == NULL) { return -1; } snprintf(cmd, sizeof(cmd), "%s %s", cfg.delete_prg, escaped); free(escaped); LOG_INFO_MSG("Running trash command: \"%s\"", cmd); return background_and_wait_for_errors(cmd, cancellable); #else char cmd[PATH_MAX*2 + 1]; snprintf(cmd, sizeof(cmd), "%s \"%s\"", cfg.delete_prg, src); to_back_slash(cmd); return os_system(cmd); #endif } if(!cfg.use_system_calls) { #ifndef _WIN32 char *escaped; char cmd[16 + PATH_MAX]; int result; const int cancellable = data == NULL; escaped = shell_like_escape(src, 0); if(escaped == NULL) return -1; snprintf(cmd, sizeof(cmd), "rm -rf %s", escaped); LOG_INFO_MSG("Running rm command: \"%s\"", cmd); result = background_and_wait_for_errors(cmd, cancellable); free(escaped); return result; #else if(is_dir(src)) { char path[PATH_MAX]; int err; copy_str(path, sizeof(path), src); to_back_slash(path); wchar_t *const utf16_path = utf8_to_utf16(path); SHFILEOPSTRUCTW fo = { .hwnd = NULL, .wFunc = FO_DELETE, .pFrom = utf16_path, .pTo = NULL, .fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI, }; err = SHFileOperationW(&fo); log_msg("Error: %d", err); free(utf16_path); return err; } else { int ok; wchar_t *const utf16_path = utf8_to_utf16(src); DWORD attributes = GetFileAttributesW(utf16_path); if(attributes & FILE_ATTRIBUTE_READONLY) { SetFileAttributesW(utf16_path, attributes & ~FILE_ATTRIBUTE_READONLY); } ok = DeleteFileW(utf16_path); if(!ok) { LOG_WERROR(GetLastError()); } free(utf16_path); return !ok; } #endif }