Back to index

avfs  1.0.1
utils.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 
00005     This program can be distributed under the terms of the GNU GPL.
00006     See the file COPYING.
00007 */
00008 
00009 #include "internal.h"
00010 #include "version.h"
00011 #include "oper.h"
00012 #include <stdarg.h>
00013 #include <string.h>
00014 
00015 #define NEED_VER    90
00016 
00017 /* FIXME: This is just a random value */
00018 #define AVFS_MAJOR 0xa5f
00019 
00020 static struct namespace *avfsstat_ns;
00021 
00022 struct av_obj {
00023     int refctr;
00024     void (*destr)(void *);
00025     avmutex *ref_lock;
00026     void (*destr_locked)(void *);
00027 };
00028 
00029 static AV_LOCK_DECL(objlock);
00030 
00031 int av_check_version(const char *modname, const char *name,
00032                        int version, int need_ver, int provide_ver)
00033 {
00034     if(version < need_ver || version > provide_ver) {
00035         if(version < need_ver) 
00036             av_log(AVLOG_WARNING, 
00037                      "%s: %s has version %i. Needs to be at least %i.",
00038                      modname, name, version, need_ver);
00039         else
00040             av_log(AVLOG_WARNING, 
00041                      "%s: %s has version %i. Cannot handle above %i.",
00042                      modname, name, version, provide_ver);
00043     
00044         return -ENODEV;
00045     }
00046   
00047     return 0;
00048 }
00049 
00050 static struct ext_info *copy_exts(struct ext_info *exts)
00051 {
00052     int i, num, len;
00053     struct ext_info *newexts;
00054     char *pp;
00055 
00056     if(exts == NULL)
00057         return NULL;
00058 
00059     len = 0;
00060     for(i = 0; exts[i].from != NULL; i++) {
00061         len += (strlen(exts[i].from) + 1);
00062         if(exts[i].to != NULL) len += (strlen(exts[i].to) + 1);
00063     }
00064     num = i;
00065 
00066     newexts = av_malloc((num + 1) * sizeof(*newexts) + len);
00067 
00068     pp = (char *) (&newexts[num + 1]);
00069   
00070     for(i = 0; i < num; i++) {
00071         strcpy(pp, exts[i].from);
00072         newexts[i].from = pp;
00073         pp += (strlen(pp) + 1);
00074         if(exts[i].to != NULL) {
00075             strcpy(pp, exts[i].to);
00076             newexts[i].to = pp;
00077             pp += (strlen(pp) + 1);
00078         }
00079         else newexts[i].to = NULL;
00080     }
00081     newexts[i].from = NULL;
00082     newexts[i].to = NULL;
00083 
00084     return newexts;
00085 }
00086 
00087 static void free_avfs(struct avfs *avfs)
00088 {
00089     AVFS_LOCK(avfs);
00090     avfs->destroy(avfs);
00091     AVFS_UNLOCK(avfs);
00092     
00093     av_free(avfs->name);
00094     av_free(avfs->exts);
00095 
00096     av_unref_obj(avfs->module);
00097     AV_FREELOCK(avfs->lock);
00098 }
00099 
00100 static int new_minor()
00101 {
00102     static AV_LOCK_DECL(lock);
00103     static int minor = 1;
00104     int res;
00105 
00106     AV_LOCK(lock);
00107     res = minor;
00108     minor++;
00109     AV_UNLOCK(lock);
00110 
00111     return res;
00112 }
00113 
00114 avino_t av_new_ino(struct avfs *avfs)
00115 {
00116     static AV_LOCK_DECL(lock);
00117     avino_t res;
00118 
00119     AV_LOCK(lock);
00120     res = avfs->inoctr;
00121     avfs->inoctr++;
00122     AV_UNLOCK(lock);
00123 
00124     return res;
00125 }
00126 
00127 int av_new_avfs(const char *name, struct ext_info *exts, int version,
00128                   int flags, struct vmodule *module, struct avfs **retp)
00129 {
00130     int ret;
00131     struct avfs *avfs;
00132 
00133     ret = av_check_version("CoreLib", name, version, NEED_VER, AV_VER);
00134     if(ret < 0)
00135         return ret;
00136 
00137     AV_NEW_OBJ(avfs, free_avfs);
00138     AV_INITLOCK(avfs->lock);
00139 
00140     avfs->name = av_strdup(name);
00141 
00142     avfs->exts = copy_exts(exts);
00143     avfs->data = NULL;
00144     avfs->version = version;
00145     avfs->flags = flags;
00146     avfs->module = module;
00147     avfs->dev = av_mkdev(AVFS_MAJOR, new_minor());
00148     avfs->inoctr = 2;
00149 
00150     av_ref_obj(module);
00151     
00152     av_default_avfs(avfs);
00153 
00154     *retp = avfs;
00155     return 0;
00156 }
00157 
00158 void av_init_avfsstat()
00159 {
00160     struct avfs *avfs;
00161 
00162     av_state_new(NULL, "avfsstat", &avfsstat_ns, &avfs);
00163     av_unref_obj(avfsstat_ns);
00164 }
00165 
00166 void av_avfsstat_register(const char *path, struct statefile *func)
00167 {
00168     struct entry *ent;
00169     struct statefile *stf;
00170 
00171     ent = av_namespace_resolve(avfsstat_ns, path);
00172     AV_NEW(stf);
00173 
00174     *stf = *func;
00175     av_namespace_set(ent, stf);
00176 }
00177 
00178 char *av_strdup(const char *s)
00179 {
00180     char *ns;
00181 
00182     if(s == NULL)
00183         return NULL;
00184   
00185     ns = (char *) av_malloc(strlen(s) + 1);
00186     strcpy(ns, s);
00187 
00188     return ns;
00189 }
00190 
00191 char *av_strndup(const char *s, avsize_t len)
00192 {
00193     char *ns;
00194 
00195     if(s == NULL)
00196         return NULL;
00197   
00198     ns = (char *) av_malloc(len + 1);
00199     strncpy(ns, s, len);
00200     
00201     ns[len] = '\0';
00202 
00203     return ns;
00204 }
00205 
00206 char *av_stradd(char *str, ...)
00207 {
00208     va_list ap;
00209     unsigned int origlen;
00210     unsigned int len;
00211     char *s, *ns;
00212 
00213     origlen = 0;
00214     if(str != NULL)
00215         origlen = strlen(str);
00216 
00217     len = origlen;
00218     va_start(ap, str);
00219     while((s = va_arg(ap, char*)) != NULL)
00220         len += strlen(s);
00221     va_end(ap);
00222   
00223     str = av_realloc(str, len + 1);
00224     ns = str + origlen;
00225     ns[0] = '\0';
00226     va_start(ap, str);
00227     while((s = va_arg(ap, char*)) != NULL) {
00228         strcpy(ns, s);
00229         ns += strlen(ns);
00230     }
00231     va_end(ap);
00232   
00233     return str;
00234 }
00235 
00236 void *av_new_obj(avsize_t nbyte, void (*destr)(void *))
00237 {
00238     struct av_obj *ao;
00239 
00240     ao = (struct av_obj *) av_calloc(sizeof(*ao) + nbyte);
00241     ao->refctr = 1;
00242     ao->destr = destr;
00243     ao->ref_lock = NULL;
00244     ao->destr_locked = NULL;
00245     
00246     return (void *) (ao + 1);
00247 }
00248 
00249 void av_obj_set_ref_lock(void *obj, avmutex *lock)
00250 {
00251     if(obj != NULL) {
00252         struct av_obj *ao = ((struct av_obj *) obj) - 1;
00253 
00254         ao->ref_lock = lock;
00255     }
00256 }
00257 
00258 void av_obj_set_destr_locked(void *obj, void (*destr_locked)(void *))
00259 {
00260     if(obj != NULL) {
00261         struct av_obj *ao = ((struct av_obj *) obj) - 1;
00262 
00263         ao->destr_locked = destr_locked;
00264     }
00265 }
00266 
00267 void av_ref_obj(void *obj)
00268 {
00269     if(obj != NULL) {
00270         struct av_obj *ao = ((struct av_obj *) obj) - 1;
00271         int refctr;
00272         
00273         if(ao->ref_lock != NULL) {
00274             AV_LOCK(*ao->ref_lock);
00275         } else {
00276             AV_LOCK(objlock);
00277         }
00278 
00279         if(ao->refctr > 0)
00280             ao->refctr ++;
00281         refctr = ao->refctr;
00282 
00283         if(ao->ref_lock != NULL) {
00284             AV_UNLOCK(*ao->ref_lock);
00285         } else {
00286             AV_UNLOCK(objlock);
00287         }
00288 
00289         if(refctr <= 0)
00290             av_log(AVLOG_ERROR, "Referencing deleted object (%p)", obj);
00291     }
00292 }
00293 
00294 void av_unref_obj(void *obj)
00295 {
00296     if(obj != NULL) {
00297         struct av_obj *ao = ((struct av_obj *) obj) - 1;
00298         int refctr;
00299 
00300         if(ao->ref_lock != NULL) {
00301             AV_LOCK(*ao->ref_lock);
00302         } else {
00303             AV_LOCK(objlock);
00304         }
00305 
00306         if(ao->refctr >= 0)
00307             ao->refctr --;
00308         refctr = ao->refctr;
00309         
00310         if(refctr == 0) {
00311             if(ao->destr_locked != NULL)
00312                 ao->destr_locked(obj);
00313         }
00314 
00315         if(ao->ref_lock != NULL) {
00316             AV_UNLOCK(*ao->ref_lock);
00317         } else {
00318             AV_UNLOCK(objlock);
00319         }
00320 
00321         if(refctr == 0) {
00322             if(ao->destr != NULL)
00323                 ao->destr(obj);
00324 
00325             av_free(ao);
00326             return;
00327         }
00328         else if(refctr < 0)
00329             av_log(AVLOG_ERROR, "Unreferencing deleted object (%p)", obj);
00330     }
00331 }
00332 
00333 avssize_t av_pread_all(vfile *vf, char *buf, avsize_t nbyte, avoff_t offset)
00334 {
00335     avssize_t res;
00336     
00337     res = av_pread(vf, buf, nbyte, offset);
00338     if(res < 0)
00339         return res;
00340     
00341     if(res != nbyte) {
00342         av_log(AVLOG_ERROR, "Premature end of file");
00343         return -EIO;
00344     }
00345 
00346     return res;
00347 }
00348 
00349 avssize_t av_read_all(vfile *vf, char *buf, avsize_t nbyte)
00350 {
00351     avssize_t res;
00352     
00353     res = av_read(vf, buf, nbyte);
00354     if(res < 0)
00355         return res;
00356     
00357     if(res != nbyte) {
00358         av_log(AVLOG_ERROR, "Premature end of file");
00359         return -EIO;
00360     }
00361 
00362     return res;
00363 }