Back to index

avfs  1.0.1
Classes | Functions
extfs.c File Reference
#include "archive.h"
#include "version.h"
#include "filebuf.h"
#include "parsels.h"
#include "realfile.h"
#include "runprog.h"
#include "filecache.h"
#include "cache.h"
#include "exit.h"
#include "tmpfile.h"
#include <unistd.h>
#include <fcntl.h>

Go to the source code of this file.

Classes

struct  extfsdata
struct  extfsnode
struct  extfscacheentry
struct  extfsfile

Functions

static void extfscacheentry_delete (struct extfscacheentry *cent)
static void fill_extfs_link (struct archive *arch, struct entry *ent, char *linkname)
static void extfsnode_delete (struct extfsnode *enod)
static void fill_extfs_node (struct archive *arch, struct entry *ent, struct avstat *stbuf, char *path, char *linkname)
static void insert_extfs_entry (struct archive *arch, struct avstat *stbuf, char *path, char *linkname)
static void parse_extfs_line (struct lscache *lc, char *line, struct archive *arch)
static int read_extfs_list (struct program *pr, struct lscache *lc, struct archive *arch)
static int extfs_list (void *data, ventry *ve, struct archive *arch)
static int get_key_for_node (ventry *ve, struct archfile *fil, char **resp)
static int get_extfs_file (ventry *ve, struct archfile *fil, const char *tmpfile)
static struct ext_infocreate_exts (char *line)
static avssize_t extfs_read (vfile *vf, char *buf, avsize_t nbyte)
static int extfs_open (ventry *ve, struct archfile *fil)
static int extfs_close (struct archfile *fil)
static void extfsdata_delete (struct extfsdata *info)
static int create_extfs_handler (struct vmodule *module, const char *extfs_dir, char *name)
static int extfs_init (struct vmodule *module)
int av_init_module_extfs (struct vmodule *module)

Class Documentation

struct extfsdata

Definition at line 29 of file extfs.c.

Class Members
int needbase
char * progpath
struct extfsnode

Definition at line 34 of file extfs.c.

Class Members
char * fullpath
avmutex lock
struct extfscacheentry

Definition at line 39 of file extfs.c.

Class Members
char * tmpfile
struct extfsfile

Definition at line 43 of file extfs.c.

Collaboration diagram for extfsfile:
Class Members
struct extfscacheentry * cent
int fd

Function Documentation

int av_init_module_extfs ( struct vmodule module)

Definition at line 504 of file extfs.c.

{
    return extfs_init(module);
}

Here is the call graph for this function:

static int create_extfs_handler ( struct vmodule module,
const char *  extfs_dir,
char *  name 
) [static]

Definition at line 403 of file extfs.c.

