/***************************************************************************** Application ASH: move.c (c) Pierre Adriaans 1994 ------------------------------------------------------------------------------ Fonction de deplacement. *****************************************************************************/ #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]; /***************************************************************************** Move() ------------------------------------------------------------------------------ Fonction de deplacement. Voir Copy(). Peut deplacer des ss-rep non vides, c'est une fonctionnalite de rename(). *****************************************************************************/ void Move(void) { char Target[PATH_LENGTH + 1], /* Cible proposee dans l'Input Box */ CopyMsg[80], /* Message de l'Input Box */ InFile[FILENAME_LENGTH], /* Specification complete du fichier source */ OutFile[FILENAME_LENGTH], /* Specification complete du fichier destinnation */ DestFile[FILENAME_LENGTH], TargetDir[FILENAME_LENGTH]; /* Ss-rep cible du deplacement */ int Nb, /* Nbre de fichiers a delacer */ 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 */ i, /* Compteur */ Recursive, TWin; /* Numero de la fenetre cible du deplacement */ struct stat s; /* Recupere les caracteristiques du fichier source */ /* Boites de dialogue */ AnswerBoxItem_t *Msg = (AnswerBoxItem_t *)NULL, *Choices = (AnswerBoxItem_t *)NULL; ListBoxItem_t *TargetList = (ListBoxItem_t *)NULL; /* Recuperer le nombre de fichiers marques */ GetNbTagged(List[AL],&NbTag,&i); Nb = NbTag; if(Nb == 0 && strcmp(Current[AL]->Info.Name,"..") == 0) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg,"The file '..' cannot"); AddAnswerBoxItem(&InfoMsg,"be moved anywhere."); InfoBox(ErrorNorm,ErrorInv," Move/Rename ",InfoMsg,0,0,DOUBLE_FRAMED); return; } /* Determiner la destination presumee du deplacement: - si deux fenetres, c'est la fenetre opposee - sinon, proposer une boite de liste avec les destinations possibles */ if(NbWins == 2) { TWin = !AL; strcpy(Target,WorkingDir[TWin]); } else { for(i=0;iInfo.s.st_mode)) { if(strlen(Current[AL]->Info.Name + 1) < 45) strcpy(DummyStr,Current[AL]->Info.Name + 1); else { strcpy(DummyStr,"/..."); strcat(DummyStr,Current[AL]->Info.Name + (strlen(Current[AL]->Info.Name) - 38)); } Recursive = 1; } else { if(strlen(Current[AL]->Info.Name) < 45) strcpy(DummyStr,Current[AL]->Info.Name); else { strcpy(DummyStr,"/..."); strcat(DummyStr,Current[AL]->Info.Name + (strlen(Current[AL]->Info.Name) - 38)); } Recursive = 0; } sprintf(CopyMsg,"Move/Rename \"%s\" to",DummyStr); } /* Saisir la cible */ if(InputBoxCB(Target,PATH_LENGTH,FileOpNorm,FileOpInv," Move/Rename ",CopyMsg, RecursiveStr,&Recursive,0,0,DOUBLE_FRAMED) != 0) return; /* Si aucun fichier marques, on marque le fichier en inverse et on incremente le nombre de fichiers a deplacer */ if(Nb == 0) { Current[AL]->Info.Tagged = 1; Nb = 1; } /* Scanner la cible pour des wildcards, qui sont interdites */ if(strchr(Target,'*') != NULL || strchr(Target,'?') != NULL) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg,"You cannot use wildcards"); AddAnswerBoxItem(&InfoMsg,"to specify a move/rename target."); InfoBox(ErrorNorm,ErrorInv," Move/Rename ",InfoMsg,0,0,DOUBLE_FRAMED); if(NbTag == 0) Current[AL]->Info.Tagged = 0; return; } /* Analyse de la cible */ if(NbTag > 0) { /* deplacement de plusieurs fichiers: la cible doit etre un ss-rep */ if(stat(Target,&s) != 0 || !IS_DIR(s.st_mode)) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg,"ERROR: Invalid target specification:"); sprintf(DummyStr,"\"%s\"",Target); AddAnswerBoxItem(&InfoMsg,DummyStr); AddAnswerBoxItem(&InfoMsg, "The target directory doesn't exist or cannot be accessed,"); AddAnswerBoxItem(&InfoMsg, "or you're trying to move/rename multiple files to a single one."); InfoBox(ErrorNorm,ErrorInv," Move/Rename ",InfoMsg,0,0,DOUBLE_FRAMED); return; } else strcpy(TargetDir,Target); } else { /* Copie d'un fichier ou d'un ss-rep */ if(stat(Target,&s) == 0) { /* La cible existe: directory ou fichier ? */ if(IS_DIR(s.st_mode)) { strcpy(DestFile,Current[AL]->Info.Name); /* Chercher le ss-rep cible dans le ss-rep courant */ for(Dummy = List[AL]; Dummy != (DirList_t *)NULL && strcmp((Dummy->Info.Name) + 1,Target) != 0; Dummy = Dummy->Suivant); if(Dummy == (DirList_t *)NULL) { /* Absent: deplacer vers un ss-rep situe dans un autre ss-rep */ strcpy(OutFile,Target); if(OutFile[strlen(OutFile) - 1] != PATH_SEPARATOR_CHAR) strcat(OutFile,PATH_SEPARATOR_STR); if(IS_DIR(Current[AL]->Info.s.st_mode)) strcat(OutFile,(Current[AL]->Info.Name) + 1); else strcat(OutFile,Current[AL]->Info.Name); strcpy(TargetDir,Target); } else { /* Trouve: le ss-rep cible se trouve dans le ss-rep courant */ strcpy(TargetDir,WorkingDir[AL]); strcpy(OutFile,TargetDir); if(OutFile[strlen(OutFile) - 1] != PATH_SEPARATOR_CHAR) strcat(OutFile,PATH_SEPARATOR_STR); strcat(OutFile,Target); } } else { /* Simple fichier deja existant, le laisser comme tel */ Analyse(Target,TargetDir,DestFile); if(strcmp(TargetDir,".") == 0) strcpy(TargetDir,WorkingDir[AL]); strcpy(OutFile,TargetDir); if(OutFile[strlen(OutFile) - 1] != PATH_SEPARATOR_CHAR) strcat(OutFile,PATH_SEPARATOR_STR); strcat(OutFile,DestFile); } } else { /* La cible n'existe pas, c'est donc un simple fichier innexistant */ Analyse(Target,TargetDir,DestFile); if(strcmp(TargetDir,".") == 0) strcpy(TargetDir,WorkingDir[AL]); strcpy(OutFile,TargetDir); if(OutFile[strlen(OutFile) - 1] != PATH_SEPARATOR_CHAR) strcat(OutFile,PATH_SEPARATOR_STR); strcat(OutFile,DestFile); } } /* Ouvrir la fenetre temoin de deplacement */ OpenWin(6,16,8,50,FileOpNorm,UNFRAMED,SHADED); PaintWin(7,19,6,44,FileOpNorm,DOUBLE_FRAMED,UNSHADED); WriteString(" Move/Rename ",FileOpNorm,7,35); WriteString("Moving the file or directory",FileOpNorm,8,27); WriteString("to",FileOpNorm,10,39); GotoXY(AfficheY,AfficheX); /* Boucle de deplacement parcourant la liste active */ for(Dummy = List[AL]; Dummy != (DirList_t *)NULL; Dummy = Dummy->Suivant) if(Dummy->Info.Tagged) { /* 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 move cycle? "); AddAnswerBoxItem(&Choices,"Cancel"); AddAnswerBoxItem(&Choices,"Resume"); rc = AnswerBox(ConfirmNorm,ConfirmInv," Move/Rename ",Msg,Choices, 2,0,DOUBLE_FRAMED); InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); if(rc == 1) break; } /* Construire les specifications completes de fichiers */ strcpy(InFile,WorkingDir[AL]); if(InFile[strlen(InFile) - 1] != PATH_SEPARATOR_CHAR) strcat(InFile,PATH_SEPARATOR_STR); if(!IS_DIR(Dummy->Info.s.st_mode)) strcat(InFile,Dummy->Info.Name); else { if(!Recursive) { Dummy->Info.Tagged = 0; continue; } strcat(InFile,Dummy->Info.Name + 1); } if(NbTag > 0) { strcpy(OutFile,TargetDir); if(OutFile[strlen(OutFile) - 1] != PATH_SEPARATOR_CHAR) strcat(OutFile,PATH_SEPARATOR_STR); if(IS_DIR(Dummy->Info.s.st_mode)) strcat(OutFile,(Dummy->Info.Name) + 1); else strcat(OutFile,Dummy->Info.Name); } /* Afficher source et destination */ SetCurrentAtt(FileOpNorm); SetString(9,20,42,' '); if(strlen(Dummy->Info.Name) < 40) WriteString(Dummy->Info.Name,FileOpNorm,9, 40 - (strlen(Dummy->Info.Name) / 2)); else { strcpy(DummyStr,"/..."); strcat(DummyStr,Dummy->Info.Name + (strlen(Dummy->Info.Name) - 33)); WriteString(DummyStr,FileOpNorm,9, 40 - (strlen(DummyStr) / 2)); } SetString(11,20,42,' '); if(strlen(OutFile) < 40) WriteString(OutFile,FileOpNorm,11,40 - (strlen(OutFile) / 2)); else { strcpy(DummyStr,"/..."); strcat(DummyStr,OutFile + (strlen(OutFile) - 33)); WriteString(DummyStr,FileOpNorm,11,40 - (strlen(DummyStr) / 2)); } /* Move cyclique ? */ if(strcmp(InFile,OutFile) == 0) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg,"ERROR: a file cannot be moved to itself."); strcpy(DummyStr,"From: "); strcat(DummyStr,InFile); AddAnswerBoxItem(&InfoMsg,DummyStr); strcpy(DummyStr,"To: "); strcat(DummyStr,OutFile); AddAnswerBoxItem(&InfoMsg,DummyStr); AddAnswerBoxItem(&InfoMsg,"Move cycle will be aborted."); InfoBox(ErrorNorm,ErrorInv," Move/Rename ",InfoMsg,1,0,DOUBLE_FRAMED); break; } /* Tester la presence de ce fichier a la cible */ if(!All) { if(access(OutFile,00) == 0) { InitAnswerBoxItem(&Choices); InitAnswerBoxItem(&Msg); sprintf(DummyStr,"WARNING: \"%s\"",OutFile); AddAnswerBoxItem(&Msg,DummyStr); AddAnswerBoxItem(&Msg,"already exists."); AddAnswerBoxItem(&Msg," Do you wish to overwrite the old file? "); AddAnswerBoxItem(&Choices,"Overwrite"); AddAnswerBoxItem(&Choices,"All"); AddAnswerBoxItem(&Choices,"Skip"); AddAnswerBoxItem(&Choices,"Cancel"); rc = AnswerBox(ConfirmNorm,ConfirmInv," Move/Rename ",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(rename(InFile,OutFile) == -1) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg, "ERROR: impossible to move/rename the file or directory"); AddAnswerBoxItem(&InfoMsg,InFile); AddAnswerBoxItem(&InfoMsg,"to"); AddAnswerBoxItem(&InfoMsg,OutFile); switch(errno) { case EACCES: AddAnswerBoxItem(&InfoMsg,"Permission denied."); break; case EBUSY: AddAnswerBoxItem(&InfoMsg,"Source file busy."); break; case ENOTEMPTY: case EEXIST: AddAnswerBoxItem(&InfoMsg, "The target directory exists and contains files."); break; case ENOTDIR: case EINVAL: AddAnswerBoxItem(&InfoMsg,"Invalid target specification."); break; case ENAMETOOLONG: AddAnswerBoxItem(&InfoMsg,"Name too long."); break; case ENOENT: AddAnswerBoxItem(&InfoMsg,"Source file or directory not found."); break; case ENOSPC: AddAnswerBoxItem(&InfoMsg, "The target directory cannot be extended."); break; case EROFS: AddAnswerBoxItem(&InfoMsg,"Target file system is read-only."); break; case EXDEV: AddAnswerBoxItem(&InfoMsg, "Links between different file systems is not supported."); break; default: sprintf(DummyStr,"Unknown reason (errno %d).",errno); AddAnswerBoxItem(&InfoMsg,DummyStr); } InfoBox(ErrorNorm,ErrorInv," Move/Rename ",InfoMsg,1,0,DOUBLE_FRAMED); } /* Deselectionner le fichier venant d'etre transferre */ Dummy->Info.Tagged = 0; /* Reset du nom cible */ OutFile[0] = 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