/* Usage transparent des r‚pertoires virtuels En utilisant les fonctions vdir_xxxx() plutot que les fonctions dir_xxxxx et file_xxxx du projet tool, on rend l'usage des makefile.dat pratiquement invisible. Ce module essai de retenir les 10 derniers FILEDIR pour activer le traitement. */ #include #include #include #include #include #include "vfs.h" #define NB_VDIR 20 typedef struct { FILEDIR fdir; /* Contenu du fichier makefile.dat */ char abspath[PATH_MAX]; unsigned usage; /* Permet d'‚liminer celui qui ne sert plus */ } VDIRS; static VDIRS tbdir[NB_VDIR]; static int nbdir=0; static volatile char *vdir_refpath=NULL; #ifdef OLDSTUFF /* Enregistre le r‚pertoire pour complŠter les paths relatif du makefile.dat. */ static void vdir_setrelatif (const char *path) { free ((void*)vdir_refpath); vdir_refpath = strdup (path); } #endif static void vdir_getreel ( VFILE_SPEC *vf, char *pathreel) { if (pathreel != NULL){ strcpy (pathreel,vf->relpath); if (pathreel[0] == '$' && pathreel[1] == '('){ /* Il y a une macro au d‚but, on remplace. */ macrodir_repl (pathreel,pathreel); }else if (!path_isabs(pathreel) && vdir_refpath != NULL){ path_make ((const char *)vdir_refpath,pathreel,pathreel); } /* #Sp‚cification: vdir / localise / unzip AprŠs avoir localis‚ un fichier dans le makefile.dat on v‚rifie toujours si le fichier est pr‚sent sur disque. Si ce n'est le cas, on assume que le fichier est dans un fichier pack.zip du r‚pertoire ancˆtre. On commande silencieusement le unzip. Le stdout du unzip est redirige sur stderr pour eviter de confondre avec le stdout de la commande courante. */ if (!vfile_exist(pathreel)){ char zippath[PATH_MAX]; char sdir[PATH_MAX+PATH_MAX+1]; SAVEPATH save; char fname[PATH_MAX]; path_splitlex (pathreel,zippath,fname); path_splitlex (zippath,zippath,sdir); if (path_pushdir (zippath,&save)!=-1){ int protege = -1; path_make(sdir,fname,sdir); { char buf[1000]; sprintf (buf,"unzip pack %s",sdir); system (buf); } if (protege != -1){ dup2(protege,1); close (protege); } path_popdir (&save); } } } } /* Initialise le FILEDIR pour un r‚pertoire. Consulte la table tbdir pour v‚rifier si le r‚pertoire n'y est pas d‚j…. Si ce n'est pas le cas, fait de la place dans la table et ajoute ce r‚pertoire. Retourne toujours une valeur ok. Attention, l'appelant ne doit pas conserver le r‚sultat trop longtemps puisque les FILEDIR font partie d'une table et que le moins utilis‚ cŠdera la place pour une nouvelle demande. */ static FILEDIR *vdir_setup ( const char *path, int decomp, /* Doit d‚composer le path */ /* car il repr‚sente un ‚l‚ment du r‚pertoire */ /* … consulter plutot que le r‚pertoire lui-mˆme */ char *name) /* Recueillera le nom extrait du path */ /* Contiendra '\0' si decomp = 0 */ /* Peut etre NULL */ { VDIRS *selvdir=NULL; /* Contiendra l'entr‚e s‚lectionn‚ */ VDIRS *ptdir = tbdir; static unsigned alloc_usage = 0; int i; char abspath[PATH_MAX]; path_setabs (path,abspath); if (name != NULL) name[0] = '\0'; if (decomp) path_splitlex (abspath,abspath,name); for (i=0; iabspath,abspath)==0){ selvdir = ptdir; break; } } if (selvdir == NULL){ if (nbdir < NB_VDIR){ /* Il y a de la place … la fin de la table */ selvdir = tbdir + nbdir++; }else{ /* On doit libŠrer une entr‚e */ unsigned minusage = 65000u; ptdir = tbdir; /* On trouve l'entr‚e qui sert la moins souvent. */ for (i=0; iusage < minusage){ minusage = ptdir->usage; selvdir = ptdir; } } filedir_end (&selvdir->fdir); } { char datpath[PATH_MAX]; char delpath[PATH_MAX]; path_make (abspath,"makefile.del",delpath); path_make (abspath,"makefile.dat",datpath); strcpy (selvdir->abspath,abspath); if (file_type(abspath)!=1 && *path_skipabs(abspath) != '\0'){ /* Le r‚pertoire n'existe pas, il faut utiliser une combinaison de makefile.dat pour retrouver la v‚ritable location du makefile.dat s'il existe. */ FILEDIR *fdir; VFILE_SPEC *spec; char relpath[PATH_MAX]; selvdir->usage = alloc_usage; /* Usage r‚cursif, protŠge */ fdir = vdir_setup (abspath,1,relpath); strcat (relpath,"/makefile.dat"); spec = filedir_locate (fdir,relpath); if (spec != NULL){ vdir_getreel(spec,datpath); }else{ path_make (abspath,"makefile.dat",datpath); } } filedir_init (&selvdir->fdir,datpath,delpath); } } if (alloc_usage > 65000){ /* On remet tous les usage … 0. C'est pas trŠs juste, mais trŠs simple. Une fois … tous les 65000 accŠs, la performance va diminuer. La vrai solution serait de r‚allouer les usages tout en conservant l'ordre. C'est plus compliqu‚ et ‡a donne pas grand chose. */ ptdir = tbdir; for (i=0; iusage = 0; alloc_usage = 0; } selvdir->usage = ++alloc_usage; return &selvdir->fdir; } #ifdef OLDSTUFF /* LibŠre m‚moire associ‚ au r‚pertoires virtuels. Appel‚ cette fonction ne changera pas le r‚sultat d'un programme mais pourra le ralentir. */ void vdir_free (void) { int i; VDIRS *ptdir = tbdir; for (i=0; ifdir); } nbdir = 0; macrodir_free(); } #endif /* D‚termine le path réel (si existe) d'un fichier pas présent physiquement. Retourne != 0 si oui. */ static int vdir_locate ( const char *fname, char *pathreel) /* Peut ˆtre NULL */ { int ret = 0; char name[PATH_MAX]; FILEDIR *fdir = vdir_setup (fname,1,name); VFILE_SPEC *vf = filedir_locate (fdir,name); if (vf != NULL){ ret = 1; vdir_getreel (vf,pathreel); } return ret; } /* Efface un fichier logiquement du makefile.dat (touche pas vraiment au makefile.dat) Retourne -1 si le fichier ne faisait pas partie du makefile.dat */ int vdir_unlink ( const char *fname) { char name[PATH_MAX]; FILEDIR *fdir = vdir_setup (fname,1,name); return filedir_unlink (fdir,name); } /* D‚termine si un fichier existe et son path r‚el. Retourne != 0 si oui. ( Retourne 1 si fichier pr‚sent localement, 2 si fichier pr‚sent dans KITOMBRE ). */ int vdir_exist ( const char *fname, char *pathreel) /* Peut ˆtre NULL */ { int ret = vfile_exist (fname); if (ret){ ret = 1; if (pathreel != NULL) strcpy (pathreel,fname); }else{ ret = vdir_locate(fname,pathreel); if (ret) ret = 2; } return ret; } #ifdef OLDSTUFF /* D‚termine le type d'un fichier */ int vdir_ftype ( const char *fname, char *pathreel) /* Peut ˆtre NULL ou mˆme que fname */ { int ret = file_type (fname); if (ret != -1){ if (pathreel != NULL) strcpy (pathreel,fname); }else{ /* D‚termine si c'est un fichier dans le makefile.dat Les sous-r‚pertoires ne sont jamais virtualiser. Il sont toujours localement pr‚sent. */ char name[PATH_MAX]; FILEDIR *fdir = vdir_setup (fname,1,name); VFILE_SPEC *vf = filedir_locate (fdir,name); if (vf != NULL){ ret = 0; vdir_getreel (vf,pathreel); } } return ret; } /* Retrouve information de base sur un fichier. Retourne -1 si le fichier existe pas. */ static int vdir_infodos ( const char *fname, char *pathreel, /* Peut ˆtre NULL ou meme que fname */ unsigned long *date, /* Date format natif */ long *size) { int ret = file_infodos (fname,date,size); char reel[PATH_MAX]; if (pathreel == NULL) pathreel = reel; if (ret != -1){ if (pathreel != fname) strcpy (pathreel,fname); }else{ /* D‚termine si c'est un fichier dans le makefile.dat */ char name[PATH_MAX]; FILEDIR *fdir = vdir_setup (fname,1,name); VFILE_SPEC *vf = filedir_locate (fdir,name); if (vf != NULL){ vdir_getreel (vf,pathreel); ret = file_infodos (pathreel,date,size); *date = vf->date; } } return ret; } /* Retourne la date d'un fichier (r‚pertoire virtuel). Retourne 0 si le fichier existe pas. C'est sensiblement mˆme traitement que vdir_info sauf que c'est la date en format DOS qui est requise. Pour optimiser le code a ‚t‚ un peu duplicat‚. */ unsigned long vdir_dosdate ( const char *fname, char *pathreel) /* Peut ˆtre NULL ou mˆme que fname */ { unsigned long date = file_dosdate (fname); char reel[PATH_MAX]; if (pathreel == NULL) pathreel = reel; if (date != 0){ if (pathreel != fname) strcpy (pathreel,fname); }else{ /* D‚termine si c'est un fichier dans le makefile.dat */ char name[PATH_MAX]; FILEDIR *fdir = vdir_setup (fname,1,name); VFILE_SPEC *vf = filedir_locate (fdir,name); if (vf != NULL){ vdir_getreel (vf,pathreel); date = vf->date; } } return date; } /* Retourne la dimension d'un fichier (r‚pertoire virtuel). Retourne -1 si le fichier existe pas. */ long vdir_size( const char *fname, char *pathreel) /* Peut ˆtre NULL ou mˆme que fname */ { long size = -1; unsigned long date; if (vdir_infodos (fname,pathreel,&date,&size) == -1){ date = (unsigned long)-1; } return size; } #endif #ifdef TEST int main (int argc, char *argv[]) { int i; for (i=1; i %s\n",arg,path); }else{ printf ("%s existe pas\n",arg); } printf ("ftype(%s) -> %d\n",arg,vdir_ftype(arg,NULL)); } return 0; } #endif /* Obtient la liste des fichiers correspondant … fwild Retourne le nombre plac‚ dans tb. L'appelant est responsable de lib‚r‚ les ‚l‚ments dans tb[]. */ export int vdir_getlist( const char *path, const char *wild, char *tb[], int maxtb) { FILEDIR *fdir = vdir_setup(path,0,NULL); return filedir_getlist (fdir,wild,tb,maxtb,path); } /* Obtient la liste des fichiers correspondant … fwild Retourne le nombre plac‚ dans tb. L'appelant est responsable de lib‚r‚ les ‚l‚ments dans tb[]. */ export int vdir_getlistp(const char *fwild, char *tb[], int maxtb) { char addpath[MAXSIZ_PATH]; char wild[MAXSIZ_NAME]; path_splitlex (fwild,addpath,wild); return vdir_getlist (addpath,wild,tb,maxtb); } #ifdef OLDSTUFF /* Obtient la liste des sous-r‚pertoire correspondant … fwild Retourne le nombre plac‚ dans tb. L'appelant est responsable de lib‚r‚ les ‚l‚ments dans tb[]. */ export int vdir_getlistd( const char *path, const char *wild, char *tb[], int maxtb) { FILEDIR *fdir = vdir_setup(path,0,NULL); return filedir_getlistd (fdir,wild,tb,maxtb,path); } /* Obtient la liste des sous-r‚pertoires correspondant … fwild Retourne le nombre plac‚ dans tb. L'appelant est responsable de lib‚r‚ les ‚l‚ments dans tb[]. */ export int vdir_getlistdp(const char *fwild, char *tb[], int maxtb) { char addpath[MAXSIZ_PATH]; char wild[MAXSIZ_NAME]; path_splitlex (fwild,addpath,wild); return vdir_getlistd (addpath,wild,tb,maxtb); } #endif #ifdef TEST #include #include unsigned int _stklen=10000; static void near tst_exist (const char *fname) { char reel[MAXSIZ_PATH]; int type; if (vdir_exist (fname,reel)){ printf ("%s existe -> %s\n",fname,reel); }else{ printf ("%s existe pas\n",fname); } type = vdir_ftype (fname,reel); if (type != -1){ printf ("%s type %d -> %s\n",fname,type,reel); }else{ printf ("%s existe pas\n",fname); } } int main (int argc, char *argv[]) { int i; char *tb[200]; int nb = vdir_getlistp ("e:\\kit\\build\\_1_0\\adm\\projet\\*.c",tb,200); for (i=0; i