Back to index

avfs  1.0.1
realfile.c
Go to the documentation of this file.
00001 /*
00002     AVFS: A Virtual File System Library
00003     Copyright (C) 1998  Miklos Szeredi <miklos@szeredi.hu>
00004     
00005     This program can be distributed under the terms of the GNU GPL.
00006     See the file COPYING.
00007 */
00008 
00009 #include "realfile.h"
00010 #include "oper.h"
00011 #include "cache.h"
00012 
00013 #include <unistd.h>
00014 #include <fcntl.h>
00015 
00016 #define COPY_BUFSIZE 16384
00017 
00018 static int copy_file(ventry *ve, const char *destpath)
00019 {
00020     int res;
00021     avssize_t num;
00022     char buf[COPY_BUFSIZE];
00023     int ctr;
00024     vfile *vf;
00025     int destfd;
00026 
00027     res = av_open(ve, AVO_RDONLY, 0, &vf);
00028     if(res < 0)
00029         return res;
00030     
00031     destfd = open(destpath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
00032     if(destfd == -1) {
00033         res = -errno;
00034         av_close(vf);
00035         av_log(AVLOG_ERROR, "Error opening file %s: %s", destpath,
00036                strerror(errno));
00037         return res;
00038     }
00039 
00040     ctr = 0;
00041     while(1) {
00042         res = av_read(vf, buf, COPY_BUFSIZE);
00043         if(res <= 0)
00044             break;
00045 
00046         num = res;
00047         res = write(destfd, buf, num);
00048         if(res == -1 && (errno == ENOSPC || errno == EDQUOT)) {
00049             av_cache_diskfull();
00050             res = write(destfd, buf, num);
00051         }
00052         if(res == -1) {
00053             res = -errno;
00054             av_log(AVLOG_ERROR, "Error writing file %s: %s", destpath,
00055                    strerror(errno));
00056             break;
00057         }
00058 
00059         /* Check free space after each Meg */
00060         if((ctr++ % 64) == 0)
00061             av_cache_checkspace();
00062     }
00063 
00064     close(destfd);
00065     if(res == 0)
00066         res = av_close(vf);
00067     else
00068         av_close(vf);
00069 
00070     return res;
00071 }
00072 
00073 static void realfile_delete(struct realfile *rf)
00074 {
00075     if(!rf->is_tmp) 
00076         av_free(rf->name);
00077     else 
00078         av_del_tmpfile(rf->name);
00079 }
00080 
00081 int av_get_realfile(ventry *ve, struct realfile **resp)
00082 {
00083     int res;
00084     struct realfile *rf;
00085 
00086     AV_NEW_OBJ(rf, realfile_delete);
00087     rf->is_tmp = 0;
00088     rf->name = NULL;
00089 
00090     if(ve->mnt->base == NULL) {
00091         rf->name = av_strdup((char *) ve->data);
00092         rf->is_tmp = 0;
00093 
00094         *resp = rf;
00095         return 0;
00096     }
00097 
00098     res = av_get_tmpfile(&rf->name);
00099     if(res < 0) {
00100         av_unref_obj(rf);
00101         return res;
00102     }
00103 
00104     rf->is_tmp = 1;
00105 
00106     res = copy_file(ve, rf->name);
00107     if(res < 0) {
00108         av_unref_obj(rf);
00109         return res;
00110     }
00111 
00112     *resp = rf;
00113     return 0;
00114 }
00115