Back to index

avfs  1.0.1
Classes | Defines | Functions
ugz.c File Reference
#include "zfile.h"
#include "zipconst.h"
#include "filecache.h"
#include "cache.h"
#include "oper.h"
#include "version.h"

Go to the source code of this file.

Classes

struct  gznode
struct  gzfile
struct  gzbuf

Defines

#define GZBUFSIZE   1024
#define GZHEADER_SIZE   10
#define GZFOOTER_SIZE   8
#define GZMAGIC1   0x1f
#define GZMAGIC2   0x8b
#define GZFL_ASCII   0x01 /* bit 0 set: file probably ascii text */
#define GZFL_CONTINUATION   0x02 /* bit 1 set: continuation of multi-part gzip file */
#define GZFL_EXTRA_FIELD   0x04 /* bit 2 set: extra field present */
#define GZFL_ORIG_NAME   0x08 /* bit 3 set: original file name present */
#define GZFL_COMMENT   0x10 /* bit 4 set: file comment present */
#define GZFL_RESERVED   0xE0 /* bits 5..7: reserved */
#define BI(ptr, i)   ((avbyte) (ptr)[i])
#define DBYTE(ptr)   (BI(ptr,0) | (BI(ptr,1)<<8))
#define QBYTE(ptr)

Functions

static int gzbuf_getbyte (struct gzbuf *gb)
static int gzbuf_skip_string (struct gzbuf *gb)
static int gzbuf_read (struct gzbuf *gb, char *buf, avsize_t nbyte)
static int gz_read_header (vfile *vf, struct gznode *nod)
static void gznode_destroy (struct gznode *nod)
static struct gznodegz_new_node (ventry *ve, struct avstat *stbuf)
static int gz_same (struct gznode *nod, struct avstat *stbuf)
static struct gznodegz_findnode (ventry *ve, const char *key, struct avstat *stbuf)
static int gz_getnode (ventry *ve, vfile *base, struct gznode **resp)
static struct zcachegz_getcache (ventry *base, struct gznode *nod)
static int gz_lookup (ventry *ve, const char *name, void **newp)
static int gz_access (ventry *ve, int amode)
static int gz_open (ventry *ve, int flags, avmode_t mode, void **resp)
static int gz_close (vfile *vf)
static avssize_t gz_read (vfile *vf, char *buf, avsize_t nbyte)
static int gz_getsize (vfile *vf, struct avstat *buf)
static int gz_getattr (vfile *vf, struct avstat *buf, int attrmask)
int av_init_module_ugz (struct vmodule *module)

Class Documentation

struct gznode

Definition at line 18 of file ugz.c.

Collaboration diagram for gznode:
Class Members
struct cacheobj * cache
avuint crc
avoff_t dataoff
avino_t ino
avmutex lock
avtime_t mtime
int ready
avoff_t size
struct gzfile

Definition at line 30 of file ugz.c.

Collaboration diagram for gzfile:
Class Members
vfile * base
struct gznode * node
int validsize
struct zfile * zfil
struct gzbuf

Definition at line 39 of file ugz.c.

Class Members
unsigned int avail
unsigned char buf
unsigned char * next
unsigned int total
vfile * vf

Define Documentation

#define BI (   ptr,
 
)    ((avbyte) (ptr)[i])

Definition at line 62 of file ugz.c.

#define DBYTE (   ptr)    (BI(ptr,0) | (BI(ptr,1)<<8))

Definition at line 63 of file ugz.c.

#define GZBUFSIZE   1024

Definition at line 37 of file ugz.c.

#define GZFL_ASCII   0x01 /* bit 0 set: file probably ascii text */

Definition at line 54 of file ugz.c.

#define GZFL_COMMENT   0x10 /* bit 4 set: file comment present */

Definition at line 58 of file ugz.c.

#define GZFL_CONTINUATION   0x02 /* bit 1 set: continuation of multi-part gzip file */

Definition at line 55 of file ugz.c.

#define GZFL_EXTRA_FIELD   0x04 /* bit 2 set: extra field present */

Definition at line 56 of file ugz.c.

#define GZFL_ORIG_NAME   0x08 /* bit 3 set: original file name present */

Definition at line 57 of file ugz.c.

#define GZFL_RESERVED   0xE0 /* bits 5..7: reserved */

Definition at line 59 of file ugz.c.

#define GZFOOTER_SIZE   8

Definition at line 48 of file ugz.c.

#define GZHEADER_SIZE   10

Definition at line 47 of file ugz.c.

