/* * Programme pour rechercher dans le fichier spécifié par le premier argument * de la ligne de commande la chaîne spécifiée par le second argument * de la ligne de commande. Le programme effectue la recherche en lisant et recherchant * les blocs de taille BLOCK_SIZE. */ #include #include #include #include /* alloc.h pour les compilateurs Borland, malloc.h pour les compilateurs Microsoft */ #define BLOCK_SIZE 0x4000 /* nous traiterons le fichier par blocs de 16 kilos */ /* Recherche le nombre spécifié de séquences dans le tampon correspondant à SearchString de longueur SearchStringLength. Notez que le code appelant doit déjà avoir raccourci SearchLength si nécessaire pour compenser la distance de la fin du tampon à la dernière séquence correspondante dans le tampon */ int SearchForString(unsigned char *Buffer, int SearchLength, unsigned char *SearchString, int SearchStringLength) { unsigned char *PotentialMatch; /* Recherche tant qu'il existe d'éventuelles correspondances à trouver */ while ( SearchLength ) { /* Vérifiez si le premier caractère de SearchString est trouvé */ if ( (PotentialMatch = memchr(Buffer, *SearchString, SearchLength)) == NULL ) { break; /* pas de correspondance ici */ } /*Le premier caractère correspond; vérifiez si le reste de la chaîne correspond également */ if ( SearchStringLength == 1 ) { return(1); /* la chaîne ne fait qu'un caractère ,nous l'avons trouvé */ } else { /* vérifie si le reste des caractères correspond */ if ( !memcmp(PotentialMatch + 1, SearchString + 1, SearchStringLength - 1) ) { return(1); /* nous avons trouvé une correspondance */ } } /*La chaîne ne correspond pas; re-pointons juste après l'éventuelle correspondance que nous avons rejetée */ SearchLength -= PotentialMatch - Buffer + 1; Buffer = PotentialMatch + 1; } return(0); /* aucune correspondance trouvée */ } main(int argc, char *argv[]) { int Done; /* indique si une recherche est effectuée */ int Handle; /* handle du fichier à rechercher */ int WorkingLength; /* longueur du bloc courant */ int SearchStringLength; /* longueur de la chaîne recherchée */ int BlockSearchLength; /* longueur de recherche dans le bloc */ int Found; /* indique le statut final de la recherche */ int NextLoadCount; /* nombre d'octets à lire dans le prochain bloc, en comptant les octets copiés dans le bloc précédent */ unsigned char *WorkingBlock; /* tampon de stockage de bloc */ unsigned char *SearchString; /* pointeur sur la chaîne recherchée */ unsigned char *NextLoadPtr; /* offset du début du chargement du prochain bloc, en comptant les octets copiés dans le bloc précédent */ /* Vérifie si le nombre d'arguments est correct */ if ( argc != 3 ) { printf("syntaxe: non_du_fichier chaine_a_rechercher\n"); exit(1); } /* Essai d'ouvrir le fichier à rechercher */ if ( (Handle = open(argv[1], O_RDONLY | O_BINARY)) == -1 ) { printf("Impossible d'ouvrir le fichier: %s\n", argv[1]); exit(1); } /* Calcul la longueur du texte à rechercher */ SearchString = argv[2]; SearchStringLength = strlen(SearchString); /* Essai d'allouer de la mémoire pour le données du tampon */ if ( (WorkingBlock = malloc(BLOCK_SIZE)) == NULL ) { printf("Impossible d'allouer la mémoire\n"); exit(1); } /* Chargement du premier bloc du tampon, et essai de remplir tout le tampon */ NextLoadPtr = WorkingBlock; NextLoadCount = BLOCK_SIZE; Done = 0; /* recherche n'est pas terminée */ Found = 0; /* suppose que nous n'avons pas trouvé de correspondance */ /* Recherche le fichier par bloc BLOCK_SIZE */ do { /* lit le nombre d'octets nécessaires pour remplir le bloc ( en comptant les octets du bloc précédent), ou les octets restant dans le fichier, */ if ( (WorkingLength = read(Handle, NextLoadPtr, NextLoadCount)) == -1 ) { printf("Erreur de la lecture du fichier %s\n", argv[1]); exit(1); } /*Si nous n'avons pas lu tous les octets requis, nous le faisons après ce bloc pour voir si nous trouvons ou non une correspondance */ if ( WorkingLength != NextLoadCount ) { Done = 1; } /* Compte les octets copiés de la fin du bloc précédent dans la longueur totale du bloc */ WorkingLength += NextLoadPtr - WorkingBlock; /* Calcul du nombre d'octets du bloc qui pourrait être le début de la séquence correspondante dans ce bloc (les séquences se chevauchant sont transférées dans le prochain bloc)*/ if ( (BlockSearchLength = WorkingLength - SearchStringLength + 1) <= 0 ) { Done = 1; /* trop peu de caractères pour trouver une correspondance, comme c'est le dernier bloc nous finissons sans avoir trouvé de correspondance */ } else { /* Recherche dans le bloc */ if ( SearchForString(WorkingBlock, BlockSearchLength, SearchString, SearchStringLength) ) { Found = 1; /* nous avons trouvé une correspondance */ Done = 1; } else { /* Copie les octets de la fin du bloc qui commence éventuellement par une séquence correspondante qui chevaucherait la fin de ce bloc et le début du suivant */ if ( SearchStringLength > 1 ) { memcpy(WorkingBlock, WorkingBlock + BLOCK_SIZE - SearchStringLength + 1, SearchStringLength - 1); } /* S'apprête à charger les prochains octets depuis le fichier après avoir copié ceux du bloc courant */ NextLoadPtr = WorkingBlock + SearchStringLength - 1; NextLoadCount = BLOCK_SIZE - SearchStringLength + 1; } } } while ( !Done ); /* Reporte les résultats */ if ( Found ) { printf("chaîne trouvée\n"); } else { printf("chaîne non trouvée\n"); } exit(Found); /* retourne le statut trouvé ou non trouvé sous forme de DOS errorlevel */ }