Back to index

avfs  1.0.1
uxz.c
Go to the documentation of this file.
00001 /*  
00002     AVFS: A Virtual File System Library
00003     Copyright (C) 2010  Ralf Hoffmann <ralf@boomerangsworld.de>
00004 
00005     This program can be distributed under the terms of the GNU GPL.
00006     See the file COPYING.
00007 
00008     UXZ module (based on UBZ2 module)
00009 */
00010 
00011 #include "version.h"
00012 
00013 #include "xzfile.h"
00014 #include "filecache.h"
00015 #include "oper.h"
00016 #include "version.h"
00017 
00018 struct xznode {
00019     struct avstat sig;
00020     struct xzcache *cache;
00021     avino_t ino;
00022 };
00023 
00024 struct xzhandle {
00025     struct xzfile *zfil;
00026     vfile *base;
00027     struct xznode *node;
00028 };
00029 
00030 
00031 static void xznode_destroy(struct xznode *nod)
00032 {
00033     av_unref_obj(nod->cache);
00034 }
00035 
00036 static struct xznode *xz_new_node(ventry *ve, struct avstat *stbuf)
00037 {
00038     struct xznode *nod;
00039 
00040     AV_NEW_OBJ(nod, xznode_destroy);
00041     nod->sig = *stbuf;
00042     nod->cache = av_xzcache_new();
00043     nod->ino = av_new_ino(ve->mnt->avfs);
00044     
00045     return nod;
00046 }
00047 
00048 static int xz_same(struct xznode *nod, struct avstat *stbuf)
00049 {
00050     if(nod->sig.ino == stbuf->ino &&
00051        nod->sig.dev == stbuf->dev &&
00052        nod->sig.size == stbuf->size &&
00053        AV_TIME_EQ(nod->sig.mtime, stbuf->mtime))
00054         return 1;
00055     else
00056         return 0;
00057 }
00058 
00059 static struct xznode *xz_do_get_node(ventry *ve, const char *key,
00060                                      struct avstat *stbuf)
00061 {
00062     static AV_LOCK_DECL(lock);
00063     struct xznode *nod;
00064 
00065     AV_LOCK(lock);
00066     nod = (struct xznode *) av_filecache_get(key);
00067     if(nod != NULL) {
00068         if(!xz_same(nod, stbuf)) {
00069             av_unref_obj(nod);
00070             nod = NULL;
00071         }
00072     }
00073     
00074     if(nod == NULL) {
00075         nod =  xz_new_node(ve, stbuf);
00076         av_filecache_set(key, nod);
00077     }
00078     AV_UNLOCK(lock);
00079 
00080     return nod;
00081 }
00082 
00083 static int xz_getnode(ventry *ve, vfile *base, struct xznode **resp)
00084 {
00085     int res;
00086     struct avstat stbuf;
00087     const int attrmask = AVA_INO | AVA_DEV | AVA_SIZE | AVA_MTIME;
00088     struct xznode *nod;
00089     char *key;
00090 
00091     res = av_fgetattr(base, &stbuf, attrmask);
00092     if(res < 0)
00093         return res;
00094 
00095     res = av_filecache_getkey(ve, &key);
00096     if(res < 0)
00097         return res;
00098 
00099     nod = xz_do_get_node(ve, key, &stbuf);
00100 
00101     av_free(key);
00102 
00103     *resp = nod;
00104     return 0;
00105 }
00106 
00107 static int xz_lookup(ventry *ve, const char *name, void **newp)
00108 {
00109     char *path = (char *) ve->data;
00110     
00111     if(path == NULL) {
00112         if(name[0] != '\0')
00113             return -ENOENT;
00114        if(ve->mnt->opts[0] != '\0')
00115             return -ENOENT;
00116         path = av_strdup(name);
00117     }
00118     else if(name == NULL) {
00119         av_free(path);
00120         path = NULL;
00121     }
00122     else 
00123         return -ENOENT;
00124     
00125     *newp = path;
00126     return 0;
00127 }
00128 
00129 static int xz_access(ventry *ve, int amode)
00130 {
00131     return av_access(ve->mnt->base, amode);
00132 }
00133 
00134 static int xz_open(ventry *ve, int flags, avmode_t mode, void **resp)
00135 {
00136     int res;
00137     vfile *base;
00138     struct xznode *nod;
00139     struct xzhandle *fil;
00140 
00141     if(flags & AVO_DIRECTORY)
00142         return -ENOTDIR;
00143 
00144     if(AV_ISWRITE(flags))
00145         return -EROFS;
00146 
00147     res = av_open(ve->mnt->base, AVO_RDONLY, 0, &base);
00148     if(res < 0)
00149         return res;
00150 
00151     res = xz_getnode(ve, base, &nod);
00152     if(res < 0) {
00153         av_close(base);
00154         return res;
00155     }
00156 
00157     AV_NEW(fil);
00158     if((flags & AVO_ACCMODE) != AVO_NOPERM)
00159         fil->zfil = av_xzfile_new(base);
00160     else
00161         fil->zfil = NULL;
00162 
00163     fil->base = base;
00164     fil->node = nod;
00165     
00166     *resp = fil;
00167     return 0;
00168 }
00169 
00170 static int xz_close(vfile *vf)
00171 {
00172     struct xzhandle *fil = (struct xzhandle *) vf->data;
00173 
00174     av_unref_obj(fil->zfil);
00175     av_unref_obj(fil->node);
00176     av_close(fil->base);
00177     av_free(fil);
00178 
00179     return 0;
00180 }
00181 
00182 static avssize_t xz_read(vfile *vf, char *buf, avsize_t nbyte)
00183 {
00184     avssize_t res;
00185     struct xzhandle *fil = (struct xzhandle *) vf->data;
00186  
00187     res = av_xzfile_pread(fil->zfil, fil->node->cache, buf, nbyte, vf->ptr);
00188     if(res > 0)
00189         vf->ptr += res;
00190 
00191     return res;
00192 }
00193 
00194 static int xz_getattr(vfile *vf, struct avstat *buf, int attrmask)
00195 {
00196     int res;
00197     struct xzhandle *fil = (struct xzhandle *) vf->data;
00198     struct xznode *nod = fil->node;
00199     avoff_t size;
00200     const int basemask = AVA_MODE | AVA_UID | AVA_GID | AVA_MTIME | AVA_ATIME | AVA_CTIME;
00201 
00202     res = av_fgetattr(fil->base, buf, basemask);
00203     if(res < 0)
00204         return res;
00205 
00206     if((attrmask & (AVA_SIZE | AVA_BLKCNT)) != 0) {
00207         res = av_xzfile_size(fil->zfil, fil->node->cache, &size);
00208         if(res == 0 && size == -1) {
00209             fil->zfil = av_xzfile_new(fil->base);
00210             res = av_xzfile_size(fil->zfil, fil->node->cache, &size);
00211         }
00212         if(res < 0)
00213             return res;
00214 
00215         buf->size = size;
00216         buf->blocks = AV_BLOCKS(buf->size);
00217     }
00218 
00219     buf->mode &= ~(07000);
00220     buf->blksize = 4096;
00221     buf->dev = vf->mnt->avfs->dev;
00222     buf->ino = nod->ino;
00223     buf->nlink = 1;
00224     
00225     return 0;
00226 }
00227 
00228 extern int av_init_module_uxz(struct vmodule *module);
00229 
00230 int av_init_module_uxz(struct vmodule *module)
00231 {
00232     int res;
00233     struct avfs *avfs;
00234     struct ext_info uxz_exts[5];
00235 
00236     uxz_exts[0].from = ".tar.xz",  uxz_exts[0].to = ".tar";
00237     uxz_exts[1].from = ".txz",  uxz_exts[1].to = ".tar";
00238     uxz_exts[2].from = ".xz",  uxz_exts[2].to = NULL;
00239     uxz_exts[3].from = ".lzma",  uxz_exts[3].to = NULL;
00240     uxz_exts[4].from = NULL;
00241 
00242     res = av_new_avfs("uxz", uxz_exts, AV_VER, AVF_NOLOCK, module, &avfs);
00243     if(res < 0)
00244         return res;
00245 
00246     avfs->lookup   = xz_lookup;
00247     avfs->access   = xz_access;
00248     avfs->open     = xz_open;
00249     avfs->close    = xz_close; 
00250     avfs->read     = xz_read;
00251     avfs->getattr  = xz_getattr;
00252 
00253     av_add_avfs(avfs);
00254 
00255     return 0;
00256 }