Blender V2.61 - r43446

fileops.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <string.h>
00034 #include <stdio.h>
00035 
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038 #include <fcntl.h>
00039 
00040 #include <errno.h>
00041 
00042 #include "zlib.h"
00043 
00044 #ifdef WIN32
00045 #include <io.h>
00046 #include "BLI_winstuff.h"
00047 #include "BLI_callbacks.h"
00048 #else
00049 #include <unistd.h> // for read close
00050 #include <sys/param.h>
00051 #endif
00052 
00053 #include "MEM_guardedalloc.h"
00054 
00055 #include "BLI_blenlib.h"
00056 
00057 #include "BKE_utildefines.h"
00058 
00059 #include "BLO_sys_types.h" // for intptr_t support
00060 
00061 
00062 /* gzip the file in from and write it to "to". 
00063  return -1 if zlib fails, -2 if the originating file does not exist
00064  note: will remove the "from" file
00065   */
00066 int BLI_file_gzip(const char *from, const char *to)
00067 {
00068     char buffer[10240];
00069     int file;
00070     int readsize = 0;
00071     int rval= 0, err;
00072     gzFile gzfile;
00073 
00074     /* level 1 is very close to 3 (the default) in terms of file size,
00075      * but about twice as fast, best use for speedy saving - campbell */
00076     gzfile = gzopen(to, "wb1");
00077     if(gzfile == NULL)
00078         return -1;
00079     
00080     file = open(from, O_BINARY|O_RDONLY);
00081     if(file < 0)
00082         return -2;
00083 
00084     while(1) {
00085         readsize = read(file, buffer, sizeof(buffer));
00086 
00087         if(readsize < 0) {
00088             rval= -2; /* error happened in reading */
00089             fprintf(stderr, "Error reading file %s: %s.\n", from, strerror(errno));
00090             break;
00091         }
00092         else if(readsize == 0)
00093             break; /* done reading */
00094         
00095         if(gzwrite(gzfile, buffer, readsize) <= 0) {
00096             rval= -1; /* error happened in writing */
00097             fprintf(stderr, "Error writing gz file %s: %s.\n", to, gzerror(gzfile, &err));
00098             break;
00099         }
00100     }
00101     
00102     gzclose(gzfile);
00103     close(file);
00104 
00105     return rval;
00106 }
00107 
00108 /* gzip the file in from_file and write it to memery to_mem, at most size bytes.
00109    return the unziped size
00110   */
00111 char *BLI_file_ungzip_to_mem(const char *from_file, int *size_r)
00112 {
00113     gzFile gzfile;
00114     int readsize, size, alloc_size=0;
00115     char *mem= NULL;
00116     const int chunk_size= 512*1024;
00117 
00118     size= 0;
00119 
00120     gzfile = gzopen( from_file, "rb" );
00121 
00122     for(;;) {
00123         if(mem==NULL) {
00124             mem= MEM_callocN(chunk_size, "BLI_ungzip_to_mem");
00125             alloc_size= chunk_size;
00126         } else {
00127             mem= MEM_reallocN(mem, size+chunk_size);
00128             alloc_size+= chunk_size;
00129         }
00130 
00131         readsize= gzread(gzfile, mem+size, chunk_size);
00132         if(readsize>0) {
00133             size+= readsize;
00134         }
00135         else break;
00136     }
00137 
00138     if(size==0) {
00139         MEM_freeN(mem);
00140         mem= NULL;
00141     }
00142     else if(alloc_size!=size)
00143         mem= MEM_reallocN(mem, size);
00144 
00145     *size_r= size;
00146 
00147     return mem;
00148 }
00149 
00150 
00151 /* return 1 when file can be written */
00152 int BLI_file_is_writable(const char *filename)
00153 {
00154     int file;
00155     
00156     /* first try to open without creating */
00157     file = open(filename, O_BINARY | O_RDWR, 0666);
00158     
00159     if (file < 0) {
00160         /* now try to open and create. a test without actually
00161          * creating a file would be nice, but how? */
00162         file = open(filename, O_BINARY | O_RDWR | O_CREAT, 0666);
00163         
00164         if(file < 0) {
00165             return 0;
00166         }
00167         else {
00168             /* success, delete the file we create */
00169             close(file);
00170             BLI_delete(filename, 0, 0);
00171             return 1;
00172         }
00173     }
00174     else {
00175         close(file);
00176         return 1;
00177     }
00178 }
00179 
00180 int BLI_file_touch(const char *file)
00181 {
00182     FILE *f = fopen(file,"r+b");
00183     if (f != NULL) {
00184         char c = getc(f);
00185         rewind(f);
00186         putc(c,f);
00187     } else {
00188         f = fopen(file,"wb");
00189     }
00190     if (f) {
00191         fclose(f);
00192         return 1;
00193     }
00194     return 0;
00195 }
00196 
00197 #ifdef WIN32
00198 
00199 static char str[MAXPATHLEN+12];
00200 
00201 int BLI_delete(const char *file, int dir, int recursive)
00202 {
00203     int err;
00204 
00205     if (recursive) {
00206         callLocalErrorCallBack("Recursive delete is unsupported on Windows");
00207         err= 1;
00208     } else if (dir) {
00209         err= !RemoveDirectory(file);
00210         if (err) printf ("Unable to remove directory");
00211     } else {
00212         err= !DeleteFile(file);
00213         if (err) callLocalErrorCallBack("Unable to delete file");
00214     }
00215 
00216     return err;
00217 }
00218 
00219 int BLI_move(const char *file, const char *to)
00220 {
00221     int err;
00222 
00223     // windows doesn't support moveing to a directory
00224     // it has to be 'mv filename filename' and not
00225     // 'mv filename destdir'
00226 
00227     BLI_strncpy(str, to, sizeof(str));
00228     // points 'to' to a directory ?
00229     if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
00230         if (BLI_last_slash(file) != NULL) {
00231             strcat(str, BLI_last_slash(file) + 1);
00232         }
00233     }
00234 
00235     err= !MoveFile(file, str);
00236     if (err) {
00237         callLocalErrorCallBack("Unable to move file");
00238         printf(" Move from '%s' to '%s' failed\n", file, str);
00239     }
00240 
00241     return err;
00242 }
00243 
00244 
00245 int BLI_copy(const char *file, const char *to)
00246 {
00247     int err;
00248 
00249     // windows doesn't support copying to a directory
00250     // it has to be 'cp filename filename' and not
00251     // 'cp filename destdir'
00252 
00253     BLI_strncpy(str, to, sizeof(str));
00254     // points 'to' to a directory ?
00255     if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
00256         if (BLI_last_slash(file) != NULL) {
00257             strcat(str, BLI_last_slash(file) + 1);
00258         }
00259     }
00260 
00261     err= !CopyFile(file,str,FALSE);
00262     
00263     if (err) {
00264         callLocalErrorCallBack("Unable to copy file!");
00265         printf(" Copy from '%s' to '%s' failed\n", file, str);
00266     }
00267 
00268     return err;
00269 }
00270 
00271 int BLI_create_symlink(const char *file, const char *to)
00272 {
00273     callLocalErrorCallBack("Linking files is unsupported on Windows");
00274     (void)file;
00275     (void)to;
00276     return 1;
00277 }
00278 
00279 void BLI_dir_create_recursive(const char *dirname)
00280 {
00281     char *lslash;
00282     char tmp[MAXPATHLEN];
00283     
00284     // First remove possible slash at the end of the dirname.
00285     // This routine otherwise tries to create
00286     // blah1/blah2/ (with slash) after creating
00287     // blah1/blah2 (without slash)
00288 
00289     BLI_strncpy(tmp, dirname, sizeof(tmp));
00290     lslash= BLI_last_slash(tmp);
00291 
00292     if (lslash == tmp + strlen(tmp) - 1) {
00293         *lslash = 0;
00294     }
00295     
00296     if (BLI_exists(tmp)) return;
00297         
00298     lslash= BLI_last_slash(tmp);
00299     if (lslash) {
00300             /* Split about the last slash and recurse */    
00301         *lslash = 0;
00302         BLI_dir_create_recursive(tmp);
00303     }
00304     
00305     if(dirname[0]) /* patch, this recursive loop tries to create a nameless directory */
00306         if (!CreateDirectory(dirname, NULL))
00307             callLocalErrorCallBack("Unable to create directory\n");
00308 }
00309 
00310 int BLI_rename(const char *from, const char *to)
00311 {
00312     if (!BLI_exists(from)) return 0;
00313 
00314     /* make sure the filenames are different (case insensitive) before removing */
00315     if (BLI_exists(to) && BLI_strcasecmp(from, to))
00316         if(BLI_delete(to, 0, 0)) return 1;
00317 
00318     return rename(from, to);
00319 }
00320 
00321 #else /* The UNIX world */
00322 
00323 /*
00324  * but the UNIX world is tied to the interface, and the system
00325  * timer, and... We implement a callback mechanism. The system will
00326  * have to initialise the callback before the functions will work!
00327  * */
00328 static char str[12 + (MAXPATHLEN * 2)];
00329 
00330 int BLI_delete(const char *file, int dir, int recursive) 
00331 {
00332     if(strchr(file, '"')) {
00333         printf("Error: not deleted file %s because of quote!\n", file);
00334     }
00335     else {
00336         if (recursive) {
00337             BLI_snprintf(str, sizeof(str), "/bin/rm -rf \"%s\"", file);
00338             return system(str);
00339         }
00340         else if (dir) {
00341             BLI_snprintf(str, sizeof(str), "/bin/rmdir \"%s\"", file);
00342             return system(str);
00343         }
00344         else {
00345             return remove(file); //BLI_snprintf(str, sizeof(str), "/bin/rm -f \"%s\"", file);
00346         }
00347     }
00348     return -1;
00349 }
00350 
00351 int BLI_move(const char *file, const char *to)
00352 {
00353     BLI_snprintf(str, sizeof(str), "/bin/mv -f \"%s\" \"%s\"", file, to);
00354 
00355     return system(str);
00356 }
00357 
00358 int BLI_copy(const char *file, const char *to)
00359 {
00360     BLI_snprintf(str, sizeof(str), "/bin/cp -rf \"%s\" \"%s\"", file, to);
00361 
00362     return system(str);
00363 }
00364 
00365 int BLI_create_symlink(const char *file, const char *to)
00366 {
00367     BLI_snprintf(str, sizeof(str), "/bin/ln -f \"%s\" \"%s\"", file, to);
00368     
00369     return system(str);
00370 }
00371 
00372 void BLI_dir_create_recursive(const char *dirname)
00373 {
00374     char *lslash;
00375     char tmp[MAXPATHLEN];
00376         
00377     if (BLI_exists(dirname)) return;
00378 
00379     BLI_strncpy(tmp, dirname, sizeof(tmp));
00380         
00381     lslash= BLI_last_slash(tmp);
00382     if (lslash) {
00383             /* Split about the last slash and recurse */    
00384         *lslash = 0;
00385         BLI_dir_create_recursive(tmp);
00386     }
00387 
00388     mkdir(dirname, 0777);
00389 }
00390 
00391 int BLI_rename(const char *from, const char *to)
00392 {
00393     if (!BLI_exists(from)) return 0;
00394     
00395     if (BLI_exists(to)) if(BLI_delete(to, 0, 0)) return 1;
00396 
00397     return rename(from, to);
00398 }
00399 
00400 #endif
00401