{
    int res;
    struct avfs *avfs;
    struct archparams *ap;
    struct extfsdata *info;
    struct ext_info *extlist;
    int needbase;
    int end;

    /* Creates extension list, and strips name of the extensions */
    extlist = create_exts(name);
    end = strlen(name) - 1;

    if(name[end] == ':') {
        needbase = 0;
        name[end] = '\0';
    }
    else
        needbase = 1;

    res = av_archive_init(name, extlist, AV_VER, module, &avfs);
    av_free(extlist);
    if(res < 0)
        return res;

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

    /* FIXME: If there is no basefile then cache the listing forever? */
    AV_NEW_OBJ(info, extfsdata_delete);
    ap->data = info;
    ap->parse = extfs_list;
    ap->read = extfs_read;
    ap->open = extfs_open;
    ap->close = extfs_close;

    if(!needbase)
        ap->flags |= ARF_NOBASE;
  
    info->progpath = av_stradd(NULL, extfs_dir, "/", name, NULL);
    info->needbase = needbase;
    
    av_add_avfs(avfs);

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct ext_info* create_exts ( char *  line) [static, read]

Definition at line 263 of file extfs.c.

{
    struct ext_info *exts;
    char *elist, *newelist;
    int i, n;
  
    while(*line && !isspace((unsigned char) *line)) line++;
    if(*line) *line++ = '\0';
    while(isspace((unsigned char) *line)) line++;
    elist = line;

    for(n = 0; *line && *line != '#'; n++) {
        while(*line && !isspace((unsigned char) *line)) line++;
        while(isspace((unsigned char) *line)) line++;
    }
    if(!n) return NULL;  /* No extensions */
  
    exts = av_malloc((n + 1) * sizeof(*exts) + strlen(elist) + 1);

    newelist = (char *) (&exts[n+1]);
    strcpy(newelist, elist);
  
    for(i = 0; i < n; i++) {
        exts[i].from = newelist;
        exts[i].to   = NULL;
        while(*newelist && !isspace((unsigned char) *newelist)) newelist++;
        if(*newelist) *newelist++ = '\0';
        while(isspace((unsigned char) *newelist)) newelist++;

    }
    exts[n].from = NULL;
    exts[n].to   = NULL;

    return exts;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int extfs_close ( struct archfile fil) [static]

Definition at line 386 of file extfs.c.

{
    struct extfsfile *efil = (struct extfsfile *) fil->data;

    close(efil->fd);

    av_unref_obj(efil->cent);
    av_free(efil);
    
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int extfs_init ( struct vmodule module) [static]

Definition at line 451 of file extfs.c.

{
    char *extfs_dir, *extfs_conf;
    struct filebuf *fb;
    int fd;
    int res;
    char *line;
    char *c;

    extfs_dir = av_get_config("moduledir");
    extfs_dir = av_stradd(extfs_dir, "/extfs", NULL);
    extfs_conf = av_stradd(NULL, extfs_dir, "/extfs.ini", NULL);

    fd = open(extfs_conf, O_RDONLY);
    if(fd == -1) {
        res = -errno;
        av_log(AVLOG_WARNING, "Could not open extfs config file %s: %s", 
                 extfs_conf, strerror(errno));
        av_free(extfs_conf);
        av_free(extfs_dir);
        return res;
    }
    av_free(extfs_conf);
  
    fb = av_filebuf_new(fd, 0);

    while(1) {
        res = av_filebuf_getline(fb, &line, -1);
        if(res < 0 || line == NULL)
            break;

        if (*line != '#') {
            c = line + strlen(line) - 1;
            if(*c == '\n') *c-- = '\0';

            if(*line) 
                res = create_extfs_handler(module, extfs_dir, line);
        }
        av_free(line);
        if(res < 0) 
            break;
    }
    av_unref_obj(fb);
    av_free(extfs_dir);
    
    if(res < 0)
        return res;

    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int extfs_list ( void *  data,
ventry *  ve,
struct archive arch 
) [static]

Definition at line 172 of file extfs.c.

{
    int res;
    const char *prog[4];
    struct realfile *rf;
    struct program *pr;
    struct extfsdata *info = (struct extfsdata *) data;    

    if(info->needbase) {
        res = av_get_realfile(ve->mnt->base, &rf);
        if(res < 0)
            return res;
    }
    else
        rf = NULL;
    
    prog[0] = info->progpath;
    prog[1] = "list";
    prog[2] = rf == NULL ? NULL : rf->name;
    prog[3] = NULL;

    res = av_start_program(prog, &pr);
    if(res == 0) {
        struct lscache *lc = av_new_lscache();
        res = read_extfs_list(pr, lc, arch);
        av_unref_obj(lc);
        av_unref_obj(pr);
    }
    av_unref_obj(rf);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int extfs_open ( ventry *  ve,
struct archfile fil 
) [static]

Definition at line 317 of file extfs.c.

{
    int res;
    struct extfsfile *efil;
    struct extfsnode *enod = (struct extfsnode *) fil->nod->data;
    int fd;
    char *key;
    struct extfscacheentry *cent;
    
    /* get key for extfscache */
    res = get_key_for_node(ve, fil, &key);
    if(res < 0)
        return res;

    AV_LOCK(enod->lock);
    cent = av_cache2_get(key);
    if (cent == NULL) {
        char *tmpfile;
        avoff_t tmpsize;

       /* no entry in cache so create a temporary file... */
        res = av_get_tmpfile(&tmpfile);
        if(res < 0) {
           av_free(key);
           AV_UNLOCK(enod->lock);
            return res;
       }
       res = get_extfs_file(ve, fil, tmpfile);
       if(res < 0) {
           av_free(key);
           av_del_tmpfile(tmpfile);
           AV_UNLOCK(enod->lock);
           return res;
       }

       /* ...create an object to store tmpfile */
       AV_NEW_OBJ(cent, extfscacheentry_delete);
       cent->tmpfile = tmpfile;

       /* put it in the extfscache */
       av_cache2_set(cent,key);
       AV_UNLOCK(enod->lock);

        tmpsize = av_tmpfile_blksize(tmpfile);
        if(tmpsize > 0)
            av_cache2_setsize(key, tmpsize);
    } else {
       AV_UNLOCK(enod->lock);
    }
    av_free(key);

    fd = open(cent->tmpfile, O_RDONLY);
    if(fd == -1) {
        res = -errno; 
        av_log(AVLOG_ERROR, "EXTFS: Could not open %s: %s", cent->tmpfile,
               strerror(errno));
       av_unref_obj(cent);
        return res;
    }

    AV_NEW(efil);
    efil->cent = cent;
    efil->fd = fd;

    fil->data = efil;
    
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 299 of file extfs.c.

{
    avssize_t res;
    struct archfile *fil = arch_vfile_file(vf);
    struct extfsfile *efil = (struct extfsfile *) fil->data;

    if(lseek(efil->fd, vf->ptr, SEEK_SET) == -1)
        return -errno;

    res = read(efil->fd, buf, nbyte);
    if(res == -1)
        return -errno;

    vf->ptr += res;

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void extfscacheentry_delete ( struct extfscacheentry cent) [static]

Definition at line 48 of file extfs.c.

{
    if( cent->tmpfile != NULL ) {
        av_del_tmpfile(cent->tmpfile);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void extfsdata_delete ( struct extfsdata info) [static]

Definition at line 398 of file extfs.c.

{
    av_free(info->progpath);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void extfsnode_delete ( struct extfsnode enod) [static]

Definition at line 77 of file extfs.c.

{
    av_free(enod->fullpath);
    AV_FREELOCK(enod->lock);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fill_extfs_link ( struct archive arch,
struct entry ent,
char *  linkname 
) [static]

Definition at line 55 of file extfs.c.

{
    struct entry *link;
    struct archnode *nod = NULL;

    link = av_arch_resolve(arch, linkname, 0, 0);
    if(link != NULL)
        nod = (struct archnode *) av_namespace_get(link);

    if(nod == NULL || AV_ISDIR(nod->st.mode))
        av_log(AVLOG_WARNING, "EXTFS: Illegal hard link");
    else {
        nod->st.nlink ++;
        av_namespace_set(ent, nod);
        av_ref_obj(ent);
        av_ref_obj(nod);
    }

    av_unref_obj(link);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fill_extfs_node ( struct archive arch,
struct entry ent,
struct avstat stbuf,
char *  path,
char *  linkname 
) [static]

Definition at line 83 of file extfs.c.

{
    struct archnode *nod;
    struct extfsnode *enod;
    char *s;

    nod = av_arch_new_node(arch, ent, AV_ISDIR(stbuf->mode));
        
    stbuf->dev = nod->st.dev;
    stbuf->ino = nod->st.ino;
    stbuf->nlink = nod->st.nlink;

    nod->st = *stbuf;
    nod->offset = 0;
    nod->realsize = 0;

    AV_NEW_OBJ(enod, extfsnode_delete);

    AV_INITLOCK(enod->lock);

    nod->data = enod;

    /* Fullpath should be without leading slashes */
    for(s = path; *s && *s == '/'; s++);
    enod->fullpath = av_strdup(s);

    if(AV_ISLNK(stbuf->mode))
        nod->linkname = av_strdup(linkname);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_extfs_file ( ventry *  ve,
struct archfile fil,
const char *  tmpfile 
) [static]

Definition at line 224 of file extfs.c.

{
    int res;
    struct archparams *ap = (struct archparams *) ve->mnt->avfs->data;
    struct extfsdata *info = (struct extfsdata *) ap->data;
    struct extfsnode *enod = (struct extfsnode *) fil->nod->data;
    const char *prog[6];
    struct realfile *rf;

    if(enod == NULL) {
        /* no extfsnode means someone tries to access the extfs
          archive as a file (e.g. open( "test.lha#" ) )
          Although open on a directory is not forbidden we cannot
          create an appropriate tmpfile so we return EISDIR */
        return -EISDIR;
    }
  
    if(info->needbase) {
        res = av_get_realfile(ve->mnt->base, &rf);
        if(res < 0)
            return res;
    }
    else 
        rf = NULL;
  
    prog[0] = info->progpath;
    prog[1] = "copyout";
    prog[2] = rf == NULL ? "/" : rf->name;
    prog[3] = enod->fullpath;
    prog[4] = tmpfile;
    prog[5] = NULL;
  
    res = av_run_program(prog);
    av_unref_obj(rf);

    return res;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_key_for_node ( ventry *  ve,
struct archfile fil,
char **  resp 
) [static]

Definition at line 205 of file extfs.c.

{
    struct extfsnode *enod = (struct extfsnode *) fil->nod->data;
    char *key;
    int res;

    if(enod == NULL) {
        return -EISDIR;
    }

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

    key = av_stradd(key, "/", enod->fullpath, NULL);
    *resp = key;
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void insert_extfs_entry ( struct archive arch,
struct avstat stbuf,
char *  path,
char *  linkname 
) [static]

Definition at line 115 of file extfs.c.

{
    struct entry *ent;

    if(!path[0])
        return;

    ent = av_arch_create(arch, path, 0);
    if(ent == NULL)
        return;

    /* if linkname is not null but mode is not a link
       then this should be a hard link */
    if(linkname != NULL && !AV_ISLNK(stbuf->mode)) 
        fill_extfs_link(arch, ent, linkname);
    else
        fill_extfs_node(arch, ent, stbuf, path, linkname);

    av_unref_obj(ent);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void parse_extfs_line ( struct lscache lc,
char *  line,
struct archive arch 
) [static]

Definition at line 137 of file extfs.c.

{
    int res;
    char *filename;
    char *linkname;
    struct avstat stbuf;
    
    res = av_parse_ls(lc, line, &stbuf, &filename, &linkname);
    if(res != 1)
        return;
    
    insert_extfs_entry(arch, &stbuf, filename, linkname);
    av_free(filename);
    av_free(linkname);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int read_extfs_list ( struct program pr,
struct lscache lc,
struct archive arch 
) [static]

Definition at line 154 of file extfs.c.

{
    int res;

    while(1) {
        char *line;

        res = av_program_getline(pr, &line, -1);
        if(res <= 0)
            return res;
        if(line == NULL)
            return 0;
        parse_extfs_line(lc, line, arch);
        av_free(line);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function: