Back to index

avfs  1.0.1
tmpfile.c
Go to the documentation of this file.
00001 /*
00002     AVFS: A Virtual File System Library
00003     Copyright (C) 1998-2001  Miklos Szeredi <miklos@szeredi.hu>
00004     Copyright (C) 2006       Ralf Hoffmann (ralf@boomerangsworld.de)
00005 
00006     This program can be distributed under the terms of the GNU GPL.
00007     See the file COPYING.
00008 */
00009 
00010 #include "internal.h"
00011 #include "config.h"
00012 
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <dirent.h>
00016 #include <fcntl.h>
00017 #include <unistd.h>
00018 #include <sys/stat.h>
00019 #ifdef HAVE_SYS_STATVFS_H
00020 #include <sys/statvfs.h>
00021 #endif
00022 
00023 struct tmpdir {
00024     char *path;
00025     int ctr;
00026 };
00027 
00028 static AV_LOCK_DECL(tmplock);
00029 static struct tmpdir *tmpdir;
00030 
00031 static int unlink_recursive(const char *file)
00032 {
00033     int res;
00034     DIR *dirp;
00035     struct dirent *ent;
00036     char *name;
00037 
00038     res = unlink(file);
00039     if(res == 0)
00040         return 0;
00041 
00042     res = rmdir(file);
00043     if(res == 0)
00044         return 0;
00045 
00046     dirp = opendir(file);
00047     if(dirp == NULL)
00048         return -1;
00049 
00050     while((ent = readdir(dirp)) != NULL) {
00051         name = ent->d_name;
00052     
00053         if(name[0] != '.' || (name[1] && (name[1] != '.' || name[2]))) {
00054             char *newname;
00055 
00056             newname = av_stradd(NULL, file, "/", name, NULL);
00057             unlink_recursive(newname);
00058             av_free(newname);
00059         }
00060     }
00061     closedir(dirp);
00062 
00063     return rmdir(file);
00064 }
00065 
00066 
00067 void av_delete_tmpdir()
00068 {
00069     AV_LOCK(tmplock);
00070     if(tmpdir != NULL) {
00071         unlink_recursive(tmpdir->path);
00072         av_free(tmpdir->path);
00073         av_free(tmpdir);
00074         tmpdir = NULL;
00075     }
00076     AV_UNLOCK(tmplock);
00077 }
00078 
00079 #ifdef HAVE_MKDTEMP
00080 
00081 static int make_tmp_dir(char *path)
00082 {
00083     char *res;
00084 
00085     res = mkdtemp(path);
00086     if(res == NULL) {
00087         av_log(AVLOG_ERROR, "mkdtemp failed: %s", strerror(errno));
00088         return -EIO;
00089     }
00090     return 0;
00091 }
00092 
00093 #else /* HAVE_MKDTEMP */
00094 
00095 static int make_tmp_dir(char *path)
00096 {
00097     int res;
00098 
00099     mktemp(path);
00100     if(path[0] == '\0') {
00101         av_log(AVLOG_ERROR, "mktemp failed for temporary directory");
00102         return -EIO;
00103     }
00104     res = mkdir(path, 0700);
00105     if(res == -1) {
00106         av_log(AVLOG_ERROR, "mkdir(%s) failed: %s", path, strerror(errno));
00107         return -EIO;
00108     }
00109     return 0;
00110 }
00111 
00112 #endif /* HAVE_MKDTEMP */
00113 
00114 int av_get_tmpfile(char **retp)
00115 {
00116     int res = 0;
00117     char buf[64];
00118   
00119     AV_LOCK(tmplock);
00120     if(tmpdir == NULL) {
00121         char *path;
00122 
00123         path = av_strdup("/tmp/.avfs_tmp_XXXXXX");
00124         res = make_tmp_dir(path);
00125         if(res < 0)
00126             av_free(path);
00127         else {
00128            AV_NEW(tmpdir);
00129            tmpdir->path = path;
00130            tmpdir->ctr = 0;
00131        }
00132     }
00133     if(tmpdir != NULL) {
00134        sprintf(buf, "/atmp%06i", tmpdir->ctr++);
00135        *retp = av_stradd(NULL, tmpdir->path, buf, NULL);
00136     }
00137     AV_UNLOCK(tmplock);
00138 
00139     return res;
00140 }
00141 
00142 void av_del_tmpfile(char *tmpf)
00143 {
00144     if(tmpf != NULL) {
00145        if(unlink(tmpf) == -1)
00146            rmdir(tmpf);
00147        
00148        av_free(tmpf);
00149     }
00150 }
00151 
00152 avoff_t av_tmp_free()
00153 {
00154 #ifdef HAVE_SYS_STATVFS_H
00155     int res;
00156     struct statvfs stbuf;
00157 #endif
00158     avoff_t freebytes = -1;
00159 
00160 #ifdef HAVE_SYS_STATVFS_H
00161     AV_LOCK(tmplock);
00162     if(tmpdir != NULL) {
00163         /* Check if fs supports df info (ramfs doesn't) */
00164         res = statvfs(tmpdir->path, &stbuf);
00165         if(res != -1 && stbuf.f_blocks != 0)
00166             freebytes = (avoff_t) stbuf.f_bavail * (avoff_t) stbuf.f_frsize;
00167     }
00168     AV_UNLOCK(tmplock);
00169 #endif
00170 
00171 #if 0    
00172     if(freebytes != -1)
00173         av_log(AVLOG_DEBUG, "free bytes in tmp directory: %lli", freebytes);
00174 #endif
00175 
00176     return freebytes;
00177 }
00178 
00179 avoff_t av_tmpfile_blksize(const char *tmpf)
00180 {
00181     int res;
00182     struct stat stbuf;
00183     
00184     if(tmpf == NULL)
00185         return -1;
00186 
00187     res = stat(tmpf, &stbuf);
00188     if(res == 0) {
00189         /* Ramfs returns 0 diskusage */
00190         if(stbuf.st_blocks == 0)
00191             return stbuf.st_size;
00192         else
00193             return stbuf.st_blocks * 512;
00194     } else
00195         return -1;
00196 }