#define GZMAGIC1   0x1f

Definition at line 50 of file ugz.c.

#define GZMAGIC2   0x8b

Definition at line 51 of file ugz.c.

#define QBYTE (   ptr)
Value:
((avuint) (BI(ptr,0) | (BI(ptr,1)<<8) | \
                   (BI(ptr,2)<<16) | (BI(ptr,3)<<24)))

Definition at line 64 of file ugz.c.


Function Documentation

int av_init_module_ugz ( struct vmodule module)

Definition at line 493 of file ugz.c.

{
    int res;
    struct avfs *avfs;
    struct ext_info ugz_exts[3];

    ugz_exts[0].from = ".gz",  ugz_exts[0].to = NULL;
    ugz_exts[1].from = ".tgz", ugz_exts[1].to = ".tar";
    ugz_exts[2].from = NULL;

    res = av_new_avfs("ugz", ugz_exts, AV_VER, AVF_NOLOCK, module, &avfs);
    if(res < 0)
        return res;

    avfs->lookup   = gz_lookup;
    avfs->access   = gz_access;
    avfs->open     = gz_open;
    avfs->close    = gz_close; 
    avfs->read     = gz_read;
    avfs->getattr  = gz_getattr;

    av_add_avfs(avfs);

    return 0;
}

Here is the call graph for this function:

static int gz_access ( ventry *  ve,
int  amode 
) [static]

Definition at line 343 of file ugz.c.

