29 #include <sys/types.h>
41 # include <shellapi.h>
42 # include <shobjidl.h>
45 # if defined(__APPLE__)
46 # include <CoreFoundation/CoreFoundation.h>
47 # include <objc/message.h>
48 # include <objc/runtime.h>
51 # include <sys/param.h>
52 # include <sys/wait.h>
69 int BLI_file_gzip(
const char *
from,
const char *to)
93 fprintf(stderr,
"Error reading file %s: %s.\n",
from, strerror(errno));
96 else if (readsize == 0) {
100 if (gzwrite(gzfile,
buffer, readsize) <= 0) {
102 fprintf(stderr,
"Error writing gz file %s: %s.\n", to, gzerror(gzfile, &
err));
120 int readsize,
size, alloc_size = 0;
122 const int chunk_size = 512 * 1024;
129 mem =
MEM_callocN(chunk_size,
"BLI_ungzip_to_mem");
130 alloc_size = chunk_size;
134 alloc_size += chunk_size;
137 readsize = gzread(gzfile, mem +
size, chunk_size);
152 else if (alloc_size !=
size) {
161 #define CHUNK (256 * 1024)
167 void *buf,
size_t len, FILE *
file,
size_t gz_stream_offset,
int compression_level)
172 unsigned char out[
CHUNK];
174 fseek(
file, gz_stream_offset, 0);
176 strm.zalloc = Z_NULL;
178 strm.opaque = Z_NULL;
179 ret = deflateInit(&strm, compression_level);
185 strm.next_in = (Bytef *)buf;
189 strm.avail_out =
CHUNK;
191 ret = deflate(&strm, flush);
192 if (
ret == Z_STREAM_ERROR) {
195 have =
CHUNK - strm.avail_out;
196 if (fwrite(out, 1, have,
file) != have || ferror(
file)) {
200 }
while (strm.avail_out == 0);
202 if (strm.avail_in != 0 ||
ret != Z_STREAM_END) {
207 return (
size_t)strm.total_out;
217 size_t chunk = 256 * 1024;
218 unsigned char in[
CHUNK];
220 fseek(
file, gz_stream_offset, 0);
222 strm.zalloc = Z_NULL;
224 strm.opaque = Z_NULL;
226 strm.next_in = Z_NULL;
227 ret = inflateInit(&strm);
233 strm.avail_in = fread(in, 1, chunk,
file);
241 strm.avail_out =
len;
242 strm.next_out = (Bytef *)buf + strm.total_out;
244 ret = inflate(&strm, Z_NO_FLUSH);
245 if (
ret == Z_STREAM_ERROR) {
248 }
while (strm.avail_out == 0);
250 }
while (
ret != Z_STREAM_END);
253 return (
size_t)strm.total_out;
272 else if (errno != ENOENT) {
284 writable =
BLI_access(parent, X_OK | W_OK) == 0;
324 static void callLocalErrorCallBack(
const char *
err)
329 FILE *
BLI_fopen(
const char *filename,
const char *mode)
333 return ufopen(filename, mode);
336 void BLI_get_short_name(
char short_name[256],
const char *filename)
338 wchar_t short_name_16[256];
343 GetShortPathNameW(filename_16, short_name_16, 256);
345 for (i = 0; i < 256; i++) {
346 short_name[i] = (char)short_name_16[i];
352 void *
BLI_gzopen(
const char *filename,
const char *mode)
359 if (mode[0] ==
'w') {
370 # if ZLIB_VERNUM >= 0x1270
373 gzfile = gzopen_w(filename_16, mode);
378 char short_name[256];
379 BLI_get_short_name(short_name, filename);
380 gzfile = gzopen(short_name, mode);
394 int BLI_access(
const char *filename,
int mode)
398 return uaccess(filename, mode);
401 static bool delete_soft(
const wchar_t *path_16,
const char **error_message)
408 HRESULT hr = CoInitializeEx(
NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
411 *error_message =
"Failed to initialize COM";
415 hr = CoCreateInstance(
416 &CLSID_FileOperation,
NULL, CLSCTX_ALL, &IID_IFileOperation, (
void **)&pfo);
418 *error_message =
"Failed to create FileOperation instance";
426 hr = pfo->lpVtbl->SetOperationFlags(pfo, FOF_ALLOWUNDO | FOF_SILENT | FOF_WANTNUKEWARNING);
429 *error_message =
"Failed to set operation flags";
433 hr = SHCreateItemFromParsingName(path_16,
NULL, &IID_IShellItem, (
void **)&pSI);
435 *error_message =
"Failed to parse path";
439 hr = pfo->lpVtbl->DeleteItem(pfo, pSI,
NULL);
441 *error_message =
"Failed to prepare delete operation";
445 hr = pfo->lpVtbl->PerformOperations(pfo);
448 *error_message =
"Failed to delete file or directory";
452 pfo->lpVtbl->Release(pfo);
459 static bool delete_unique(
const char *path,
const bool dir)
466 err = !RemoveDirectoryW(path_16);
468 printf(
"Unable to remove directory\n");
472 err = !DeleteFileW(path_16);
474 callLocalErrorCallBack(
"Unable to delete file");
483 static bool delete_recursive(
const char *dir)
504 if (delete_recursive(
path)) {
509 if (delete_unique(fl->
path,
false)) {
516 if (!
err && delete_unique(dir,
true)) {
535 err = delete_unique(
file, dir);
561 int BLI_move(
const char *
file,
const char *to)
580 err = !MoveFileW(file_16, str_16);
585 callLocalErrorCallBack(
"Unable to move file");
586 printf(
" Move from '%s' to '%s' failed\n",
file,
str);
612 err = !CopyFileW(file_16, str_16,
false);
617 callLocalErrorCallBack(
"Unable to copy file!");
618 printf(
" Copy from '%s' to '%s' failed\n",
file,
str);
625 int BLI_create_symlink(
const char *
file,
const char *to)
628 callLocalErrorCallBack(
"Linking files is unsupported on Windows");
651 if (isalpha(tmp[0]) && (tmp[1] ==
':') && tmp[2] ==
'\0') {
674 printf(
"Unable to create directory %s\n",
dirname);
716 size_t len = strlen(dir) + strlen(
file) + 1;
721 else if (*alloc_len <
len) {
759 char *from_path =
NULL, *to_path =
NULL;
761 size_t from_alloc_len = -1, to_alloc_len = -1;
762 int i, n = 0,
ret = 0;
780 if (callback_file !=
NULL) {
789 n = scandir(startfrom, &dirlist,
NULL, alphasort);
797 if (callback_dir_pre !=
NULL) {
798 ret = callback_dir_pre(
from, to);
811 for (i = 0; i < n; i++) {
830 lstat(filename, &st_dir);
831 is_dir =
S_ISDIR(st_dir.st_mode);
834 is_dir = (
dirent->d_type == DT_DIR);
840 from_path, to_path, callback_dir_pre, callback_file, callback_dir_post);
842 else if (callback_file !=
NULL) {
843 ret = callback_file(from_path, to_path);
857 if (callback_dir_post !=
NULL) {
858 ret = callback_dir_post(
from, to);
865 if (dirlist !=
NULL) {
866 for (i = 0; i < n; i++) {
871 if (from_path !=
NULL) {
874 if (to_path !=
NULL) {
914 Class NSAutoreleasePoolClass = objc_getClass(
"NSAutoreleasePool");
915 SEL allocSel = sel_registerName(
"alloc");
916 SEL initSel = sel_registerName(
"init");
917 id poolAlloc = ((
id(*)(Class, SEL))objc_msgSend)(NSAutoreleasePoolClass, allocSel);
918 id pool = ((
id(*)(
id, SEL))objc_msgSend)(poolAlloc, initSel);
920 Class NSStringClass = objc_getClass(
"NSString");
921 SEL stringWithUTF8StringSel = sel_registerName(
"stringWithUTF8String:");
922 id pathString = ((
id(*)(Class, SEL,
const char *))objc_msgSend)(
923 NSStringClass, stringWithUTF8StringSel,
file);
925 Class NSFileManagerClass = objc_getClass(
"NSFileManager");
926 SEL defaultManagerSel = sel_registerName(
"defaultManager");
927 id fileManager = ((
id(*)(Class, SEL))objc_msgSend)(NSFileManagerClass, defaultManagerSel);
929 Class NSURLClass = objc_getClass(
"NSURL");
930 SEL fileURLWithPathSel = sel_registerName(
"fileURLWithPath:");
931 id nsurl = ((
id(*)(Class, SEL,
id))objc_msgSend)(NSURLClass, fileURLWithPathSel, pathString);
933 SEL trashItemAtURLSel = sel_registerName(
"trashItemAtURL:resultingItemURL:error:");
934 BOOL deleteSuccessful = ((BOOL(*)(
id, SEL,
id,
id,
id))objc_msgSend)(
935 fileManager, trashItemAtURLSel, nsurl, nil, nil);
937 if (deleteSuccessful) {
941 *error_message =
"The Cocoa API call to delete file or directory failed";
944 SEL drainSel = sel_registerName(
"drain");
945 ((void (*)(
id, SEL))objc_msgSend)(
pool, drainSel);
953 const char *process_failed;
955 char *xdg_current_desktop = getenv(
"XDG_CURRENT_DESKTOP");
956 char *xdg_session_desktop = getenv(
"XDG_SESSION_DESKTOP");
958 if ((xdg_current_desktop !=
NULL &&
STREQ(xdg_current_desktop,
"KDE")) ||
959 (xdg_session_desktop !=
NULL &&
STREQ(xdg_session_desktop,
"KDE"))) {
960 args[0] =
"kioclient5";
965 process_failed =
"kioclient5 reported failure";
972 process_failed =
"gio reported failure";
981 waitpid(pid, &wstatus, 0);
983 if (!WIFEXITED(wstatus)) {
985 "Blender may not support moving files or directories to trash on your system.";
988 if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus)) {
989 *error_message = process_failed;
996 execvp(args[0], (
char **)args);
998 *error_message =
"Forking process failed.";
1007 return fopen(filename, mode);
1014 return gzopen(filename, mode);
1021 return open(filename,
oflag, pmode);
1028 return access(filename, mode);
1047 return remove(
file);
1068 struct stat st_a, st_b;
1070 if (lstat(path_a, &st_a)) {
1074 if (lstat(path_b, &st_b)) {
1078 return st_a.st_dev == st_b.st_dev && st_a.st_ino == st_b.st_ino;
1086 if (chown(
file, st->st_uid, st->st_gid)) {
1091 if (chmod(
file, st->st_mode)) {
1106 fprintf(stderr,
"%s: '%s' is the same as '%s'\n", __func__,
from, to);
1110 if (lstat(
from, &st)) {
1116 if (mkdir(to, st.st_mode)) {
1122 if (chown(to, st.st_uid, st.st_gid)) {
1132 FILE *from_stream, *to_stream;
1138 fprintf(stderr,
"%s: '%s' is the same as '%s'\n", __func__,
from, to);
1142 if (lstat(
from, &st)) {
1147 if (S_ISLNK(st.st_mode)) {
1154 if ((st.st_size + 1) <
sizeof(buf)) {
1159 link_buffer =
MEM_callocN(st.st_size + 2,
"copy_single_file link_buffer");
1163 link_len = readlink(
from, link_buffer, st.st_size + 1);
1174 link_buffer[link_len] =
'\0';
1176 if (symlink(link_buffer, to)) {
1190 if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) || S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
1192 if (mknod(to, st.st_mode, st.st_rdev)) {
1204 fprintf(stderr,
"Copying of this kind of files isn't supported yet\n");
1208 from_stream = fopen(
from,
"rb");
1214 to_stream = fopen(to,
"wb");
1217 fclose(from_stream);
1221 while ((
len = fread(buf, 1,
sizeof(buf), from_stream)) > 0) {
1222 fwrite(buf, 1,
len, to_stream);
1226 fclose(from_stream);
1237 static int move_callback_pre(
const char *
from,
const char *to)
1248 static int move_single_file(
const char *
from,
const char *to)
1261 int BLI_move(
const char *
file,
const char *to)
1277 if (!stat(to, &st)) {
1280 const char *filename;
1294 len = strlen(to) + strlen(filename) + 1;
1314 if (actual_to != to) {
1322 int BLI_create_symlink(
const char *
file,
const char *to)
1324 return symlink(to,
file);
1393 return rename(
from, to);
File and directory operations.
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void BLI_filelist_free(struct direntry *filelist, const unsigned int nrentries)
unsigned int BLI_filelist_dir_contents(const char *dir, struct direntry **r_filelist)
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Some types for dealing with directories.
void BLI_kdtree_nd_() free(KDTree *tree)
const char * BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
#define FILENAME_IS_CURRPAR(_n)
size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path_first,...) ATTR_NONNULL(1
void BLI_path_slash_rstrip(char *string) ATTR_NONNULL()
int BLI_path_slash_ensure(char *string) ATTR_NONNULL()
const char * BLI_path_slash_rfind(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Compatibility-like things for windows.
const char * dirname(char *path)
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
ATTR_WARN_UNUSED_RESULT const BMFlagLayer const short oflag
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static int set_permissions(const char *file, const struct stat *st)
int BLI_delete_soft(const char *file, const char **error_message)
char * BLI_file_ungzip_to_mem(const char *from_file, int *r_size)
FILE * BLI_fopen(const char *filename, const char *mode)
static bool check_the_same(const char *path_a, const char *path_b)
size_t BLI_ungzip_file_to_mem_at_pos(void *buf, size_t len, FILE *file, size_t gz_stream_offset)
int BLI_open(const char *filename, int oflag, int pmode)
bool BLI_file_is_writable(const char *filename)
int BLI_access(const char *filename, int mode)
int(* RecursiveOp_Callback)(const char *from, const char *to)
static const char * check_destination(const char *file, const char *to)
void * BLI_gzopen(const char *filename, const char *mode)
int BLI_copy(const char *file, const char *to)
bool BLI_dir_create_recursive(const char *dirname)
static char * strip_last_slash(const char *dir)
static int copy_single_file(const char *from, const char *to)
static int delete_single_file(const char *from, const char *UNUSED(to))
static void join_dirfile_alloc(char **dst, size_t *alloc_len, const char *dir, const char *file)
bool BLI_file_touch(const char *file)
static int recursive_operation(const char *startfrom, const char *startto, RecursiveOp_Callback callback_dir_pre, RecursiveOp_Callback callback_file, RecursiveOp_Callback callback_dir_post)
size_t BLI_gzip_mem_to_file_at_pos(void *buf, size_t len, FILE *file, size_t gz_stream_offset, int compression_level)
@ RecursiveOp_Callback_StopRecurs
@ RecursiveOp_Callback_OK
@ RecursiveOp_Callback_Error
static int delete_callback_post(const char *from, const char *UNUSED(to))
int BLI_rename(const char *from, const char *to)
static int delete_soft(const char *file, const char **error_message)
static int copy_callback_pre(const char *from, const char *to)
int BLI_delete(const char *file, bool dir, bool recursive)
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
void(* MEM_freeN)(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_mallocN)(size_t len, const char *str)
int umkdir(const char *pathname)
FILE * ufopen(const char *filename, const char *mode)
int uopen(const char *filename, int oflag, int pmode)
int uaccess(const char *filename, int mode)
int urename(const char *oldname, const char *newname)
#define UTF16_ENCODE(in8str)
#define UTF16_UN_ENCODE(in8str)