/***************************************************************************** Application ASH: delete.c (c) Pierre Adriaans 1994 ------------------------------------------------------------------------------ Fonction d'effacement recursive. *****************************************************************************/ #include "ash.h" extern DIR *DummyDir; extern AnswerBoxItem_t *InfoMsg; extern CheckBoxItem_t *RecursiveStr; extern DirList_t *Current[NB_MAX_WINS], *List[NB_MAX_WINS], *Dummy; extern int AL,AfficheX,AfficheY,NbWins; extern char DummyStr[DUMMYSTR_SIZE],WorkingDir[NB_MAX_WINS][FILENAME_LENGTH]; extern InvZone_t InvZone[NB_MAX_WINS]; /***************************************************************************** DelDir() ------------------------------------------------------------------------------ Fonction d'effacement recursive d'un ss-rep: passer le nom du ss-rep a effacer. La fonction se rappelle pour tout ss-rep situe en dessous de ce ss-rep, puis efface les fichiers simples. Output: 0 si ok, -1 si operation interrompue par l'utilisateur. *****************************************************************************/ int DelDir(char *Path) { char CurrentPath[FILENAME_LENGTH], /* Spec complete ss-rep courant */ PathToDelete[FILENAME_LENGTH], /* Spec complete ss-rep a effacer */ Display[80]; /* Ligne d'affichage */ DirList_t *List = (DirList_t *)NULL, /* Contenu du ss-rep a effacer */ *Temp; /* Pointeur de parcours */ DIR *DummyDir; /* Teste l'accessibilite */ /* Boite de dialogue */ AnswerBoxItem_t *Msg = (AnswerBoxItem_t *)NULL, *Choices = (AnswerBoxItem_t *)NULL; int rc; /* Code de retour */ /* Recuperer le ss-rep courant et construire la specification complete du ss-rep a effacer */ getcwd(CurrentPath,FILENAME_LENGTH); strcpy(PathToDelete,CurrentPath); if(strcmp(PathToDelete,PATH_SEPARATOR_STR) == 0) PathToDelete[0] = 0; strcat(PathToDelete,Path); /* Tester l'accessibilite de ce ss-rep */ if((DummyDir = opendir(PathToDelete)) == (DIR *)NULL) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg,"ERROR: impossible to access the directory"); AddAnswerBoxItem(&InfoMsg,PathToDelete); InfoBox(ErrorNorm,ErrorInv," Delete ",InfoMsg,1,0,DOUBLE_FRAMED); InitAnswerBoxItem(&InfoMsg); return(0); } /* S'y placer */ chdir(PathToDelete); /* Recuperer le contenu et l'effacer */ if(Dir("*.*",&List) > 1) { /* Commencer par les ss-rep: appel recursif */ for(Temp = List; Temp != (DirList_t *)NULL; Temp = Temp->Suivant) if(IS_DIR(Temp->Info.s.st_mode) && strcmp(Temp->Info.Name,"..") != 0) { /* Interruption utilisateur ? */ if(KeyPressed()) { ReadKbd(); InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); AddAnswerBoxItem(&Msg,"Operation interrupted by user."); AddAnswerBoxItem(&Msg," Do you wish to cancel the delete cycle? "); AddAnswerBoxItem(&Choices,"Cancel"); AddAnswerBoxItem(&Choices,"Resume"); rc = AnswerBox(ConfirmNorm,ConfirmInv," Delete ",Msg,Choices, 2,0,DOUBLE_FRAMED); InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); if(rc == 1) { chdir(CurrentPath); FreeAllTheList(&List); return(-1); } } /* Appel recursif */ if(DelDir(Temp->Info.Name) == -1) return(-1); } /* Ensuite, les fichiers */ for(Temp = List; Temp != (DirList_t *)NULL; Temp = Temp->Suivant) if(!IS_DIR(Temp->Info.s.st_mode)) { /* Interruption utilisateur */ if(KeyPressed()) { ReadKbd(); InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); AddAnswerBoxItem(&Msg,"Operation interrupted by user."); AddAnswerBoxItem(&Msg," Do you wish to cancel the delete cycle? "); AddAnswerBoxItem(&Choices,"Cancel"); AddAnswerBoxItem(&Choices,"Resume"); rc = AnswerBox(ConfirmNorm,ConfirmInv," Delete ",Msg,Choices, 2,0,DOUBLE_FRAMED); InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); if(rc == 1) { chdir(CurrentPath); FreeAllTheList(&List); return(-1); } } /* Afficher le nom du fichier dans la fenetre temoin */ SetCurrentAtt(FileOpNorm); SetString(10,20,42,' '); strcpy(DummyStr,PathToDelete); if(DummyStr[strlen(DummyStr) - 1] != PATH_SEPARATOR_CHAR) strcat(DummyStr,PATH_SEPARATOR_STR); strcat(DummyStr,Temp->Info.Name); if(strlen(DummyStr) < 40) strcpy(Display,DummyStr); else { strcpy(Display,"/..."); strcat(Display,DummyStr + (strlen(DummyStr) - 33)); } WriteString(Display,FileOpNorm,10,40 - (strlen(Display) / 2)); /* Effacer */ if(unlink(Temp->Info.Name) == -1) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg,"ERROR: impossible to delete the file"); AddAnswerBoxItem(&InfoMsg,Temp->Info.Name); AddAnswerBoxItem(&InfoMsg,"from the directory"); AddAnswerBoxItem(&InfoMsg,PathToDelete); switch(errno) { case ENOLINK: case ENOENT: AddAnswerBoxItem(&InfoMsg, "The file or directory does not exist."); break; case EPERM: case EACCES: AddAnswerBoxItem(&InfoMsg,"Permission denied."); break; case EBUSY: AddAnswerBoxItem(&InfoMsg, "The entry contains a mounted file system."); break; case ETXTBSY: AddAnswerBoxItem(&InfoMsg,"Text file busy."); break; case EROFS: AddAnswerBoxItem(&InfoMsg,"The target file system in read-only."); break; case EMULTIHOP: AddAnswerBoxItem(&InfoMsg,"Multiple remote machines link."); break; default: sprintf(DummyStr,"Unknown reason (errno %d).",errno); AddAnswerBoxItem(&InfoMsg,DummyStr); } InfoBox(ErrorNorm,ErrorInv," Delete ",InfoMsg,1,0,DOUBLE_FRAMED); InitAnswerBoxItem(&InfoMsg); } } } /* Liberer la liste */ FreeAllTheList(&List); /* Remonter au ss-rep original */ chdir(CurrentPath); /* Afficher le nom du ss-rep dans le fenetre temoin */ SetCurrentAtt(FileOpNorm); SetString(10,20,42,' '); strcpy(DummyStr,CurrentPath); if(DummyStr[strlen(DummyStr) - 1] != PATH_SEPARATOR_CHAR) strcat(DummyStr,PATH_SEPARATOR_STR); strcat(DummyStr,Path + 1); if(strlen(DummyStr) < 40) strcpy(Display,DummyStr); else { strcpy(Display,"/..."); strcat(Display,DummyStr + (strlen(DummyStr) - 33)); } WriteString(Display,FileOpNorm,10,40 - (strlen(Display) / 2)); /* Le ss-rep est vide: on peut l'effacer */ if(rmdir(Path + 1) != 0) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg, "ERROR: impossible to delete the directory"); AddAnswerBoxItem(&InfoMsg,Path); AddAnswerBoxItem(&InfoMsg,"from the directory"); AddAnswerBoxItem(&InfoMsg,CurrentPath); switch(errno) { case EACCES: case EINVAL: AddAnswerBoxItem(&InfoMsg,"Permission denied."); break; case EEXIST: AddAnswerBoxItem(&InfoMsg,"The directory is not empty."); break; case ENOTDIR: AddAnswerBoxItem(&InfoMsg,"Not a directory."); break; case ENOENT: case ENOLINK: AddAnswerBoxItem(&InfoMsg,"Directory not found."); break; case EBUSY: AddAnswerBoxItem(&InfoMsg, "A file system is mounted in this directory."); break; case EROFS: AddAnswerBoxItem(&InfoMsg,"The file system is read-only."); break; case EIO: AddAnswerBoxItem(&InfoMsg,"An I/O error has occured."); break; case EMULTIHOP: AddAnswerBoxItem(&InfoMsg,"Multiple remote machines link."); break; default: sprintf(DummyStr,"Unknown reason (errno %d).",errno); AddAnswerBoxItem(&InfoMsg,DummyStr); } InfoBox(ErrorNorm,ErrorInv," Delete ",InfoMsg,1,0,DOUBLE_FRAMED); InitAnswerBoxItem(&InfoMsg); } return(0); } /***************************************************************************** Delete() ------------------------------------------------------------------------------ Fonction d'effacement. L'effacement physique n'a lieu que si l'effacement logique est le dernier lien avec le fichier !! *****************************************************************************/ void Delete(void) { int Nb, /* Nbre de fichiers a copier */ NbTag, /* Nbre de fichiers marques dans le ss-rep actif */ All = 0, /* Temoin de reponse "All" si fichier deja existant dans le ss-rep cible */ rc, /* Code de retour des boites de dialogue */ Recursive, i; /* Compteur */ /* Boites de dialogue */ AnswerBoxItem_t *Msg = (AnswerBoxItem_t *)NULL, *Choices = (AnswerBoxItem_t *)NULL; /* Recuperer le nombre de fichiers marques */ GetNbTagged(List[AL],&NbTag,&i); Nb = NbTag; /* impossible de supprimer ".." */ if((Nb == 0) && (strcmp(Current[AL]->Info.Name,"..") == 0)) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg,"The file '..' cannot"); AddAnswerBoxItem(&InfoMsg,"be deleted."); InfoBox(ErrorNorm,ErrorInv," Delete ",InfoMsg,0,0,DOUBLE_FRAMED); return; } /* Construire le message de la boite de dialogue */ if(Nb != 0) { sprintf(DummyStr,"You have selected %d files in the directory",Nb); AddAnswerBoxItem(&Msg,DummyStr); AddAnswerBoxItem(&Msg,WorkingDir[AL]); Recursive = 0; } else { if(IS_DIR(Current[AL]->Info.s.st_mode)) { AddAnswerBoxItem(&Msg," You want to delete the directory "); sprintf(DummyStr,"\"%s\"",(Current[AL]->Info.Name) + 1); AddAnswerBoxItem(&Msg,DummyStr); AddAnswerBoxItem(&Msg,"from the directory"); AddAnswerBoxItem(&Msg,WorkingDir[AL]); Recursive = 1; } else { AddAnswerBoxItem(&Msg," You want to delete the file "); sprintf(DummyStr,"\"%s\"",(Current[AL]->Info.Name)); AddAnswerBoxItem(&Msg,DummyStr); AddAnswerBoxItem(&Msg,"from the directory"); AddAnswerBoxItem(&Msg,WorkingDir[AL]); Recursive = 0; } } AddAnswerBoxItem(&Choices,"Delete"); AddAnswerBoxItem(&Choices,"Cancel"); rc = AnswerBoxCB(FileOpNorm,FileOpInv," Delete ",Msg,Choices, RecursiveStr,&Recursive,-1,0,DOUBLE_FRAMED); InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); if(rc == -1 || rc == 2) return; /* Si aucun fichier marques, on marque le fichier en inverse et on incremente le nombre de fichiers a effacer */ if(Nb == 0) { Current[AL]->Info.Tagged = 1; Nb = 1; } /* Ouvrir la fenetre temoin d'effacement */ OpenWin(7,16,6,50,FileOpNorm,UNFRAMED,SHADED); PaintWin(8,19,4,44,FileOpNorm,DOUBLE_FRAMED,UNSHADED); WriteString(" Delete ",FileOpNorm,8,37); WriteString("Deleting the file or directory",FileOpNorm,9,25); GotoXY(AfficheY,AfficheX); /* Boucle d'effacement parcourant la liste active */ for(Dummy = List[AL]; Dummy != (DirList_t *)NULL; Dummy = Dummy->Suivant) if(Dummy->Info.Tagged) { /* Afficher le nom du fichier dans la fenetre temoin */ SetCurrentAtt(FileOpNorm); SetString(10,20,42,' '); if(!IS_DIR(Dummy->Info.s.st_mode)) WriteString(Dummy->Info.Name,FileOpNorm,10, 40 - (strlen(Dummy->Info.Name) / 2)); else if(Recursive) WriteString(Dummy->Info.Name + 1,FileOpNorm,10, 40 - (strlen(Dummy->Info.Name + 1) / 2)); else { Dummy->Info.Tagged = 0; continue; } /* Touche clavier enregistree: interrompre la boucle ? */ if(KeyPressed()) { ReadKbd(); InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); AddAnswerBoxItem(&Msg,"Operation interrupted by user."); AddAnswerBoxItem(&Msg," Do you wish to cancel the delete cycle? "); AddAnswerBoxItem(&Choices,"Cancel"); AddAnswerBoxItem(&Choices,"Resume"); rc = AnswerBox(ConfirmNorm,ConfirmInv," Delete ",Msg,Choices, 2,0,DOUBLE_FRAMED); InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); if(rc == 1) break; } if(!All) { InitAnswerBoxItem(&Choices); InitAnswerBoxItem(&Msg); if(!IS_DIR(Dummy->Info.s.st_mode)) { AddAnswerBoxItem(&Msg, "WARNING: you are DELETING the file"); AddAnswerBoxItem(&Msg,Dummy->Info.Name); } else { AddAnswerBoxItem(&Msg, "WARNING: you are DELETING the directory"); AddAnswerBoxItem(&Msg,Dummy->Info.Name + 1); } AddAnswerBoxItem(&Msg,"from the directory"); AddAnswerBoxItem(&Msg,WorkingDir[AL]); AddAnswerBoxItem(&Choices,"Delete"); AddAnswerBoxItem(&Choices,"All"); AddAnswerBoxItem(&Choices,"Skip"); AddAnswerBoxItem(&Choices,"Cancel"); rc = AnswerBox(ConfirmNorm,ConfirmInv," Delete ",Msg,Choices, 2,0,DOUBLE_FRAMED); InitAnswerBoxItem(&Choices); InitAnswerBoxItem(&Msg); if(rc == 2) All = 1; if(rc == 3) continue; if(rc == 4 || rc == -1) break; } if(IS_DIR(Dummy->Info.s.st_mode)) { if(!All) { InitAnswerBoxItem(&Choices); InitAnswerBoxItem(&Msg); AddAnswerBoxItem(&Msg,"WARNING: all the files in the directory"); AddAnswerBoxItem(&Msg,(Dummy->Info.Name) + 1); AddAnswerBoxItem(&Msg,"will be deleted."); AddAnswerBoxItem(&Choices,"Delete"); AddAnswerBoxItem(&Choices,"All"); AddAnswerBoxItem(&Choices,"Skip"); AddAnswerBoxItem(&Choices,"Cancel"); rc = AnswerBox(ConfirmNorm,ConfirmInv," Delete ",Msg,Choices, 2,0,DOUBLE_FRAMED); InitAnswerBoxItem(&Choices); InitAnswerBoxItem(&Msg); if(rc == 2) All = 1; if(rc == 3) continue; if(rc == 4 || rc == -1) break; } if(DelDir(Dummy->Info.Name) == -1) break; } else if(unlink(Dummy->Info.Name) == -1) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg,"ERROR: impossible to delete the file"); AddAnswerBoxItem(&InfoMsg,Dummy->Info.Name); AddAnswerBoxItem(&InfoMsg,"from the directory"); AddAnswerBoxItem(&InfoMsg,WorkingDir[AL]); switch(errno) { case ENOLINK: case ENOENT: AddAnswerBoxItem(&InfoMsg, "The file or directory does not exist."); break; case EPERM: case EACCES: AddAnswerBoxItem(&InfoMsg,"Permission denied."); break; case EBUSY: AddAnswerBoxItem(&InfoMsg, "The entry contains a mounted file system."); break; case ETXTBSY: AddAnswerBoxItem(&InfoMsg,"Text file busy."); break; case EROFS: AddAnswerBoxItem(&InfoMsg,"The target file system in read-only."); break; case EMULTIHOP: AddAnswerBoxItem(&InfoMsg,"Multiple remote machines link."); break; default: sprintf(DummyStr,"Unknown reason (errno %d).",errno); AddAnswerBoxItem(&InfoMsg,DummyStr); } InfoBox(ErrorNorm,ErrorInv," Delete ",InfoMsg,1,0,DOUBLE_FRAMED); InitAnswerBoxItem(&InfoMsg); } /* Deselectionner le fichier venant d'etre efface */ Dummy->Info.Tagged = 0; } /* Fermeture de la fenetre temoin */ CloseWin(); /* Supprimer le faux marquage */ if(NbTag == 0) Current[AL]->Info.Tagged = 0; /* Reset affichage */ for(i=0;i