#include #include #include #include #include "tool.h" /* 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 "." */ export 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 */ export 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[0] == '~'){ snprintf (buf,sizeof(buf)-1,"%s/%s",getenv("HOME"),oldpath+1); ok = path_simplifie (buf,newp); }else 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 */ export 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