#include #include #include #include #include #include #include #include "vfs.h" #include #include /* Simplifie un path en eliminant les ancetres et les identite .. et . Retourne -1 si path impossible, 0 si ok Ne verifie pas sur disque si existe Si le r‚sultat est la chaine vide, remplace par "." */ int path_simplifie (const char *path, char *newp) { int ok = 0; char *debnewp = newp; char *lastvalid[20]; /* Dernier membre autre que . et .. */ int nbvalid = 0; int isabs = path_isabs (path); char tmp[MAXSIZ_PATH]; if (path == newp){ strcpy (tmp,path); path = tmp; } while (path[0] == '.' && path_issep(path[1])) path += 2; if (!path_issep(path[0]) && path[0] != '.'){ lastvalid[nbvalid++] = newp; } while (ok == 0 && *path != '\0'){ if (strncmp (path,"/./",3)==0){ path += 2; }else if (strcmp (path,"/.")==0){ *newp++ = *path; path += 2; }else if (strncmp (path,"/..",3)==0){ if (nbvalid > 0){ newp = lastvalid[--nbvalid]; /* x/../y -> y et non /y */ if (newp == debnewp && !isabs && path_issep(path[3])) path++; }else if (isabs){ ok = -1; break; }else{ newp = stpcpy (newp,"/.."); } path += 3; }else{ if (*path == '/') lastvalid[nbvalid++] = newp; *newp++ = *path++; } } *newp = '\0'; if (debnewp[0] == '\0'){ debnewp[0] = '.'; debnewp[1] = '\0'; } return ok; } /* Transforme un path en absolue et ellimine les .. et . InsŠre cwd si oldpath est relatif et ne fait pas reference a aucun disque. Si cwd == NULL, utilise le r‚pertoire courant (path_getcwd()). Si cwd != NULL, Retourne 0 si ok, -1 si path impossible Pas de verification sur disque newp peut etre le meme que path */ int path_setabs0 ( const char *cwd, /* r‚pertoire courant ou NULL */ const char *oldpath, /* path … transformer */ char *newp) /* contiendra r‚sultat */ { char *debnewp = newp; int ok = 0; { char buf[MAXSIZ_PATH]; char *path = buf; strcpy (path,oldpath); *newp = '\0'; /* au cas d'un erreur */ if (*path != '/'){ /* path relatif, il faut ins‚rer le path courant */ char buffer[MAXSIZ_PATH]; if (cwd == NULL){ /* on obtient path courant du systŠme */ ok = path_getcwd (buffer,sizeof(buffer)); }else{ /* on utilise celui fourni par l'appelant */ strcpy (buffer,cwd); } if (ok != -1){ path_addback (buffer,buffer); strcat (buffer,path); ok = path_simplifie (buffer,newp); } }else{ ok = path_simplifie (path,newp); } } path_stripsep (debnewp,debnewp); return (ok); } /* Transforme un path en absolue et ellimine les .. et . Ajoute le path courant si il est relatif Retourne 0 si ok, -1 si path impossible Pas de verification sur disque newp peut etre le meme que path */ int path_setabs (const char *oldpath, char *newp) { return (path_setabs0(NULL,oldpath,newp)); } #ifdef TEST static char *tb[]={ "../../h/./protoc.h", "../../h/toto", "..", "allo", "../allo", "allo/../toto", "./allo", "allo/../../toto", "../../../toto", "allo", "/allo", NULL }; static void near stest (char *cwd, const char *str) { char buffer[MAXSIZ_PATH]; int ok = path_setabs0 (cwd,str,buffer); if (ok == -1){ printf ("[%s]-> *** illegal ***\n",cwd==NULL?"NULL":cwd); }else{ printf ("[%s]-> %s\n",cwd==NULL?"NULL":cwd,buffer); } } static void near test (const char *str) { printf ("## %s\n",str); stest (NULL,str); stest ("/cwd",str); } static void tstsim (const char *str) { char buffer[MAXSIZ_PATH]; int ok = path_simplifie (str,buffer); if (ok == -1){ printf ("simplifie [%s]-> *** illegal ***\n",str); }else{ printf ("simplifie [%s]-> %s\n",str,buffer); } } int main (int argc, char *argv[]) { int i=0; printf ("-------------- path_simplifie --------------\n"); while (tb[i] != NULL){ tstsim (tb[i]); i++; } printf ("-------------- path_setabs0 ----------------\n"); i = 0; while (tb[i] != NULL){ test (tb[i]); i++; } } #endif /* compose un path de fichier a partir du repertoire et du fichier filepath peut etre egal a path filepath peut etre egal a name Le path est optimis‚ pour ‚liminer les retour en arriŠre etc... name peut etre NULL ou une chaine vide. */ void path_make (const char *path, const char *name, char *filepath) { if (name == NULL || name[0] == '\0'){ if (path != filepath) strcpy (filepath,path); }else if (path == NULL || path[0] == '\0'){ if (name != filepath) strcpy (filepath,name); }else{ char tempo[MAXSIZ_PATH]; strcpy (tempo,name); if (path_issep(tempo[0])){ path_stripsep(path,filepath); }else{ path_addback (path,filepath); } strcat (filepath,tempo); } path_simplifie(filepath,filepath); } #ifdef TEST static void near tst_make0 (const char *path, const char *fname) { char ret[MAXSIZ_PATH]; path_make (path,fname,ret); printf ("%s + %s -> %s\n",path,fname,ret); } static void near tst_make (const char *path) { tst_make0 (path,"*.*"); tst_make0 (path,"\\*.*"); } int main (int argc, char *argv[]) { static char *tbp[]={ "c:", "c:\\", NULL }; static char *tb[][2]={ "e:/kit/groupe", "e:/kit/groupe/vdi", "e:/kit/groupe", "e:/kit/ombre", "e:/kit/groupe", "e:/kit", "e:/kit/groupe", "e:/bc", "e:/kit/groupe", "d:/kit/ombre", NULL }; int i = 0; while (tbp[i] != NULL){ tst_make (tbp[i]); i++; } i = 0; while (tb[i][0] != NULL){ char refpath[MAXSIZ_PATH]; int ret = path_abs2rel (tb[i][1],tb[i][0],refpath); if (ret == -1){ printf ("*** %s ne peut pas ˆtre relatif … %s\n" ,tb[i][1],tb[i][0]); }else{ printf ("%s relatif … %s -> %s [%d]\n" ,tb[i][1],tb[i][0],refpath,ret); } i++; } } #endif /* D‚termine si un path est absolue. Retourne != 0 si oui. */ int path_isabs (const char *path) { return path_issep (*path); } /* Separe une chaine contenant de wildcard en plusieurs chaine *.c,*.asm,toto donne trois chaine dans tbuns[] Retourne le nombre de chaine produite. Attention : La chaine str est modifie. Les virgules sont remplacees par des '\0' */ int wild_split (char *str, char *tbuns[]) { int nbuns=0; while (*str != '\0'){ tbuns[nbuns++] = str; while (*str != '\0' && *str != ',') str++; if (*str == ',') *str++ = '\0'; } tbuns[nbuns] = NULL; return (nbuns); } #if 0 /* Change le propri‚taire d'un fichier. Retourne -1 si erreur. G‚n‚ralement, seul root peut faire ca. Si user == -1, choisit usager courant, si group == -1, choisit group courant. Fonction sp‚cifique … UNIX. */ int file_chown (const char *fname, int user, int group) { if (user == -1) user = process_getuid(); if (group == -1) group = process_getgid(); return chown (fname,user,group); } #endif /* Copie un fichier dans un autre en conservant la mˆme date Retourne 0 ou -1 si erreur Retourne 1 si copie ok, mais la date n'est pas chang‚e. */ static int copy ( const char *dirsrc, /* R‚pertoire source */ const char *dirdst, /* r‚pertoire destination */ const char *namesrc, /* Nom du fichier source ou wildcard*/ const char *namedst) /* nom du fichier destination ou NULL */ { int ok = -1; char pathsrc[MAXSIZ_PATH]; char pathdst[MAXSIZ_PATH]; path_make (dirsrc,namesrc,pathsrc); path_make (dirdst,namedst,pathdst); #if 0 consio_printf ("copy :%s: -> :%s:\n",pathsrc,pathdst); consio_keywait(); #elif defined(TEST) printf ("copy :%s: -> :%s:\n",pathsrc,pathdst); #endif { FILE *fin = fopen (pathsrc,"r"); if (fin!=NULL){ if (file_writeok(pathdst)){ FILE *fout = fopen (pathdst,"w"); if (fout != NULL){ int bufsiz = 20000; size_t nb; char *buf; while ((buf=(char*)malloc (bufsiz))==NULL){ assert (bufsiz != 0); bufsiz /=2; } ok = 0; while ((nb=fread(buf,1,bufsiz,fin))>0){ if(fwrite (buf,1,nb,fout)!=nb){ ok = -1; break; } } free (buf); fflush(fout); if (ok != -1){ struct utimbuf timbuf; struct stat stbuf; stat (pathsrc,&stbuf); timbuf.modtime = stbuf.st_mtime; timbuf.actime = stbuf.st_atime; ok = utime (pathdst,&timbuf); if (ok == -1) ok = 1; fchmod (fileno(fout),stbuf.st_mode); #if defined(TEST) extern int errno; printf ("Change date %d [%d]\n",ok,errno); #endif } fclose (fout); //file_chown (pathdst,-1,-1); } } fclose (fin); } } return ok; } /* Copie un ou une s‚rie de fichiers … partir de path d‚compos‚s Retourne nombre de fichier copi‚ si ok, -1 si erreur */ int file_copy ( const char *dirsrc, /* R‚pertoire source */ const char *dirdst, /* r‚pertoire destination */ const char *namesrc, /* Nom du fichier source ou wildcard*/ const char *namedst) /* nom du fichier destination ou NULL */ { int ok = -1; if (file_type(dirsrc)==1 && file_type(dirdst)==1){ if (file_iswild(namesrc)){ char *tbstr[400]; int nbstr = dir_getlist (dirsrc,namesrc,0,tbstr,400); int i; assert (namedst == NULL); for (i=0; iname); if (ret != -1){ int mask = buf.st_mode & S_IFMT; long size = 0; FILETYPE type = FILETYPE_REG; if (mask == S_IFREG){ size = buf.st_size; type = FILETYPE_REG; }else if (mask == S_IFDIR){ size = buf.st_size/16; type = FILETYPE_DIR; }else if (mask == S_IFCHR){ type = FILETYPE_DEVCHR; }else if (mask == S_IFBLK){ type = FILETYPE_DEVBLK; }else if (mask == S_IFIFO){ type = FILETYPE_PIPE; } info->size = size; info->type = type; info->date = buf.st_mtime; info->inode = (int)buf.st_ino; info->device = buf.st_dev; } } return ret; } /* D‚termine la longueur et la date d'un fichier ou r‚pertoire Si le fichier est un r‚pertoire, retourne le nombre maximum de fichier qu'il peut contenir retourne -1 si trouve pas le fichier, 0 si ok */ int file_info (const char *filnam, unsigned long *date, long *size) { FILEINFO info; int ret = file_statinfo (filnam,&info); if (ret != -1){ *size = info.size; *date = info.date;; } return (ret); } /* D‚termine la longueur et la date (format DOS) d'un fichier ou r‚pertoire Si le fichier est un r‚pertoire, retourne le nombre maximum de fichier qu'il peut contenir retourne -1 si trouve pas le fichier, 0 si ok */ int file_infodos (const char *filnam, unsigned long *date, long *size) { int ret = file_info(filnam,date,size); if (ret != -1){ *date = date_unix2dos (*date); } return ret; } /* Retourne la longueur d'un fichier sans l'ouvrir retourne -1 si erreur */ #if 0 long file_size (const char *filnam) { long len; unsigned long date; if (file_info(filnam,&date,&len)==-1) len = -1; return (len); } #endif /* Retourne le type d'un fichier Retourne -1 si le fichier n'existe pas. Retourne 0 si fichier ordinaire 1 si le fichier est en fait un repertoire 2 si le fichier est un character device 3 si le fichier est un block device 4 si le fichier est un pipe Ne fonctionne pas avec wild card */ int file_type (char const *pathname) { int ret = -1; if (pathname[0] == '\0' || strcmp(pathname,"/")==0){ ret = 1; }else{ struct stat buf; ret = stat ((char*)pathname,&buf); if (ret != -1){ int mask = buf.st_mode & S_IFMT; if (mask == S_IFREG){ ret = 0; }else if (mask == S_IFDIR){ ret = 1; }else if (mask == S_IFCHR){ ret = 2; }else if (mask == S_IFBLK){ ret = 3; }else if (mask == S_IFIFO){ ret = 4; } } } return ret; } /* D‚termine si un fichier (au moins un) existe Retourne != 0 si au moins un, 0 sinon Les entr‚es . et .. sont ignor‚s ainsi que les r‚pertoires. Si pathname est un r‚pertoire, c'est comme si il n'existe pas vue de cette fonction. Fonctionne avec wild card */ int vfile_exist (char const *pathname) { int ret = 0; if (file_iswild (pathname)){ char *tb[2]; int nb = dir_getlistp(pathname,0,tb,1); tbstr_free (tb,nb); ret = nb > 0; }else{ struct stat st; if (lstat(pathname,&st)!=-1){ ret = 1; } } return ret; } /* Renomme un fichier Permet aussi de relocaliser un fichier dans un autre directory Retourne 0 si ok, -1 si erreur */ int file_rename (const char *present, const char *nouveau) { int ret = -1; if (file_type(nouveau)<0){ ret = rename (present,nouveau); } return ret; } /* Change l'extension du nom d'un fichier oldfile et newfile peuvent etre identique newext peut etre vide, cela produit un fichier sans extension ni point */ void file_chgext ( const char *oldfile, /* fichier a renommer */ char *newfile, /* contiendra le r‚sultat */ const char *newext) /* extension pour remplacer celle de oldfile */ /* commence par un . ou pas */ { char *pt = newfile; char *trouve = NULL; strcpy (newfile,oldfile); /* Trouve le dernier point du path */ /* Il peut y avoir des r‚pertoire avec extension /dir/dir.1/fichier.c */ while (*pt != '\0'){ if (path_issep(*pt)) trouve = NULL; if (*pt == '.' && *(pt+1) != '/' && *(pt+1) != '.') trouve = pt; pt++; } if (trouve != NULL) pt = trouve; if (*newext != '\0'){ *pt ++ = '.'; if (*newext == '.') newext++; strcpy (pt,newext); }else{ *pt = '\0'; } } /* Renomme un fichier en ne changeant que l'extension Si un fichier possedant une telle extension existe deja, force indique si l'on doit faire l'operation tout de meme Retourne 0 si ok, -1 si erreur */ int file_renameext (const char *nomfch, const char *ext, int force) { char newnam[MAXSIZ_PATH]; int typef; file_chgext (nomfch,newnam,ext); typef = file_type(newnam); if (typef == 1 || (typef == 0 && !force)) return (-1); if (typef == 0) unlink (newnam); return (file_rename (nomfch,newnam)); } /* Compare l'extension d'un fichier avec un extension Retourne < 0, 0 ou > 0 comme strcmp */ int file_cmpext ( const char *fname, const char *extcmp) /* Extension avec ou sans point */ { char ext[MAXSIZ_EXTENSION]; file_baseext (fname,NULL,ext); if (extcmp[0] == '.') extcmp++; return strcasecmp(ext,extcmp); } #ifdef TEST #include static void tst (char *path) { int type = file_type(path); printf ("%20s --> %d",path,type); if (type != -1){ FILEINFO info; file_statinfo (path,&info); printf (" size %d date %d inode %d device %d" ,info.size,info.date,info.inode,info.device); } printf ("\n"); } static void near exist (char *name) { printf ("exist :%s: -> %s\n",name,vfile_exist(name)? "ok" : "non"); } int main (int argc, char *argv[]) { if (argc == 4 && strcmp(argv[1],"ren")==0){ printf ("Renomme :%s: -> :%s: statut %d\n",argv[2],argv[3] ,file_rename(argv[2],argv[3])); }else if (argc == 1){ exist ("*.lib"); exist ("*.c"); exist ("file.c"); printf ("file size de file.c = %ld\n",file_size("file.c")); printf ("file size de /usr/prj = %ld\n",file_size("/usr/prj")); tst (""); tst ("/tmp/tty1a.0"); tst ("/"); tst ("/usr/pierre"); tst ("/u"); tst ("/home/solucor/jack/commun.mak"); } return 0; } #endif /* A partir d'un path de fichier extrait le nom de base et l'extension base peut etre egal a fname base peut etre NULL ext peut etre NULL ext ne contiendra pas de '.'. */ /* #Specification: extension L'extension est la s‚quence qui suit le dernier point dans le nom du fichier. */ export void file_baseext (const char *fname, char *base, char *ext) { char file[MAXSIZ_PATH]; char path[MAXSIZ_PATH]; char *pt = file; char *lastpt = NULL; path_splitlex (fname,path,file); while (*pt != '\0'){ if (*pt == '.') lastpt = pt; pt++; } if (lastpt != NULL){ *lastpt++ = '\0'; }else{ lastpt = ""; } if (ext != NULL){ strcpy (ext,lastpt); } if (base != NULL) strcpy(base,file); } /* determine si un path de fichier contient des wild card Retourne != 0 si oui */ export int file_iswild (const char *fpath) { return (strchr(fpath,'*')!=NULL || strchr(fpath,'?')!=NULL); } /* fait la correspondance entre deux path de liste A partir d'un path qui contient un wild card, d'un des elements issue de ce path, et d'un autre path avec wild card, produit ce qui devrait etre element correspondant ex: *.c toto.c et *.obj -> toto.obj \prj\b*.c \prj\bonjour.c * -> onjour Il peut y avoir plusieurs etoile et ? ATTENTION : elm1 doit correspondre strictement caractŠre pour caractŠre … list1. list1="\prj\doc\*.nap" et elm1="c:\prj\doc\toto.nap" n'est pas acceptable. Retourne 0 si ok, -1 si erreur */ export int file_correspond ( const char *list1, const char *elm1, const char *list2, char *elm2) { int ok = 0; while (*list2 != '\0'){ char carac = *list2++; if (carac == '*'){ const char *pt = strchr (list1,'*'); if (pt == NULL || (pt[1] != '\0' && pt[1] != '.')){ ok = -1; break; } elm1 += (int)(pt - list1); list1 = pt+1; while (*elm1 != '\0' && *elm1 != '.'){ *elm2++ = *elm1++; } }else if (carac == '?'){ const char *pt = strchr (list1,'?'); if (pt == NULL){ ok = -1; break; } elm1 += (int)(pt - list1); list1 = pt+1; *elm2++ = *elm1++; }else{ *elm2++ = carac; } } *elm2 = '\0'; if (file_iswild(list1)) ok = -1; return (ok); } /* D‚termine si un fichier provient d'un wildcard. Il peut y avoir des wildcard mˆme dans la partie r‚pertoire. Fonction r‚cursive. Retourne != 0 si oui */ export int file_fromwild( const char *filename, const char *wildname) { int ok; if (filename[0] == '\0' || wildname[0] == '\0'){ ok = filename[0] == wildname[0]; }else{ char fpath[MAXSIZ_PATH]; char fname[MAXSIZ_NAME]; char wpath[MAXSIZ_PATH]; char wname[MAXSIZ_NAME]; WILD wild; path_splitlex (filename,fpath,fname); path_splitlex (wildname,wpath,wname); if (strcmp(filename,fpath)==0 || strcmp(wildname,wpath)==0){ /* Les paths ne sont pas divisibles d'avantage */ ok = strcmp(fpath,wpath)==0; }else{ ok = (strcmp(fpath,wpath)==0 || file_fromwild(fpath,wpath)!=0) && wild_set (wname,&wild) && wild_test (fname,&wild); } } return ok; } #ifdef TEST static struct { char *list1; char *elm1; char *list2; } tb[]={ "/usr/pierre/v3/doc/*.nai", "/usr/pierre/v3/doc/view.nai", "/usr/pierre/v3/*", "*.c", "toto.c", "*.obj", "/prj/*.*", "/prj/allo.x", "*.*", "/prj/*.*", "/prj/allo.x", "*.x", "/prj2/doc/*.nar","/prj2/doc/tool.nar", "/prj/*", NULL, }; static void near tst (char *path, char *wild) { printf ("fichier :%s: appartient … la liste :%s: -> %d\n",path,wild ,file_fromwild(path,wild)); } void main(void) { int i = 0; tst ("toto.c","*.c"); tst ("/prj/toto.c","/prj/*.c"); tst ("toto.c","*.cc"); tst ("/prj2/toto.c","/prj/*.c"); while (tb[i].list1 != NULL){ char res[MAXSIZ_PATH]; int ret = file_correspond (tb[i].list1,tb[i].elm1,tb[i].list2,res); printf ("%s , %s , %s -> ",tb[i].list1,tb[i].elm1,tb[i].list2); if (ret != -1){ printf (":%s:\n",res); }else{ printf ("*** erreur\n"); } i++; } } #endif /* Test si l'‚criture ou la cr‚ation d'un fichier est permis Retourne != 0 si ok Si le fichier existe pas, v‚rifie si le r‚pertoire existe */ export int file_writeok (const char *fname) { int ret = 0; int type = file_type (fname); if (type == 0){ ret = access (fname,2) != -1; }else if (type == -1){ /* Le fichier n'existe pas, on v‚rifie si on peut ‚crire dans le r‚pertoire */ char path[MAXSIZ_PATH]; path_splitlex (fname,path,NULL); if (path[0] == '\0'){ /* Est-ce qu'on peut ecrire dans le r‚pertoire courant */ ret = access(".",2) != -1; }else if (file_type(path) == 1){ /* Est-ce qu'on peut ecrire dans ce repertoire */ ret = access(path,2) != -1; } } return ret; } /* Change l'attribut d'‚criture d'un fichier. Change uniquement l'attribut de l'usager. Retourne -1 si erreur. */ export int file_setmode (const char *fname, int writeok) { return chmod (fname,writeok ? S_IREAD|S_IWRITE : S_IREAD); } /* 10/08/88 : Jacques Gelinas Conversion de dates */ #define cnvu(j,m,a) (((a)<<9) + (m<<5) +j) /* Retourne la date courante dans un unsigned */ export short unsigned date_currentu(void) { long curt = time(NULL); struct tm *d = localtime (&curt); return ((short unsigned) cnvu(d->tm_mday,d->tm_mon+1,d->tm_year-80)); } /* convertit un chaine ascii en data unsigned selon le format DOS La chaine est du type jj[/mm[/aa]] */ export short unsigned date_a2u (const char *date) { long curt = time(NULL); struct tm *d = localtime (&curt); short unsigned res; unsigned a,m,j; j = d->tm_mday; m = d->tm_mon+1; a = d->tm_year-80; if (isdigit(*date)){ j = atoi (date); date = str_skipdig(date); if (*date == '/'){ date++; m = atoi (date); date = str_skipdig(date); if (*date == '/'){ a = atoi (date+1)-80; } } } /* printf ("j = %d m = %d a = %d\n",j,m,a);*/ res = (short unsigned) cnvu (j,m,a); return (res); } #if 0 /* Construit un date/heure complŠte … partir d'une date et d'un temps. la date et le temps sont en format DOS. Retourne en format naturel UNIX (secondes ‚coul‚ depuis 1970). C'est le mˆme format que file_date() retourne. */ export unsigned long date_td2l(short unsigned date, short unsigned timet) { struct tm d; d.tm_hour = timet>>11; d.tm_min = (timet>>5) & 0x3f; d.tm_sec = (timet&0x1f)*2; d.tm_mday = date & 0x1f; d.tm_mon = ((date>>5) & 0xf) - 1; d.tm_year = (date>>9) + 80; /* printf ("%d/%d/%d %d:%d:%d\n",d.tm_mday,d.tm_mon,d.tm_year,d.tm_hour ,d.tm_min,d.tm_sec); */ return tool_mktime (&d); } /* Construit un date/heure complŠte … partir d'une date et d'un temps. la date et le temps sont en format DOS. Le r‚sultat est aussi en format DOS. C'est le mˆme format que file_dosdate() retourne. */ export unsigned long date_td2l_dos(short unsigned date, short unsigned time) { return ((unsigned long)date<<16)+time; } #endif /* Transforme une date en format DOS vers format UNIX. Le format DOS est une structure de bit. Le format UNIX est un d‚compte de seconde depuis 1970. */ export unsigned long date_unix2dos (unsigned long date) { struct tm *ptm = localtime ((time_t*)&date); return ((ptm->tm_year-80)<<25) + ((ptm->tm_mon+1)<<21) + (ptm->tm_mday<<16) + (ptm->tm_hour<<11) + (ptm->tm_min<<5) + (ptm->tm_sec/2); } /* Convertit une date format UNIX en ascii. Retourne le nombre de bytes plac‚s dans str. */ export int date_td2a ( long datetime, char *str, int format) /* 0=jj/mm/aa, 1 = aa/mm/jj, 2 = mm/jj/aa */ { struct tm *d = localtime (&datetime); int nb=0; if (format == 0){ nb = sprintf (str,"%02d/%02d/%02d ",d->tm_mday,d->tm_mon,d->tm_year); }else if (format == 1){ nb = sprintf (str,"%02d/%02d/%02d ",d->tm_year,d->tm_mon,d->tm_mday); }else if (format == 2){ nb = sprintf (str,"%02d/%02d/%02d " ,d->tm_mon,d->tm_mday,d->tm_year); } str += nb; nb += sprintf (str,"%02d:%02d:%02d",d->tm_hour,d->tm_min,d->tm_sec); return nb; } #ifdef TEST static void tst (char *f) { long date = file_date (f); unsigned long ddate = file_dosdate(f); long rdate = date_td2l(ddate>>16,ddate&0xffff); struct tm *d = localtime (&date); printf ("%s %d %d %d %d %d %d\n",f ,d->tm_mday,d->tm_mon,d->tm_year ,d->tm_hour,d->tm_min,d->tm_sec); d = localtime (&rdate); printf ("%s %d %d %d %d %d %d\n",f ,d->tm_mday,d->tm_mon,d->tm_year ,d->tm_hour,d->tm_min,d->tm_sec); printf ("\n"); } int main (int, char *argv[]) { short unsigned da = date_currentu(); char buf[20]; time_t tt,curt; struct tm *d; int len = date_u2a (da,buf); printf ("date[%d] = :%s:\n",len,buf); tt = date_td2l(da,time_currentu()); printf ("En seconde -> %d\n",tt); d = localtime (&tt); printf ("%d %d %d %d %d %d\n",d->tm_mday,d->tm_mon,d->tm_year ,d->tm_hour,d->tm_min,d->tm_sec); curt = time(NULL); d = localtime (&curt); printf ("%d %d %d %d %d %d\n",d->tm_mday,d->tm_mon,d->tm_year ,d->tm_hour,d->tm_min,d->tm_sec); tst ("path.c"); tst ("path1.c"); tst ("path2.c"); tst ("path3.c"); tst ("date.c"); } #endif #define cnvhu(h,m,s) (((h)<<11) + (m<<5) +s/2) /* Retourne le temps courant dans un unsigned Utilise le format de DOS */ export short unsigned time_currentu(void) { long curt = time(NULL); struct tm *d = localtime (&curt); return ((short unsigned)cnvhu(d->tm_hour,d->tm_min,d->tm_sec)); } /* InterprŠte une chaine ascii et retourne un temps unsigned selon le format DOS La chaine est du type hh[:mm[:ss]] */ export short unsigned time_a2u0 (const char *time, char separ) { unsigned h,m,s; h = m = s = 0; if (isdigit(*time)){ h = atoi (time); time = str_skipdig(time); if (*time == separ){ time++; m = atoi (time); time = str_skipdig(time); if (*time == separ){ s = atoi (time+1); } } } return ((short unsigned) cnvhu (h,m,s)); } /* InterprŠte une chaine ascii et retourne un temps unsigned selon le format DOS La chaine est du type hh[:mm[:ss]] */ export short unsigned time_a2u (const char *time) { return time_a2u0 (time,':'); } /* Convertit une temps de fichier Retourne le nombre de byte ecrit */ export int time_u2a0 (short unsigned time, char *str, char separ) { int nb = sprintf (str,"%02d%c%02d%c%02d" ,(time>>11) ,separ ,(time>>5) & 0x3f ,separ ,(time&0x1f)*2); return (nb); } /* Convertit une temps de fichier Retourne le nombre de byte ecrit */ export int time_u2a (short unsigned time, char *str) { return time_u2a0 (time,str,':'); } #ifdef TEST void main (void) { char str[20]; short unsigned int res = time_a2u("10:20"); int nb = time_u2a (res,str); printf ("nb = %d :%s:\n",nb,str); res = time_a2u("1:2"); nb = time_u2a (res,str); printf ("nb = %d :%s:\n",nb,str); res = time_currentu(); nb = time_u2a (res,str); printf ("nb = %d :%s:\n",nb,str); } #endif