Back to index

avfs  1.0.1
Functions
archive.c File Reference
#include "archint.h"
#include "namespace.h"
#include "filecache.h"
#include "internal.h"
#include "oper.h"

Go to the source code of this file.

Functions

static struct archentarch_ventry_entry (ventry *ve)
static void arch_free_tree (struct entry *parent)
static void arch_delete (struct archive *arch)
static int arch_same (struct archive *arch, struct avstat *stbuf)
static int new_archive (ventry *ve, struct archive *arch)
static int check_archive (ventry *ve, struct archive *arch, int *neednew)
static struct archivefind_archive (const char *key)
static int get_archive (ventry *ve, struct archive **archp)
static int lookup_check_node (struct entry *ent, const char *name)
static int arch_lookup (ventry *ve, const char *name, void **newp)
static void arch_putent (ventry *ve)
static int arch_copyent (ventry *ve, void **resp)
static int arch_getpath (ventry *ve, char **resp)
static int arch_real_open (int flags)
static void arch_do_close (struct archfile *fil, int realopen)
static int arch_do_open (ventry *ve, int flags, avmode_t mode, void **resp)
static int arch_open (ventry *ve, int flags, avmode_t mode, void **resp)
static int arch_close (vfile *vf)
avssize_t av_arch_read (vfile *vf, char *buf, avsize_t nbyte)
static avssize_t arch_read (vfile *vf, char *buf, avsize_t nbyte)
static struct archnodearch_special_entry (int n, struct entry *ent, char **namep)
static struct archnodearch_nth_entry (int n, struct archfile *fil, char **namep)
static int arch_readdir (vfile *vf, struct avdirent *buf)
static int arch_getattr (vfile *vf, struct avstat *buf, int attrmask)
static int arch_access (ventry *ve, int amode)
static int arch_readlink (ventry *ve, char **bufp)
static void arch_destroy (struct avfs *avfs)
int av_archive_init (const char *name, struct ext_info *exts, int version, struct vmodule *module, struct avfs **avfsp)

Function Documentation

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

Definition at line 555 of file archive.c.

{
    if((amode & AVW_OK) != 0)
        return -EACCES;

    return 0;
}

Here is the caller graph for this function:

static int arch_close ( vfile *  vf) [static]

Definition at line 404 of file archive.c.