{
    return av_access(ve->mnt->base, amode);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gz_close ( vfile *  vf) [static]

Definition at line 388 of file ugz.c.

{
    struct gzfile *fil = (struct gzfile *) vf->data;

    av_unref_obj(fil->zfil);
    av_unref_obj(fil->node);
    av_close(fil->base);
    av_free(fil);

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct gznode* gz_findnode ( ventry *  ve,
const char *  key,
struct avstat stbuf 
) [static, read]

Definition at line 232 of file ugz.c.

{
    struct gznode *nod;
    static AV_LOCK_DECL(lock);

    AV_LOCK(lock);
    nod = (struct gznode *) av_filecache_get(key);
    if(nod != NULL) {
        if(!gz_same(nod, stbuf)) {
            av_unref_obj(nod);
            nod = NULL;
        }
    }
    
    if(nod == NULL) {
        nod = gz_new_node(ve, stbuf);
        av_filecache_set(key, nod);
    }
    AV_UNLOCK(lock);

    return nod;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gz_getattr ( vfile *  vf,
struct avstat buf,
int  attrmask 
) [static]

Definition at line 461 of file ugz.c.

{
    int res;
    struct gzfile *fil = (struct gzfile *) vf->data;
    struct gznode *nod = fil->node;
    const int basemask = AVA_MODE | AVA_UID | AVA_GID | AVA_ATIME | AVA_CTIME |
           AVA_BLKCNT;

    res = av_fgetattr(fil->base, buf, basemask);
    if(res < 0)
        return res;

    buf->size = nod->size;
    if(!fil->validsize && (attrmask & (AVA_SIZE | AVA_BLKCNT)) != 0) {
        res = gz_getsize(vf, buf);
        if(res < 0)
            return res;
    }

    buf->mode &= ~(07000);
    buf->blksize = 4096;
    buf->dev = vf->mnt->avfs->dev;
    buf->ino = nod->ino;
    buf->nlink = 1;
    buf->mtime.sec = nod->mtime;
    buf->mtime.nsec = 0;
    
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct zcache* gz_getcache ( ventry *  base,
struct gznode nod 
) [static, read]

Definition at line 294 of file ugz.c.

{
    struct zcache *cache;
    
    cache = (struct zcache *) av_cacheobj_get(nod->cache);
    if(cache == NULL) {
        int res;
        char *name;

        res = av_generate_path(base, &name);
        if(res < 0)
            name = NULL;
        else
            name = av_stradd(name, "(index)", NULL);

        cache = av_zcache_new();
        av_unref_obj(nod->cache);

        /* FIXME: the cacheobj should only be created when the zcache
           is nonempty */
        nod->cache = av_cacheobj_new(cache, name);
        av_free(name); 
    }

    return cache;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gz_getnode ( ventry *  ve,
vfile *  base,
struct gznode **  resp 
) [static]

Definition at line 256 of file ugz.c.

{
    int res;
    struct avstat stbuf;
    const int attrmask = AVA_INO | AVA_DEV | AVA_SIZE | AVA_MTIME;
    struct gznode *nod;
    char *key;

    res = av_fgetattr(base, &stbuf, attrmask);
    if(res < 0)
        return res;

    res = av_filecache_getkey(ve, &key);
    if(res < 0)
        return res;
    
    nod = gz_findnode(ve, key, &stbuf);

    AV_LOCK(nod->lock);
    if(!nod->ready) {
        res = gz_read_header(base, nod);
        if(res < 0)
            av_filecache_set(key, NULL);
    }
    else
        res = 0;
    AV_UNLOCK(nod->lock);
    av_free(key);

    if(res < 0) {
        av_unref_obj(nod);
        return res;
    }

    *resp = nod;
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gz_getsize ( vfile *  vf,
struct avstat buf 
) [static]

Definition at line 433 of file ugz.c.

{
    int res;
    struct gzfile *fil = (struct gzfile *) vf->data;
    struct zcache *zc;
    struct cacheobj *cobj;
    avoff_t size;

    AV_LOCK(fil->node->lock);
    zc = gz_getcache(vf->mnt->base, fil->node);
    cobj = fil->node->cache;
    av_ref_obj(cobj);
    AV_UNLOCK(fil->node->lock);

    res = av_zfile_size(fil->zfil, zc, &size);
    if(res == 0 && size == -1) {
        fil->zfil = av_zfile_new(fil->base, fil->node->dataoff,
                                 fil->node->crc, 0);
        res = av_zfile_size(fil->zfil, zc, &size);
    }
    buf->size = size;

    av_unref_obj(zc);
    av_unref_obj(cobj);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gz_lookup ( ventry *  ve,
const char *  name,
void **  newp 
) [static]

Definition at line 321 of file ugz.c.

{
    char *path = (char *) ve->data;
    
    if(path == NULL) {
        if(name[0] != '\0')
            return -ENOENT;
       if(ve->mnt->opts[0] != '\0' && strcmp(ve->mnt->opts, "-s") != 0)
            return -ENOENT;
        path = av_strdup(name);
    }
    else if(name == NULL) {
        av_free(path);
        path = NULL;
    }
    else 
        return -ENOENT;
    
    *newp = path;
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct gznode* gz_new_node ( ventry *  ve,
struct avstat stbuf 
) [static, read]

Definition at line 207 of file ugz.c.

{
    struct gznode *nod;

    AV_NEW_OBJ(nod, gznode_destroy);
    AV_INITLOCK(nod->lock);
    nod->ready = 0;
    nod->sig = *stbuf;
    nod->cache = NULL;
    nod->ino = av_new_ino(ve->mnt->avfs);
    
    return nod;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gz_open ( ventry *  ve,
int  flags,
avmode_t  mode,
void **  resp 
) [static]

Definition at line 348 of file ugz.c.

{
    int res;
    vfile *base;
    struct gznode *nod;
    struct gzfile *fil;

    if(flags & AVO_DIRECTORY)
        return -ENOTDIR;

    if(AV_ISWRITE(flags))
        return -EROFS;

    res = av_open(ve->mnt->base, AVO_RDONLY, 0, &base);
    if(res < 0)
        return res;

    res = gz_getnode(ve, base, &nod);
    if(res < 0) {
        av_close(base);
        return res;
    }

    AV_NEW(fil);
    if((flags & AVO_ACCMODE) != AVO_NOPERM)
        fil->zfil = av_zfile_new(base, nod->dataoff, nod->crc, 1);
    else
        fil->zfil = NULL;

    fil->base = base;
    fil->node = nod;
    if(strcmp(ve->mnt->opts, "-s") == 0)
        fil->validsize = 1;
    else
        fil->validsize = 0;
    
    *resp = fil;
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static avssize_t gz_read ( vfile *  vf,
char *  buf,
avsize_t  nbyte 
) [static]

Definition at line 400 of file ugz.c.

{
    avssize_t res;
    struct gzfile *fil = (struct gzfile *) vf->data;
    struct zcache *zc;
    struct cacheobj *cobj;

    AV_LOCK(fil->node->lock);
    zc = gz_getcache(vf->mnt->base, fil->node);
    cobj = fil->node->cache;
    av_ref_obj(cobj);
    AV_UNLOCK(fil->node->lock);

    res = av_zfile_pread(fil->zfil, zc, buf, nbyte, vf->ptr);
    if(res >= 0) {
        vf->ptr += res;

        /* FIXME: should only be set when changed, ugly, UGLY, etc... */
        av_cacheobj_setsize(cobj, av_zcache_size(zc));
    }
    else {
        AV_LOCK(fil->node->lock);
        av_unref_obj(fil->node->cache);
        fil->node->cache = NULL;
        AV_UNLOCK(fil->node->lock);
    }

    av_unref_obj(zc);
    av_unref_obj(cobj);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gz_read_header ( vfile *  vf,
struct gznode nod 
) [static]

Definition at line 113 of file ugz.c.

{
    int res;
    avoff_t sres;
    struct gzbuf gb;
    unsigned char buf[GZHEADER_SIZE];
    int method, flags;
    
    gb.vf = vf;
    gb.avail = 0;
    gb.total = 0;

    res = gzbuf_read(&gb, (char*)buf, GZHEADER_SIZE);
    if(res < 0)
        return res;

    if(buf[0] != GZMAGIC1 || buf[1] != GZMAGIC2) {
        av_log(AVLOG_ERROR, "UGZ: File not in GZIP format");
        return -EIO;
    }

    method = buf[2];
    flags  = buf[3];
  
    if(method != METHOD_DEFLATE) {
        av_log(AVLOG_ERROR, "UGZ: File compression is not DEFLATE");
        return -EIO;
    }

    if(flags & GZFL_RESERVED) {
        av_log(AVLOG_ERROR, "UGZ: Unknown flags");
        return -EIO;
    }

    nod->mtime = QBYTE(buf + 4);
  
    /* Ignore bytes 8 and 9 */

    if((flags & GZFL_CONTINUATION) != 0) {
        res = gzbuf_read(&gb, (char*)buf, 2);
        if(res < 0)
            return res;
    }

    if((flags & GZFL_EXTRA_FIELD) != 0) {
        avsize_t len;

        res = gzbuf_read(&gb, (char*)buf, 2);
        if(res < 0)
            return res;

        for(len = DBYTE(buf); len; len--) {
            res = gzbuf_getbyte(&gb);
            if(res < 0)
                return res;
        }
    }

    if((flags & GZFL_ORIG_NAME) != 0) {
        res = gzbuf_skip_string(&gb);
        if(res < 0)
            return res;
    }

    if((flags & GZFL_COMMENT) != 0) {
        res = gzbuf_skip_string(&gb);
        if(res < 0)
            return res;
    }

    nod->dataoff = gb.total;

    sres = av_lseek(vf, -8, AVSEEK_END);
    if(sres < 0)
        return sres;

    res = av_read_all(vf, (char*)buf, 8);
    if(res < 0)
        return res;

    nod->crc = QBYTE(buf);
    nod->size = QBYTE(buf + 4);

    nod->ready = 1;
    
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gz_same ( struct gznode nod,
struct avstat stbuf 
) [static]

Definition at line 221 of file ugz.c.

{
    if(nod->sig.ino == stbuf->ino &&
       nod->sig.dev == stbuf->dev &&
       nod->sig.size == stbuf->size &&
       AV_TIME_EQ(nod->sig.mtime, stbuf->mtime))
        return 1;
    else
        return 0;
}

Here is the caller graph for this function:

static int gzbuf_getbyte ( struct gzbuf gb) [static]

Definition at line 67 of file ugz.c.

{
    if(gb->avail == 0) {
        avssize_t res = av_read(gb->vf, (char*)( gb->buf ), GZBUFSIZE);
        if(res < 0)
            return res;

        gb->next = gb->buf;
        gb->avail = res;
    }
    
    if(gb->avail == 0) {
        av_log(AVLOG_ERROR, "UGZ: Premature end of file");
        return -EIO;
    }
    
    gb->avail --;
    gb->total ++;
    return *gb->next ++;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gzbuf_read ( struct gzbuf gb,
char *  buf,
avsize_t  nbyte 
) [static]

Definition at line 101 of file ugz.c.

{
    for(; nbyte; nbyte--) {
        int c = gzbuf_getbyte(gb);
        if(c < 0)
            return c;

        *buf ++ = c;
    }
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int gzbuf_skip_string ( struct gzbuf gb) [static]

Definition at line 88 of file ugz.c.

{
    int c;

    do {
        c = gzbuf_getbyte(gb);
        if(c < 0)
            return c;
    } while(c != '\0');

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void gznode_destroy ( struct gznode nod) [static]

Definition at line 201 of file ugz.c.

{
    av_unref_obj(nod->cache);
    AV_FREELOCK(nod->lock);
}

Here is the call graph for this function:

Here is the caller graph for this function: