~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

Viewing changes to source/blender/blenlib/intern/fileops.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2012-07-23 08:54:18 UTC
  • mfrom: (14.2.16 sid)
  • mto: (14.2.19 sid)
  • mto: This revision was merged to the branch mainline in revision 42.
  • Revision ID: package-import@ubuntu.com-20120723085418-9foz30v6afaf5ffs
Tags: 2.63a-2
* debian/: Cycles support added (Closes: #658075)
  For now, this top feature has been enabled only
  on [any-amd64 any-i386] architectures because
  of OpenImageIO failing on all others
* debian/: scripts installation path changed
  from /usr/lib to /usr/share:
  + debian/patches/: patchset re-worked for path changing
  + debian/control: "Breaks" field added on yafaray-exporter

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * $Id: fileops.c 30446 2010-07-17 18:08:14Z campbellbarton $
3
 
 *
4
2
 * ***** BEGIN GPL LICENSE BLOCK *****
5
3
 *
6
4
 * This program is free software; you can redistribute it and/or
27
25
 * ***** END GPL LICENSE BLOCK *****
28
26
 */
29
27
 
 
28
/** \file blender/blenlib/intern/fileops.c
 
29
 *  \ingroup bli
 
30
 */
 
31
 
 
32
 
30
33
#include <string.h>
31
34
#include <stdio.h>
32
35
 
40
43
 
41
44
#ifdef WIN32
42
45
#include <io.h>
43
 
#include "BLI_winstuff.h"
 
46
#  include "BLI_winstuff.h"
 
47
#  include "BLI_callbacks.h"
 
48
#  include "utf_winfunc.h"
 
49
#  include "utfconv.h"
44
50
#else
45
 
#include <unistd.h> // for read close
46
 
#include <sys/param.h>
 
51
#  include <unistd.h> // for read close
 
52
#  include <sys/param.h>
 
53
#  include <dirent.h>
 
54
#  include <unistd.h>
 
55
#  include <sys/stat.h>
47
56
#endif
48
57
 
 
58
#include "MEM_guardedalloc.h"
49
59
 
50
60
#include "BLI_blenlib.h"
 
61
#include "BLI_utildefines.h"
51
62
 
52
63
#include "BKE_utildefines.h"
53
64
 
54
65
#include "BLO_sys_types.h" // for intptr_t support
55
66
 
56
 
/* implementations: */
57
 
char *first_slash(char *string) {
58
 
        char *ffslash, *fbslash;
59
 
        
60
 
        ffslash= strchr(string, '/');   
61
 
        fbslash= strchr(string, '\\');
62
 
        
63
 
        if (!ffslash) return fbslash;
64
 
        else if (!fbslash) return ffslash;
65
 
        
66
 
        if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
67
 
        else return fbslash;
68
 
}
69
 
 
70
 
char *BLI_last_slash(const char *string) {
71
 
        char *lfslash, *lbslash;
72
 
        
73
 
        lfslash= strrchr(string, '/');  
74
 
        lbslash= strrchr(string, '\\');
75
 
 
76
 
        if (!lfslash) return lbslash; 
77
 
        else if (!lbslash) return lfslash;
78
 
        
79
 
        if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
80
 
        else return lfslash;
81
 
}
82
 
 
83
 
/* adds a slash if there isnt one there already */
84
 
int BLI_add_slash(char *string) {
85
 
        int len = strlen(string);
86
 
#ifdef WIN32
87
 
        if (len==0 || string[len-1]!='\\') {
88
 
                string[len] = '\\';
89
 
                string[len+1] = '\0';
90
 
                return len+1;
91
 
        }
92
 
#else
93
 
        if (len==0 || string[len-1]!='/') {
94
 
                string[len] = '/';
95
 
                string[len+1] = '\0';
96
 
                return len+1;
97
 
        }
98
 
#endif
99
 
        return len;
100
 
}
101
 
 
102
 
/* removes a slash if there is one */
103
 
void BLI_del_slash(char *string) {
104
 
        int len = strlen(string);
105
 
        while (len) {
106
 
#ifdef WIN32
107
 
                if (string[len-1]=='\\') {
108
 
#else
109
 
                if (string[len-1]=='/') {
110
 
#endif
111
 
                        string[len-1] = '\0';
112
 
                        len--;
113
 
                } else {
114
 
                        break;
115
 
                }
116
 
        }
117
 
}
118
67
 
119
68
/* gzip the file in from and write it to "to". 
120
 
 return -1 if zlib fails, -2 if the originating file does not exist
121
 
 note: will remove the "from" file
122
 
  */
123
 
int BLI_gzip(char *from, char *to) {
 
69
 * return -1 if zlib fails, -2 if the originating file does not exist
 
70
 * note: will remove the "from" file
 
71
 */
 
72
int BLI_file_gzip(const char *from, const char *to)
 
73
{
124
74
        char buffer[10240];
125
75
        int file;
126
76
        int readsize = 0;
127
77
        int rval= 0, err;
128
78
        gzFile gzfile;
129
 
        
130
 
        gzfile = gzopen(to, "wb"); 
131
 
        if(gzfile == NULL)
 
79
 
 
80
        /* level 1 is very close to 3 (the default) in terms of file size,
 
81
         * but about twice as fast, best use for speedy saving - campbell */
 
82
        gzfile = BLI_gzopen(to, "wb1");
 
83
        if (gzfile == NULL)
132
84
                return -1;
133
 
        
134
 
        file = open(from, O_BINARY|O_RDONLY);
135
 
        if(file < 0)
 
85
        file = BLI_open(from, O_BINARY|O_RDONLY,0);
 
86
        if (file < 0)
136
87
                return -2;
137
88
 
138
 
        while(1) {
139
 
                readsize = read(file, buffer, 10240);
 
89
        while (1) {
 
90
                readsize = read(file, buffer, sizeof(buffer));
140
91
 
141
 
                if(readsize < 0) {
 
92
                if (readsize < 0) {
142
93
                        rval= -2; /* error happened in reading */
143
94
                        fprintf(stderr, "Error reading file %s: %s.\n", from, strerror(errno));
144
95
                        break;
145
96
                }
146
 
                else if(readsize == 0)
 
97
                else if (readsize == 0)
147
98
                        break; /* done reading */
148
99
                
149
 
                if(gzwrite(gzfile, buffer, readsize) <= 0) {
 
100
                if (gzwrite(gzfile, buffer, readsize) <= 0) {
150
101
                        rval= -1; /* error happened in writing */
151
102
                        fprintf(stderr, "Error writing gz file %s: %s.\n", to, gzerror(gzfile, &err));
152
103
                        break;
159
110
        return rval;
160
111
}
161
112
 
 
113
/* gzip the file in from_file and write it to memery to_mem, at most size bytes.
 
114
 * return the unziped size
 
115
 */
 
116
char *BLI_file_ungzip_to_mem(const char *from_file, int *size_r)
 
117
{
 
118
        gzFile gzfile;
 
119
        int readsize, size, alloc_size=0;
 
120
        char *mem= NULL;
 
121
        const int chunk_size= 512*1024;
 
122
 
 
123
        size= 0;
 
124
 
 
125
        gzfile = BLI_gzopen( from_file, "rb" );
 
126
        for (;;) {
 
127
                if (mem==NULL) {
 
128
                        mem= MEM_callocN(chunk_size, "BLI_ungzip_to_mem");
 
129
                        alloc_size= chunk_size;
 
130
                }
 
131
                else {
 
132
                        mem= MEM_reallocN(mem, size+chunk_size);
 
133
                        alloc_size+= chunk_size;
 
134
                }
 
135
 
 
136
                readsize= gzread(gzfile, mem+size, chunk_size);
 
137
                if (readsize>0) {
 
138
                        size+= readsize;
 
139
                }
 
140
                else break;
 
141
        }
 
142
 
 
143
        if (size==0) {
 
144
                MEM_freeN(mem);
 
145
                mem= NULL;
 
146
        }
 
147
        else if (alloc_size!=size)
 
148
                mem= MEM_reallocN(mem, size);
 
149
 
 
150
        *size_r= size;
 
151
 
 
152
        return mem;
 
153
}
 
154
 
 
155
/* read the file in from_file and write it to memory to_mem, at most size bytes.
 
156
   return the file size
 
157
  */
 
158
char *BLI_file_to_mem(const char *from_file, int *size_r) {
 
159
 
 
160
    FILE * file;
 
161
    int readsize, size, alloc_size=0;
 
162
    char *mem= NULL;
 
163
    const int chunk_size= 512*1024;
 
164
 
 
165
    size= 0;
 
166
 
 
167
    file = fopen( from_file, "rb" );
 
168
 
 
169
    for(;;) {
 
170
        if(mem==NULL) {
 
171
            mem= MEM_callocN(chunk_size, "BLI_file_to_mem");
 
172
            alloc_size= chunk_size;
 
173
        } else {
 
174
            mem= MEM_reallocN(mem, size+chunk_size);
 
175
            alloc_size+= chunk_size;
 
176
        }
 
177
 
 
178
        readsize= fread(mem+size, chunk_size,1,file);
 
179
        if(readsize>0) {
 
180
            size+= readsize;
 
181
        }
 
182
        else break;
 
183
    }
 
184
 
 
185
    if(size==0) {
 
186
        MEM_freeN(mem);
 
187
        mem= NULL;
 
188
    }
 
189
    else if(alloc_size!=size)
 
190
        mem= MEM_reallocN(mem, size);
 
191
 
 
192
    fclose(file);
 
193
    *size_r= size;
 
194
 
 
195
    return mem;
 
196
 
 
197
}
 
198
 
162
199
/* return 1 when file can be written */
163
 
int BLI_is_writable(char *filename)
 
200
int BLI_file_is_writable(const char *filename)
164
201
{
165
202
        int file;
166
203
        
167
204
        /* first try to open without creating */
168
 
        file = open(filename, O_BINARY | O_RDWR, 0666);
 
205
        file = BLI_open(filename, O_BINARY | O_RDWR, 0666);
169
206
        
170
207
        if (file < 0) {
171
208
                /* now try to open and create. a test without actually
172
209
                 * creating a file would be nice, but how? */
173
 
                file = open(filename, O_BINARY | O_RDWR | O_CREAT, 0666);
 
210
                file = BLI_open(filename, O_BINARY | O_RDWR | O_CREAT, 0666);
174
211
                
175
 
                if(file < 0) {
 
212
                if (file < 0) {
176
213
                        return 0;
177
214
                }
178
215
                else {
188
225
        }
189
226
}
190
227
 
191
 
int BLI_touch(const char *file)
 
228
int BLI_file_touch(const char *file)
192
229
{
193
 
   FILE *f = fopen(file,"r+b");
194
 
   if (f != NULL) {
 
230
        FILE *f = BLI_fopen(file, "r+b");
 
231
        if (f != NULL) {
195
232
                char c = getc(f);
196
233
                rewind(f);
197
 
                putc(c,f);
198
 
        } else {
199
 
           f = fopen(file,"wb");
 
234
                putc(c, f);
 
235
        }
 
236
        else {
 
237
                f = BLI_fopen(file, "wb");
200
238
        }
201
239
        if (f) {
202
240
                fclose(f);
205
243
        return 0;
206
244
}
207
245
 
208
 
int BLI_exists(char *file) {
209
 
        return BLI_exist(file);
210
 
}
211
 
 
212
246
#ifdef WIN32
213
247
 
214
 
static char str[MAXPATHLEN+12];
215
 
 
216
 
int BLI_delete(char *file, int dir, int recursive) {
 
248
static char str[MAXPATHLEN + 12];
 
249
 
 
250
FILE *BLI_fopen(const char *filename, const char *mode)
 
251
{
 
252
        return ufopen(filename, mode);
 
253
}
 
254
 
 
255
void *BLI_gzopen(const char *filename, const char *mode)
 
256
{
 
257
        gzFile gzfile;
 
258
 
 
259
        if (!filename || !mode) {
 
260
                return 0;
 
261
        }
 
262
        else {
 
263
                wchar_t short_name_16[256];
 
264
                char short_name[256];
 
265
                int i = 0;
 
266
 
 
267
                /* xxx Creates file before transcribing the path */
 
268
                if (mode[0] == 'w')
 
269
                        fclose(ufopen(filename,"a"));
 
270
 
 
271
                UTF16_ENCODE(filename);
 
272
 
 
273
                GetShortPathNameW(filename_16,short_name_16, 256);
 
274
 
 
275
                for (i = 0; i < 256; i++) {
 
276
                        short_name[i] = short_name_16[i];
 
277
                }
 
278
 
 
279
                gzfile = gzopen(short_name,mode);
 
280
 
 
281
                UTF16_UN_ENCODE(filename);
 
282
        }
 
283
 
 
284
        return gzfile;
 
285
}
 
286
 
 
287
int   BLI_open(const char *filename, int oflag, int pmode)
 
288
{
 
289
        return uopen(filename, oflag, pmode);
 
290
}
 
291
 
 
292
int BLI_delete(const char *file, int dir, int recursive)
 
293
{
217
294
        int err;
 
295
        
 
296
        UTF16_ENCODE(file);
218
297
 
219
298
        if (recursive) {
220
299
                callLocalErrorCallBack("Recursive delete is unsupported on Windows");
221
300
                err= 1;
222
 
        } else if (dir) {
223
 
                err= !RemoveDirectory(file);
 
301
        }
 
302
        else if (dir) {
 
303
                err= !RemoveDirectoryW(file_16);
224
304
                if (err) printf ("Unable to remove directory");
225
 
        } else {
226
 
                err= !DeleteFile(file);
 
305
        }
 
306
        else {
 
307
                err= !DeleteFileW(file_16);
227
308
                if (err) callLocalErrorCallBack("Unable to delete file");
228
309
        }
229
310
 
 
311
        UTF16_UN_ENCODE(file);
 
312
 
230
313
        return err;
231
314
}
232
315
 
233
 
int BLI_move(char *file, char *to) {
 
316
int BLI_move(const char *file, const char *to)
 
317
{
234
318
        int err;
235
319
 
236
320
        // windows doesn't support moveing to a directory
237
321
        // it has to be 'mv filename filename' and not
238
322
        // 'mv filename destdir'
239
323
 
240
 
        strcpy(str, to);
 
324
        BLI_strncpy(str, to, sizeof(str));
241
325
        // points 'to' to a directory ?
242
326
        if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
243
327
                if (BLI_last_slash(file) != NULL) {
244
328
                        strcat(str, BLI_last_slash(file) + 1);
245
329
                }
246
330
        }
 
331
        
 
332
        UTF16_ENCODE(file);
 
333
        UTF16_ENCODE(str);
 
334
        err= !MoveFileW(file_16, str_16);
 
335
        UTF16_UN_ENCODE(str);
 
336
        UTF16_UN_ENCODE(file);
247
337
 
248
 
        err= !MoveFile(file, str);
249
338
        if (err) {
250
339
                callLocalErrorCallBack("Unable to move file");
251
340
                printf(" Move from '%s' to '%s' failed\n", file, str);
255
344
}
256
345
 
257
346
 
258
 
int BLI_copy_fileops(char *file, char *to) {
 
347
int BLI_copy(const char *file, const char *to)
 
348
{
259
349
        int err;
260
350
 
261
351
        // windows doesn't support copying to a directory
262
352
        // it has to be 'cp filename filename' and not
263
353
        // 'cp filename destdir'
264
354
 
265
 
        strcpy(str, to);
 
355
        BLI_strncpy(str, to, sizeof(str));
266
356
        // points 'to' to a directory ?
267
357
        if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
268
358
                if (BLI_last_slash(file) != NULL) {
270
360
                }
271
361
        }
272
362
 
273
 
        err= !CopyFile(file,str,FALSE);
274
 
        
 
363
        UTF16_ENCODE(file);
 
364
        UTF16_ENCODE(str);
 
365
        err = !CopyFileW(file_16, str_16, FALSE);
 
366
        UTF16_UN_ENCODE(str);
 
367
        UTF16_UN_ENCODE(file);
 
368
 
275
369
        if (err) {
276
370
                callLocalErrorCallBack("Unable to copy file!");
277
371
                printf(" Copy from '%s' to '%s' failed\n", file, str);
280
374
        return err;
281
375
}
282
376
 
283
 
int BLI_link(char *file, char *to) {
 
377
int BLI_create_symlink(const char *file, const char *to)
 
378
{
284
379
        callLocalErrorCallBack("Linking files is unsupported on Windows");
285
 
        
 
380
        (void)file;
 
381
        (void)to;
286
382
        return 1;
287
383
}
288
384
 
289
 
void BLI_recurdir_fileops(char *dirname) {
 
385
void BLI_dir_create_recursive(const char *dirname)
 
386
{
290
387
        char *lslash;
291
388
        char tmp[MAXPATHLEN];
292
389
        
293
 
        // First remove possible slash at the end of the dirname.
294
 
        // This routine otherwise tries to create
295
 
        // blah1/blah2/ (with slash) after creating
296
 
        // blah1/blah2 (without slash)
 
390
        /* First remove possible slash at the end of the dirname.
 
391
         * This routine otherwise tries to create
 
392
         * blah1/blah2/ (with slash) after creating
 
393
         * blah1/blah2 (without slash) */
297
394
 
298
 
        strcpy(tmp, dirname);
 
395
        BLI_strncpy(tmp, dirname, sizeof(tmp));
299
396
        lslash= BLI_last_slash(tmp);
300
 
 
 
397
        
301
398
        if (lslash == tmp + strlen(tmp) - 1) {
302
399
                *lslash = 0;
303
400
        }
304
401
        
305
402
        if (BLI_exists(tmp)) return;
306
 
                
 
403
 
307
404
        lslash= BLI_last_slash(tmp);
308
405
        if (lslash) {
309
 
                        /* Split about the last slash and recurse */    
 
406
                /* Split about the last slash and recurse */
310
407
                *lslash = 0;
311
 
                BLI_recurdir_fileops(tmp);
 
408
                BLI_dir_create_recursive(tmp);
312
409
        }
313
410
        
314
 
        if(dirname[0]) /* patch, this recursive loop tries to create a nameless directory */
315
 
                if (!CreateDirectory(dirname, NULL))
316
 
                        callLocalErrorCallBack("Unable to create directory\n");
 
411
        if (dirname[0]) /* patch, this recursive loop tries to create a nameless directory */
 
412
                if (umkdir(dirname)==-1)
 
413
                        printf("Unable to create directory %s\n",dirname);
317
414
}
318
415
 
319
 
int BLI_rename(char *from, char *to) {
 
416
int BLI_rename(const char *from, const char *to)
 
417
{
320
418
        if (!BLI_exists(from)) return 0;
321
419
 
322
420
        /* make sure the filenames are different (case insensitive) before removing */
323
421
        if (BLI_exists(to) && BLI_strcasecmp(from, to))
324
 
                if(BLI_delete(to, 0, 0)) return 1;
325
 
 
326
 
        return rename(from, to);
327
 
}
328
 
 
329
 
#else /* The weirdo UNIX world */
330
 
 
331
 
/*
332
 
 * but the UNIX world is tied to the interface, and the system
333
 
 * timer, and... We implement a callback mechanism. The system will
334
 
 * have to initialise the callback before the functions will work!
335
 
 * */
336
 
static char str[MAXPATHLEN+12];
337
 
 
338
 
int BLI_delete(char *file, int dir, int recursive) 
339
 
{
340
 
        if(strchr(file, '"')) {
 
422
                if (BLI_delete(to, 0, 0)) return 1;
 
423
        
 
424
        return urename(from, to);
 
425
}
 
426
 
 
427
#else /* The UNIX world */
 
428
 
 
429
enum {
 
430
        /* operation succeeded succeeded */
 
431
        recursiveOp_Callback_OK = 0,
 
432
 
 
433
        /* operation requested not to perform recursive digging for current path */
 
434
        recursiveOp_Callback_StopRecurs = 1,
 
435
 
 
436
        /* error occured in callback and recursive walking should stop immediately */
 
437
        recursiveOp_Callback_Error = 2
 
438
} recuresiveOp_Callback_Result;
 
439
 
 
440
typedef int (*recursiveOp_Callback) (const char *from, const char *to);
 
441
 
 
442
/* appending of filename to dir (ensures for buffer size before appending) */
 
443
static void join_dirfile_alloc(char **dst, size_t *alloc_len, const char *dir, const char *file)
 
444
{
 
445
        size_t len = strlen(dir) + strlen(file) + 1;
 
446
 
 
447
        if (!*dst)
 
448
                *dst = MEM_callocN(len + 1, "join_dirfile_alloc path");
 
449
        else if (*alloc_len < len)
 
450
                *dst = MEM_reallocN(*dst, len + 1);
 
451
 
 
452
        *alloc_len = len;
 
453
 
 
454
        BLI_join_dirfile(*dst, len + 1, dir, file);
 
455
}
 
456
 
 
457
static char *strip_last_slash(const char *dir)
 
458
{
 
459
        char *result = BLI_strdup(dir);
 
460
        BLI_del_slash(result);
 
461
 
 
462
        return result;
 
463
}
 
464
 
 
465
static int recursive_operation(const char *startfrom, const char *startto, recursiveOp_Callback callback_dir_pre,
 
466
                               recursiveOp_Callback callback_file, recursiveOp_Callback callback_dir_post)
 
467
{
 
468
        struct dirent **dirlist;
 
469
        struct stat st;
 
470
        char *from = NULL, *to = NULL;
 
471
        char *from_path = NULL, *to_path = NULL;
 
472
        size_t from_alloc_len = -1, to_alloc_len = -1;
 
473
        int i, n, ret = 0;
 
474
 
 
475
        /* ensure there's no trailing slash in file path */
 
476
        from = strip_last_slash(startfrom);
 
477
        if (startto)
 
478
                to = strip_last_slash(startto);
 
479
 
 
480
        ret = lstat(from, &st);
 
481
        if (ret < 0) {
 
482
                /* source wasn't found, nothing to operate with */
 
483
                return ret;
 
484
        }
 
485
 
 
486
        if (!S_ISDIR(st.st_mode)) {
 
487
                /* source isn't a directory, can't do recursive walking for it,
 
488
                 * so just call file callback and leave */
 
489
                if (callback_file) {
 
490
                        ret = callback_file(from, to);
 
491
 
 
492
                        if (ret != recursiveOp_Callback_OK)
 
493
                                ret = -1;
 
494
                }
 
495
 
 
496
                MEM_freeN(from);
 
497
                if (to) MEM_freeN(to);
 
498
 
 
499
                return ret;
 
500
        }
 
501
 
 
502
 
 
503
        n = scandir(startfrom, &dirlist, 0, alphasort);
 
504
        if (n < 0) {
 
505
                /* error opening directory for listing */
 
506
                perror("scandir");
 
507
 
 
508
                MEM_freeN(from);
 
509
                if (to) MEM_freeN(to);
 
510
 
 
511
                return -1;
 
512
        }
 
513
 
 
514
        if (callback_dir_pre) {
 
515
                /* call pre-recursive walking directory callback */
 
516
                ret = callback_dir_pre(from, to);
 
517
 
 
518
                if (ret != recursiveOp_Callback_OK) {
 
519
                        MEM_freeN(from);
 
520
                        if (to) free(to);
 
521
 
 
522
                        if (ret == recursiveOp_Callback_StopRecurs) {
 
523
                                /* callback requested not to perform recursive walking, not an error */
 
524
                                return 0;
 
525
                        }
 
526
 
 
527
                        return -1;
 
528
                }
 
529
        }
 
530
 
 
531
        for (i = 0; i < n; i++) {
 
532
                struct dirent *dirent = dirlist[i];
 
533
 
 
534
                if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) {
 
535
                        free(dirent);
 
536
                        continue;
 
537
                }
 
538
 
 
539
                join_dirfile_alloc(&from_path, &from_alloc_len, from, dirent->d_name);
 
540
 
 
541
                if (to)
 
542
                        join_dirfile_alloc(&to_path, &to_alloc_len, to, dirent->d_name);
 
543
 
 
544
                if (dirent->d_type == DT_DIR) {
 
545
                        /* recursively dig into a folder */
 
546
                        ret = recursive_operation(from_path, to_path, callback_dir_pre, callback_file, callback_dir_post);
 
547
                }
 
548
                else if (callback_file) {
 
549
                        /* call file callback for current path */
 
550
                        ret = callback_file(from_path, to_path);
 
551
                        if (ret != recursiveOp_Callback_OK)
 
552
                                ret = -1;
 
553
                }
 
554
 
 
555
                if (ret != 0) {
 
556
                        while (i < n)
 
557
                                free(dirlist[i]);
 
558
                        break;
 
559
                }
 
560
        }
 
561
 
 
562
        free(dirlist);
 
563
 
 
564
        if (ret == 0) {
 
565
                if (callback_dir_post) {
 
566
                        /* call post-recursive directory callback */
 
567
                        ret = callback_dir_post(from, to);
 
568
                        if (ret != recursiveOp_Callback_OK)
 
569
                                ret = -1;
 
570
                }
 
571
        }
 
572
 
 
573
        if (from_path) MEM_freeN(from_path);
 
574
        if (to_path) MEM_freeN(to_path);
 
575
 
 
576
        MEM_freeN(from);
 
577
        if (to) MEM_freeN(to);
 
578
 
 
579
        return ret;
 
580
}
 
581
 
 
582
static int delete_callback_post(const char *from, const char *UNUSED(to))
 
583
{
 
584
        if (rmdir(from)) {
 
585
                perror("rmdir");
 
586
 
 
587
                return recursiveOp_Callback_Error;
 
588
        }
 
589
 
 
590
        return recursiveOp_Callback_OK;
 
591
}
 
592
 
 
593
static int delete_single_file(const char *from, const char *UNUSED(to))
 
594
{
 
595
        if (unlink(from)) {
 
596
                perror("unlink");
 
597
 
 
598
                return recursiveOp_Callback_Error;
 
599
        }
 
600
 
 
601
        return recursiveOp_Callback_OK;
 
602
}
 
603
 
 
604
FILE *BLI_fopen(const char *filename, const char *mode)
 
605
{
 
606
        return fopen(filename, mode);
 
607
}
 
608
 
 
609
void *BLI_gzopen(const char *filename, const char *mode)
 
610
{
 
611
        return gzopen(filename, mode);
 
612
}
 
613
 
 
614
int BLI_open(const char *filename, int oflag, int pmode)
 
615
{
 
616
        return open(filename, oflag, pmode);
 
617
}
 
618
 
 
619
int BLI_delete(const char *file, int dir, int recursive) 
 
620
{
 
621
        if (strchr(file, '"')) {
341
622
                printf("Error: not deleted file %s because of quote!\n", file);
342
623
        }
343
624
        else {
344
625
                if (recursive) {
345
 
                        sprintf(str, "/bin/rm -rf \"%s\"", file);
346
 
                        return system(str);
 
626
                        return recursive_operation(file, NULL, NULL, delete_single_file, delete_callback_post);
347
627
                }
348
628
                else if (dir) {
349
 
                        sprintf(str, "/bin/rmdir \"%s\"", file);
350
 
                        return system(str);
 
629
                        return rmdir(file);
351
630
                }
352
631
                else {
353
 
                        return remove(file); //sprintf(str, "/bin/rm -f \"%s\"", file);
 
632
                        return remove(file); //BLI_snprintf(str, sizeof(str), "/bin/rm -f \"%s\"", file);
354
633
                }
355
634
        }
356
635
        return -1;
357
636
}
358
637
 
359
 
int BLI_move(char *file, char *to) {
360
 
        sprintf(str, "/bin/mv -f \"%s\" \"%s\"", file, to);
361
 
 
362
 
        return system(str);
363
 
}
364
 
 
365
 
int BLI_copy_fileops(char *file, char *to) {
366
 
        sprintf(str, "/bin/cp -rf \"%s\" \"%s\"", file, to);
367
 
 
368
 
        return system(str);
369
 
}
370
 
 
371
 
int BLI_link(char *file, char *to) {
372
 
        sprintf(str, "/bin/ln -f \"%s\" \"%s\"", file, to);
373
 
        
374
 
        return system(str);
375
 
}
376
 
 
377
 
void BLI_recurdir_fileops(char *dirname) {
 
638
static int check_the_same(const char *path_a, const char *path_b)
 
639
{
 
640
        struct stat st_a, st_b;
 
641
 
 
642
        if (lstat(path_a, &st_a))
 
643
                return 0;
 
644
 
 
645
        if (lstat(path_b, &st_b))
 
646
                return 0;
 
647
 
 
648
        return st_a.st_dev == st_b.st_dev && st_a.st_ino == st_b.st_ino;
 
649
}
 
650
 
 
651
static int set_permissions(const char *file, struct stat *st)
 
652
{
 
653
        if (chown(file, st->st_uid, st->st_gid)) {
 
654
                perror("chown");
 
655
                return -1;
 
656
        }
 
657
 
 
658
        if (chmod(file, st->st_mode)) {
 
659
                perror("chmod");
 
660
                return -1;
 
661
        }
 
662
 
 
663
        return 0;
 
664
}
 
665
 
 
666
/* pre-recursive callback for copying operation
 
667
 * creates a destination directory where all source content fill be copied to */
 
668
static int copy_callback_pre(const char *from, const char *to)
 
669
{
 
670
        struct stat st;
 
671
 
 
672
        if (check_the_same(from, to)) {
 
673
                fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to);
 
674
                return recursiveOp_Callback_Error;
 
675
        }
 
676
 
 
677
        if (lstat(from, &st)) {
 
678
                perror("stat");
 
679
                return recursiveOp_Callback_Error;
 
680
        }
 
681
 
 
682
        /* create a directory */
 
683
        if (mkdir(to, st.st_mode)) {
 
684
                perror("mkdir");
 
685
                return recursiveOp_Callback_Error;
 
686
        }
 
687
 
 
688
        /* set proper owner and group on new directory */
 
689
        if (chown(to, st.st_uid, st.st_gid)) {
 
690
                perror("chown");
 
691
                return recursiveOp_Callback_Error;
 
692
        }
 
693
 
 
694
        return recursiveOp_Callback_OK;
 
695
}
 
696
 
 
697
static int copy_single_file(const char *from, const char *to)
 
698
{
 
699
        FILE *from_stream, *to_stream;
 
700
        struct stat st;
 
701
        char buf[4096];
 
702
        size_t len;
 
703
 
 
704
        if (check_the_same(from, to)) {
 
705
                fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to);
 
706
                return recursiveOp_Callback_Error;
 
707
        }
 
708
 
 
709
        if (lstat(from, &st)) {
 
710
                perror("lstat");
 
711
                return recursiveOp_Callback_Error;
 
712
        }
 
713
 
 
714
        if (S_ISLNK(st.st_mode)) {
 
715
                /* symbolic links should be copied in special way */
 
716
                char *link_buffer;
 
717
                int need_free;
 
718
                ssize_t link_len;
 
719
 
 
720
                /* get large enough buffer to read link content */
 
721
                if (st.st_size < sizeof(buf)) {
 
722
                        link_buffer = buf;
 
723
                        need_free = 0;
 
724
                }
 
725
                else {
 
726
                        link_buffer = MEM_callocN(st.st_size+2, "copy_single_file link_buffer");
 
727
                        need_free = 1;
 
728
                }
 
729
 
 
730
                link_len = readlink(from, link_buffer, st.st_size+1);
 
731
                if (link_len < 0) {
 
732
                        perror("readlink");
 
733
 
 
734
                        if (need_free) MEM_freeN(link_buffer);
 
735
 
 
736
                        return recursiveOp_Callback_Error;
 
737
                }
 
738
 
 
739
                link_buffer[link_len] = 0;
 
740
 
 
741
                if (symlink(link_buffer, to)) {
 
742
                        perror("symlink");
 
743
                        if (need_free) MEM_freeN(link_buffer);
 
744
                        return recursiveOp_Callback_Error;
 
745
                }
 
746
 
 
747
                if (need_free)
 
748
                        MEM_freeN(link_buffer);
 
749
 
 
750
                return recursiveOp_Callback_OK;
 
751
        }
 
752
        else if (S_ISCHR (st.st_mode) ||
 
753
                S_ISBLK (st.st_mode) ||
 
754
                S_ISFIFO (st.st_mode) ||
 
755
                S_ISSOCK (st.st_mode))
 
756
        {
 
757
                /* copy special type of file */
 
758
                if (mknod(to, st.st_mode, st.st_rdev)) {
 
759
                        perror("mknod");
 
760
                        return recursiveOp_Callback_Error;
 
761
                }
 
762
 
 
763
                if (set_permissions(to, &st))
 
764
                        return recursiveOp_Callback_Error;
 
765
 
 
766
                return recursiveOp_Callback_OK;
 
767
        }
 
768
        else if (!S_ISREG(st.st_mode)) {
 
769
                fprintf(stderr, "Copying of this kind of files isn't supported yet\n");
 
770
                return recursiveOp_Callback_Error;
 
771
        }
 
772
 
 
773
        from_stream = fopen(from, "rb");
 
774
        if (!from_stream) {
 
775
                perror("fopen");
 
776
                return recursiveOp_Callback_Error;
 
777
        }
 
778
 
 
779
        to_stream = fopen(to, "wb");
 
780
        if (!to_stream) {
 
781
                perror("fopen");
 
782
                fclose(from_stream);
 
783
                return recursiveOp_Callback_Error;
 
784
        }
 
785
 
 
786
        while ((len = fread(buf, 1, sizeof(buf), from_stream)) > 0) {
 
787
                fwrite(buf, 1, len, to_stream);
 
788
        }
 
789
 
 
790
        fclose(to_stream);
 
791
        fclose(from_stream);
 
792
 
 
793
        if (set_permissions(to, &st))
 
794
                return recursiveOp_Callback_Error;
 
795
 
 
796
        return recursiveOp_Callback_OK;
 
797
}
 
798
 
 
799
static int move_callback_pre(const char *from, const char *to)
 
800
{
 
801
        int ret = rename(from, to);
 
802
 
 
803
        if (ret)
 
804
                return copy_callback_pre(from, to);
 
805
 
 
806
        return recursiveOp_Callback_StopRecurs;
 
807
}
 
808
 
 
809
static int move_single_file(const char *from, const char *to)
 
810
{
 
811
        int ret = rename(from, to);
 
812
 
 
813
        if (ret)
 
814
                return copy_single_file(from, to);
 
815
 
 
816
        return recursiveOp_Callback_OK;
 
817
}
 
818
 
 
819
int BLI_move(const char *file, const char *to)
 
820
{
 
821
        int ret = recursive_operation(file, to, move_callback_pre, move_single_file, NULL);
 
822
 
 
823
        if (ret) {
 
824
                return recursive_operation(file, NULL, NULL, delete_single_file, delete_callback_post);
 
825
        }
 
826
 
 
827
        return ret;
 
828
}
 
829
 
 
830
static char *check_destination(const char *file, const char *to)
 
831
{
 
832
        struct stat st;
 
833
 
 
834
        if (!stat(to, &st)) {
 
835
                if (S_ISDIR(st.st_mode)) {
 
836
                        char *str, *filename, *path;
 
837
                        size_t len = 0;
 
838
 
 
839
                        str = strip_last_slash(file);
 
840
                        filename = BLI_last_slash(str);
 
841
 
 
842
                        if (!filename) {
 
843
                                MEM_freeN(str);
 
844
                                return (char*)to;
 
845
                        }
 
846
 
 
847
                        /* skip slash */
 
848
                        filename += 1;
 
849
 
 
850
                        len = strlen(to) + strlen(filename) + 1;
 
851
                        path = MEM_callocN(len + 1, "check_destination path");
 
852
                        BLI_join_dirfile(path, len + 1, to, filename);
 
853
 
 
854
                        MEM_freeN(str);
 
855
 
 
856
                        return path;
 
857
                }
 
858
        }
 
859
 
 
860
        return (char*)to;
 
861
}
 
862
 
 
863
int BLI_copy(const char *file, const char *to)
 
864
{
 
865
        char *actual_to = check_destination(file, to);
 
866
        int ret;
 
867
 
 
868
        ret = recursive_operation(file, actual_to, copy_callback_pre, copy_single_file, NULL);
 
869
 
 
870
        if (actual_to!=to)
 
871
                MEM_freeN(actual_to);
 
872
 
 
873
        return ret;
 
874
}
 
875
 
 
876
int BLI_create_symlink(const char *file, const char *to)
 
877
{
 
878
        return symlink(to, file);
 
879
}
 
880
 
 
881
void BLI_dir_create_recursive(const char *dirname)
 
882
{
378
883
        char *lslash;
379
 
        char tmp[MAXPATHLEN];
380
 
                
 
884
        size_t size;
 
885
#ifdef MAXPATHLEN
 
886
        char static_buf[MAXPATHLEN];
 
887
#endif
 
888
        char *tmp;
 
889
        int needs_free;
 
890
 
381
891
        if (BLI_exists(dirname)) return;
382
892
 
383
 
        strcpy(tmp, dirname);
 
893
#ifdef MAXPATHLEN
 
894
        size = MAXPATHLEN;
 
895
        tmp = static_buf;
 
896
        needs_free = 0;
 
897
#else
 
898
        size = strlen(dirname)+1;
 
899
        tmp = MEM_callocN(size, "BLI_dir_create_recursive tmp");
 
900
        needs_free = 1;
 
901
#endif
 
902
 
 
903
        BLI_strncpy(tmp, dirname, size);
384
904
                
385
905
        lslash= BLI_last_slash(tmp);
386
906
        if (lslash) {
387
907
                        /* Split about the last slash and recurse */    
388
908
                *lslash = 0;
389
 
                BLI_recurdir_fileops(tmp);
 
909
                BLI_dir_create_recursive(tmp);
390
910
        }
391
911
 
 
912
        if (needs_free)
 
913
                MEM_freeN(tmp);
 
914
 
392
915
        mkdir(dirname, 0777);
393
916
}
394
917
 
395
 
int BLI_rename(char *from, char *to) {
 
918
int BLI_rename(const char *from, const char *to)
 
919
{
396
920
        if (!BLI_exists(from)) return 0;
397
921
        
398
 
        if (BLI_exists(to))     if(BLI_delete(to, 0, 0)) return 1;
 
922
        if (BLI_exists(to))
 
923
                if (BLI_delete(to, 0, 0)) return 1;
399
924
 
400
925
        return rename(from, to);
401
926
}
402
927
 
403
928
#endif
 
929