/* Gestion du fichier projet.lck Le fichier contient des lignes de texte de la forme suivante: Nom_du_programmeur Nom_du_fichier path_du_programmeur Nom_du_programmeur Nom_du_repertoire\ path_du_programmeur Le nom_du_fichier ou nom_du_r‚pertoire est l'objet qui a ‚t‚ accapar‚ par un programmeur et copi‚ dans path_du_programmeur. Les noms de fichiers ou r‚pertoires sont des path relatif au r‚pertoire des r‚f‚rences de groupe. Si un r‚pertoire a ‚t‚ accapar‚ par un programmeur, tous ce qui se trouve … l'int‚rieur de ce r‚pertoire est accapar‚ aussi. */ #include #include #include #include #include #include #include "projet.h" #include "projetx.m" /* fabrique le path du fichier */ static void near make_path( const char *groupe, /* r‚pertoire des r‚f‚rences groupes */ const char *projet, /* projet a lire */ char *path) { assert (strchr(projet,'.')==NULL); path_make (groupe,projet,path); strcat (path,LOCK_EXT); } /* Verifie si le fichier lock existe Retourne != 0 si oui, 0 sinon */ int prjlock_exist( const char *groupe, /* r‚pertoire des r‚f‚rences groupes */ const char *projet, int creation) { int ret = 0; char path[MAXSIZ_PATH]; make_path (groupe,projet,path); if (file_type (path)==0){ ret = 1; }else if (creation){ FILE *fout = fopen (path,"w"); if (fout != NULL){ fclose (fout); ret = 1; } } return ret; } /* Ouverture du fichier lock Retourne FILE * ou NULL */ static FILE * near lck_open( const char *groupe, /* r‚pertoire des r‚f‚rences groupes */ const char *projet, /* projet a lire */ const char *opt) /* option pour ouverture du fichier */ { char path[100]; make_path (groupe,projet,path); return fopen(path,opt); } /* Construit les path pour r‚pertoire et fichier s‚maphore. Cela sert … faire un lock durant les transactions sur le projet et … laisser une trace de l'auteur du lock. */ static void near prjlock_makesem ( const char *projet, const char *prog, const char *groupe, char *pathsem, char *usersem) { char nomsem[20]; sprintf (nomsem,"%s.sem",projet); path_make (groupe,nomsem,pathsem); path_make (pathsem,prog,usersem); } /* Lit le fichier de lock dans un table Retourne 0 si ok, -1 si erreur */ PUBLIC PRJLOCK::PRJLOCK ( USERINFO *_user, const char *_projet) // projet a lire { strcpy (projet,_projet); user = _user; { /* assure l'exclusivite de l'operation en cr‚ant un r‚pertoire dont le nom est le nom du projet avec extension sem */ char pathsem[MAXSIZ_PATH]; char usersem[MAXSIZ_PATH]; prjlock_makesem (projet,user->getnom(),user->getgroupe() ,pathsem,usersem); if (file_mkdir(pathsem)!=-1 || file_type(usersem)==0){ FILE *fout; fout = fopen (usersem,"w"); fclose (fout); lock_other = 0; }else{ char *tbf[2]; int nbf = dir_getlist (pathsem,"*",0,tbf,1); const char *usrlock = MSG_U(I_INCONNU,"inconnu"); char proglock[MAXSIZ_NAME]; if (nbf > 0){ path_splitlex (tbf[0],NULL,proglock); usrlock = proglock; } xconf_error (MSG_U(E_TRANSACTION ,"Transaction en cours sur le projet %s\n" "par l'usager %s") ,projet,usrlock); lock_other = 1; } } tb = NULL; nblock = 0; maxlock = 0; if (!lock_other){ tb = (ONE_LOCK*) calloc_err (3000,sizeof(ONE_LOCK),1); if (tb != NULL){ maxlock = 3000; if (prjlock_exist(user->getgroupe(),projet,0)){ FILE *fin = lck_open (user->getgroupe(),projet,"r"); if (fin != NULL){ ONE_LOCK *pt = tb; char objet[MAXSIZ_PATH]; char prog[8+1]; char path[MAXSIZ_PATH]; char locktype[2]; while (fscanf (fin,"%s %s %s %s\n" ,prog,locktype,objet,path)==4){ pt->prog = strdup_err(prog); pt->locktype = locktype[0]; pt->objet = strdup_err(objet); pt->path = strdup_err(path); pt++; nblock++; } fclose (fin); } } } } } /* libŠre espace utilis‚ par lck */ PUBLIC PRJLOCK::~PRJLOCK () { if (!lock_other){ /* Retire l'exclusivite de l'operation en d‚truisant le r‚pertoire et usager s‚maphore. */ char pathsem[MAXSIZ_PATH]; char usersem[MAXSIZ_PATH]; prjlock_makesem (projet,user->getnom(),user->getgroupe() ,pathsem,usersem); unlink (usersem); file_rmdir (pathsem); } if (tb != NULL){ ONE_LOCK *pt = tb; for (int i=0; iobjet); free (pt->prog); free (pt->path); } free (tb); } } /* ecriture du lock file sur le disque */ PUBLIC void PRJLOCK::save () { if (!lock_other){ if (nblock == 0){ char path[MAXSIZ_PATH]; make_path (user->getgroupe(),projet,path); file_unlink (path); }else{ FILE *fout = lck_open (user->getgroupe(),projet,"w"); if (fout == NULL){ xconf_error (MSG_U(E_WRITELOCK ,"Ne peut écrire le fichier lock")); }else{ ONE_LOCK *pt = tb; for (int i=0; iprog,pt->locktype,pt->objet,pt->path); } fclose (fout); } } } } /* Retourne != 0 si le projet nous a ‚t‚ temporairement allou‚ exclusivement. On peut faire des transactions sans crainte. */ PUBLIC int PRJLOCK::isok () { return !lock_other; } #ifdef TEST static void add (PRJLOCK *lck, const char *obj) { char prog[100]; char objlock[100]; int isl = prjlock_islock (lck,obj,prog,objlock); if (isl){ printf ("Conflit avec %s %s\n",prog,objlock); }else{ int ret = prjlock_add (lck,"jacques",obj,"\\usr\\jacques"); printf ("add %s -> %d\n",obj,ret); } } void main (void) { PRJLOCK lck; /* cr‚ation d'un fichier lock bidon */ FILE *fout = fopen ("projet.lck","w"); fclose (fout); if (prjlock_read (&lck,".","projet")!=-1){ static char *tb[]={ "dir\\", "dir\\toto.c", "toto.c", NULL }; int i=0; while (tb[i] != NULL){ add (&lck,tb[i]); i++; } prjlock_write (&lck); } } #endif