{
    int res;
    struct archfile *fil = arch_vfile_file(vf);
    struct archive *arch = fil->arch;
    struct archparams *ap = (struct archparams *) vf->mnt->avfs->data;
    int realopen = arch_real_open(vf->flags);

    AV_LOCK(arch->lock);
    if(realopen && ap->close != NULL)
        res = ap->close(fil);
    else
        res = 0;
    arch_do_close(fil, realopen);
    AV_UNLOCK(arch->lock);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int arch_copyent ( ventry *  ve,
void **  resp 
) [static]

Definition at line 265 of file archive.c.

{
    struct archent *ae = arch_ventry_entry(ve);
    struct archent *nae;

    AV_NEW(nae);
    nae->ent = ae->ent;
    nae->arch = ae->arch;
    
    av_ref_obj(nae->ent);
    av_ref_obj(nae->arch);

    *resp = nae;
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void arch_delete ( struct archive arch) [static]

Definition at line 40 of file archive.c.

{
    struct entry *root;

    if(arch->ns != NULL) {
        root = av_namespace_subdir(arch->ns, NULL);
        arch_free_tree(root);
        av_unref_obj(root);
        av_unref_obj(arch->ns);
    }

    AV_FREELOCK(arch->lock);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void arch_destroy ( struct avfs avfs) [static]

Definition at line 589 of file archive.c.

{
    struct archparams *ap = (struct archparams *) avfs->data;

    av_unref_obj(ap->data);
    av_free(ap);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void arch_do_close ( struct archfile fil,
int  realopen 
) [static]

Definition at line 297 of file archive.c.

{
    struct archive *arch = fil->arch;
    struct archparams *ap = (struct archparams *) arch->avfs->data;

    if(realopen) {
        if(fil->basefile != NULL) {
            arch->numread --;
            if(arch->numread == 0) {
                av_close(arch->basefile);
                arch->basefile = NULL;
            }
        }

        fil->nod->numopen --;
        if(fil->nod->numopen == 0 && ap->release != NULL)
            ap->release(arch, fil->nod);
    }

    av_unref_obj(fil->arch);
    av_unref_obj(fil->nod);
    av_unref_obj(fil->ent);
    av_unref_obj(fil->curr);
    av_free(fil);
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 323 of file archive.c.

{
    int res;
    struct archent *ae = arch_ventry_entry(ve);
    struct archfile *fil;
    struct archnode *nod = (struct archnode *) av_namespace_get(ae->ent);
    struct archive *arch = ae->arch;
    struct archparams *ap = (struct archparams *) ve->mnt->avfs->data;
    vfile *basefile = NULL;
    int realopen;
   
    if(nod == NULL)
        return -ENOENT;

    if(AV_ISWRITE(flags))
        return -EROFS;

    if((flags & AVO_DIRECTORY) != 0 && !AV_ISDIR(nod->st.mode))
        return -ENOTDIR;
    
    realopen = arch_real_open(flags);
    if(realopen) {
        if(!(ap->flags & ARF_NOBASE)) {
            if(arch->basefile == NULL) {
                res = av_open(ve->mnt->base, AVO_RDONLY, 0, &arch->basefile);
                if(res < 0)
                    return res;
            }

            arch->numread ++;
            basefile = arch->basefile;
        }

        nod->numopen ++;
    }
    
    AV_NEW(fil);
    fil->basefile = basefile;
    fil->arch = arch;
    fil->nod = nod;
    fil->data = NULL;
    
    if((flags & AVO_DIRECTORY))
        fil->ent = ae->ent;
    else
        fil->ent = NULL;

    fil->curr = NULL;
    fil->currn = -1;

    av_ref_obj(fil->arch);
    av_ref_obj(fil->nod);
    av_ref_obj(fil->ent);

    if(realopen && ap->open != NULL) {
        res = ap->open(ve, fil);
        if(res < 0) {
            arch_do_close(fil, realopen);
            return res;
        }
    }

    *resp = fil;
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void arch_free_tree ( struct entry parent) [static]

Definition at line 20 of file archive.c.

{
    struct entry *ent;
    struct archnode *nod;

    ent = av_namespace_subdir(NULL, parent);
    while(ent != NULL) {
        struct entry *next;
        
        arch_free_tree(ent);
        next = av_namespace_next(ent);
        av_unref_obj(ent);
        ent = next;
    }
    
    nod = (struct archnode *) av_namespace_get(parent);
    av_unref_obj(nod);
    av_unref_obj(parent);
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 542 of file archive.c.

{
     struct archfile *fil = arch_vfile_file(vf);
     struct archnode *nod = fil->nod;
     struct archive *arch = fil->arch;
    
     AV_LOCK(arch->lock);
     *buf = nod->st;
     AV_UNLOCK(arch->lock);

     return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int arch_getpath ( ventry *  ve,
char **  resp 
) [static]

Definition at line 281 of file archive.c.

{
    struct archent *ae = arch_ventry_entry(ve);
    
    *resp = av_namespace_getpath(ae->ent);

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 200 of file archive.c.

{
    int res;
    int type;
    struct archent *ae = arch_ventry_entry(ve);
    struct entry *ent;
    struct archive *arch;
 
    if(ae == NULL) {
        if(name[0] != '\0')
            return -ENOENT;

        AV_NEW(ae);
        ae->ent = NULL;
        res = get_archive(ve, &arch);
        if(res < 0) {
            av_free(ae);
            return res;
        }
        ae->arch = arch;
    }
    else {
        arch = ae->arch;
        AV_LOCK(arch->lock);
        res = lookup_check_node(ae->ent, name);
        if(res < 0) {
            AV_UNLOCK(arch->lock);
            return res;
        }
    }

    ent = av_namespace_lookup_all(arch->ns, ae->ent, name);
    av_unref_obj(ae->ent);
    if(ent == NULL) {
        av_unref_obj(ae->arch);
        av_free(ae);
        ae = NULL;
        type = 0;
    }
    else {
        struct archnode *nod = (struct archnode *) av_namespace_get(ent);

        if(nod != NULL)
            type = AV_TYPE(nod->st.mode);
        else
            type = 0;

        ae->ent = ent;        
    }
    AV_UNLOCK(arch->lock);

    *newp = ae;
    return type;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct archnode* arch_nth_entry ( int  n,
struct archfile fil,
char **  namep 
) [static, read]

Definition at line 489 of file archive.c.

{
    struct entry *ent;
    struct archnode *nod;

    if(n  < 2)
        return arch_special_entry(n, fil->ent, namep);
    
    n -= 2;
    if(n == 0 || fil->currn != n - 1)
       ent = av_namespace_nth(NULL, fil->ent, n);
    else
       ent = av_namespace_next(fil->curr);

    av_unref_obj(fil->curr);
    fil->curr = ent;
    fil->currn = n;

    if(ent == NULL)
        return NULL;

    *namep = av_namespace_name(ent);
    nod = (struct archnode *) av_namespace_get(ent);

    return nod;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 390 of file archive.c.

{
    int res;
    struct archent *ae = arch_ventry_entry(ve);
    struct archive *arch = ae->arch;
 
    AV_LOCK(arch->lock);
    res = arch_do_open(ve, flags, mode, resp);
    AV_UNLOCK(arch->lock);
    
    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void arch_putent ( ventry *  ve) [static]

Definition at line 255 of file archive.c.

{
    struct archent *ae = arch_ventry_entry(ve);

    av_unref_obj(ae->ent);
    av_unref_obj(ae->arch);

    av_free(ae);
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 447 of file archive.c.

{
    avssize_t res;
    struct archfile *fil = arch_vfile_file(vf);
    struct archive *arch = fil->arch;
    struct archparams *ap = (struct archparams *) vf->mnt->avfs->data;
    
    AV_LOCK(arch->lock);
    if(AV_ISDIR(fil->nod->st.mode))
       res = -EISDIR;
    else
       res =  ap->read(vf, buf, nbyte);
    AV_UNLOCK(arch->lock);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int arch_readdir ( vfile *  vf,
struct avdirent buf 
) [static]

Definition at line 517 of file archive.c.

{
    int res;
    struct archfile *fil = arch_vfile_file(vf);
    struct archive *arch = fil->arch;
    struct archnode *nod;
    char *name;

    AV_LOCK(arch->lock);
    nod = arch_nth_entry(vf->ptr, fil, &name);
    if(nod == NULL)
        res = 0;
    else {
        buf->name = name;
        buf->ino = nod->st.ino;
        buf->type = AV_TYPE(nod->st.mode);
        
        vf->ptr ++;
        res = 1;
    }
    AV_UNLOCK(arch->lock);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int arch_readlink ( ventry *  ve,
char **  bufp 
) [static]

Definition at line 563 of file archive.c.

{
    int res;
    struct archent *ae = arch_ventry_entry(ve);
    struct archnode *nod;
    struct archive *arch = ae->arch;

    AV_LOCK(arch->lock);
    nod = (struct archnode *) av_namespace_get(ae->ent);
    if(nod == NULL)
        res = -ENOENT;
    else if(!AV_ISLNK(nod->st.mode))
        res = -EINVAL;
    else if(nod->linkname == NULL) {
       av_log(AVLOG_ERROR, "ARCH: linkname is NULL");
       res = -EIO;
    }
    else {
        *bufp = av_strdup(nod->linkname);
        res = 0;
    }
    AV_UNLOCK(arch->lock);    

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int arch_real_open ( int  flags) [static]

Definition at line 289 of file archive.c.

{
    if((flags & AVO_DIRECTORY) == 0 && (flags & AVO_ACCMODE) != AVO_NOPERM)
        return 1;
    else
        return 0;
}

Here is the caller graph for this function:

static int arch_same ( struct archive arch,
struct avstat stbuf 
) [static]

Definition at line 54 of file archive.c.

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

Here is the caller graph for this function:

static struct archnode* arch_special_entry ( int  n,
struct entry ent,
char **  namep 
) [static, read]

Definition at line 464 of file archive.c.

{
    struct archnode *nod;

    if(n == 0) {
        *namep = av_strdup(".");
        nod = (struct archnode *) av_namespace_get(ent);
        return nod;
    }
    else {
        struct entry *parent;

        *namep = av_strdup("..");
        parent = av_namespace_parent(ent);
        if(parent != NULL)
            nod = (struct archnode *) av_namespace_get(parent);
        else
            nod = (struct archnode *) av_namespace_get(ent);

        av_unref_obj(parent);
        return nod;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct archent* arch_ventry_entry ( ventry *  ve) [static, read]

Definition at line 15 of file archive.c.

{
    return (struct archent *) ve->data;
}

Here is the caller graph for this function:

avssize_t av_arch_read ( vfile *  vf,
char *  buf,
avsize_t  nbyte 
)

Definition at line 423 of file archive.c.

{
    int res;
    avoff_t realoff;
    struct archfile *fil = arch_vfile_file(vf);
    struct archnode *nod = fil->nod;
    avsize_t nact;

    if(AV_ISDIR(nod->st.mode))
        return -EISDIR;

    if(nbyte == 0 || vf->ptr >= nod->realsize)
        return 0;

    realoff = vf->ptr + nod->offset;
    nact = AV_MIN(nbyte, (avsize_t) (nod->realsize - vf->ptr));

    res = av_pread(fil->basefile, buf, nact, realoff);
    if(res > 0)
        vf->ptr += res;

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int av_archive_init ( const char *  name,
struct ext_info exts,
int  version,
struct vmodule module,
struct avfs **  avfsp 
)

Definition at line 598 of file archive.c.

{
    int res;
    struct avfs *avfs;
    struct archparams *ap;

    res = av_new_avfs(name, exts, version, AVF_NOLOCK, module, &avfs);
    if(res < 0)
        return res;

    avfs->lookup    = arch_lookup;
    avfs->putent    = arch_putent;
    avfs->copyent   = arch_copyent;
    avfs->getpath   = arch_getpath;
    avfs->open      = arch_open;
    avfs->close     = arch_close;
    avfs->read      = arch_read;
    avfs->readdir   = arch_readdir;
    avfs->getattr   = arch_getattr;
    avfs->access    = arch_access;
    avfs->readlink  = arch_readlink;
    avfs->destroy   = arch_destroy;

    AV_NEW(ap);
    ap->data = NULL;
    ap->flags = 0;
    ap->parse = NULL;
    ap->open = NULL;
    ap->close = NULL;
    ap->read = av_arch_read;
    ap->release = NULL;

    avfs->data = ap;

    *avfsp = avfs;
    
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int check_archive ( ventry *  ve,
struct archive arch,
int *  neednew 
) [static]

Definition at line 104 of file archive.c.

{
    int res;
    struct archparams *ap = (struct archparams *) ve->mnt->avfs->data;
    struct avstat stbuf;
    int attrmask = AVA_INO | AVA_DEV | AVA_SIZE | AVA_MTIME;
    
    if((ap->flags & ARF_NOBASE) != 0)
        return 0;

    res = av_getattr(ve->mnt->base, &stbuf, attrmask, 0);
    if(res < 0)
        return res;

    if(!arch_same(arch, &stbuf))
        *neednew = 1;

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct archive* find_archive ( const char *  key) [static, read]

Definition at line 124 of file archive.c.

{
    struct archive *arch;
    static AV_LOCK_DECL(lock);

    AV_LOCK(lock);
    arch = (struct archive *) av_filecache_get(key);
    if(arch == NULL) {
        AV_NEW_OBJ(arch, arch_delete);
        AV_INITLOCK(arch->lock);
        arch->flags = 0;
        arch->ns = NULL;
        arch->numread = 0;
        av_filecache_set(key, arch);
    }
    AV_UNLOCK(lock);

    return arch;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_archive ( ventry *  ve,
struct archive **  archp 
) [static]

Definition at line 144 of file archive.c.

{
    int res;
    char *key;
    struct archive *arch = NULL;
    int neednew;
    int tries;

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

    tries = 0;
    do {
        if(tries > 5) {
            av_log(AVLOG_ERROR, "ARCH: Giving up trying to create archive");
            res = -EIO;
            break;
        }
        arch = find_archive(key);

        neednew = 0;
        AV_LOCK(arch->lock);
        if(!(arch->flags & ARCHF_READY))
            res = new_archive(ve, arch);
        else
            res = check_archive(ve, arch, &neednew);
        if(res < 0 || neednew) {
            AV_UNLOCK(arch->lock);
            av_unref_obj(arch);
            av_filecache_set(key, NULL);
        }
        tries ++;
    } while(neednew);

    av_free(key);
    if(res < 0)
        return res;

    *archp = arch;
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int lookup_check_node ( struct entry ent,
const char *  name 
) [static]

Definition at line 187 of file archive.c.

{
    struct archnode *nod = (struct archnode *) av_namespace_get(ent);
    
    if(nod == NULL)
        return -ENOENT;
    
    if(name != NULL && !AV_ISDIR(nod->st.mode))
        return -ENOTDIR;

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int new_archive ( ventry *  ve,
struct archive arch 
) [static]

Definition at line 65 of file archive.c.

{
    int res;
    struct archparams *ap = (struct archparams *) ve->mnt->avfs->data;
    struct entry *root;
    struct avstat stbuf;

    arch->avfs = ve->mnt->avfs;

    if(!(ap->flags & ARF_NOBASE)) {
        res = av_getattr(ve->mnt->base, &arch->st, AVA_ALL & ~AVA_SIZE, 0);
        if(res < 0)
            return res;
    }
    
    arch->ns = av_namespace_new();
    root = av_namespace_lookup(arch->ns, NULL, "");
    av_arch_default_dir(arch, root);
    av_unref_obj(root);

    res = ap->parse(ap->data, ve, arch);
    if(res < 0)
        return res;

    if(!(ap->flags & ARF_NOBASE)) {
        /* The size is only requested _after_ the parse, so bzip2 &
           al. won't suffer. */
        res = av_getattr(ve->mnt->base, &stbuf, AVA_SIZE, 0);
        if(res < 0)
            return res;
    }

    arch->st.size = stbuf.size;

    arch->flags |= ARCHF_READY;

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function: