#include #include #include #include #include #include #include #include #include #include #include #include typedef struct dirent DIRENT; typedef struct stat STAT; /* search func start */ void searchFiles(const char *searchingString, const char *catalogPath, FILE *outputFilePointer, const int maxNumOfProcesses, int *currNumOfProcesses) { const int PATH_LENGTH = 255; DIR *dir; dir = opendir(catalogPath); if (!dir) // каталог не открылся { fprintf(stderr, "\t\t\tОшибка при открытии %s!\n", catalogPath); return; }; struct dirent *entry; while ((entry = readdir(dir)) != NULL) // пока не кончатся файлы в каталоге { char fullPath[PATH_LENGTH]; snprintf(fullPath, PATH_LENGTH, "%s/%s", catalogPath, entry->d_name); STAT buffer; stat(fullPath, &buffer); if (S_ISREG(buffer.st_mode)) // если текущий файл(при просмотре в каталоге) является регулярным { pid_t childPid = fork(); if (childPid == -1) // не удалось создать процесс { fprintf(stderr, "Ошибка при создании дочернего процесса!\n"); return; } if (childPid == 0) // процесс является дочерним { fprintf(stdout, "\tPID: %d, PPID: %d, Путь: %s, Название: %s\n", getpid(), getppid(), fullPath, entry->d_name); fprintf(outputFilePointer, "\tPID: %d, PPID: %d, Путь: %s, Название: %s\n", getpid(), getppid(), fullPath, entry->d_name); FILE *fileForCheckPointer; if ((fileForCheckPointer = fopen(fullPath, "rb")) == NULL) // файл не открылся для побитового чтения { fprintf(stdout, "Не удалось прочитать данные в файле %s.\n", entry->d_name); } else { char tempChar; int byteCounter = 0; bool isFound = false; while (!feof(fileForCheckPointer)) { byteCounter++; tempChar = getc(fileForCheckPointer); if (tempChar == searchingString[0]) // если текущий выбранный символ в файле совпал с первым символом проверочной строки { int i = 1; isFound = true; while (searchingString[i] != '\0' && isFound) { //пока строка не кончается и сравниваемые символы равны isFound = searchingString[i] == getc(fileForCheckPointer); i++; } } } if (isFound) { fprintf(stdout, "\t\tФайл %s содержит строку %s. До нахождения было просмотрено %d байт.\n", entry->d_name, searchingString, byteCounter); fprintf(outputFilePointer, "\t\tФайл %s содержит строку %s. До нахождения было просмотрено %d байт.\n", entry->d_name, searchingString, byteCounter); } else { fprintf(stdout, "\t\tФайл %s НЕ содержит строку %s. Было просмотрено %d байт.\n", entry->d_name, searchingString, byteCounter); fprintf(outputFilePointer, "\t\tФайл %s НЕ содержит строку %s. Было просмотрено %d байт.\n", entry->d_name, searchingString, byteCounter); } fclose(fileForCheckPointer); } exit(0); } else // процесс является родительским { (*currNumOfProcesses)++; fprintf(stdout, "Родительский процесс: %d. Его дочерний - %d, а родительский - %d\n", getpid(), childPid, getppid()); fprintf(outputFilePointer, "Родительский процесс: %d. Его дочерний - %d, а родительский - %d\n", getpid(), childPid, getppid()); if ((*currNumOfProcesses) >= maxNumOfProcesses) // кол-во текущих процессов больше либо равно максимальному { waitpid(-1, NULL, 0); (*currNumOfProcesses)--; } } } } closedir(dir); while ((*currNumOfProcesses) > 0) { waitpid(-1, NULL, 0); (*currNumOfProcesses)--; } } /* search func end */ /* print procedures start */ void printTaskInfo() { fprintf(stdout, "\tДанная программа ищет в заданном каталоге все файлы,\n\t\t которые содержат заданную строку.\n\tРезультаты выводятся на консоль и в указанный файл.\n\n"); } /* print procedures end */ int main(int argc, char *argv[], char *envp[]) { const int NUM_OF_ARGS = 5; printTaskInfo(); if (argc != NUM_OF_ARGS) { fprintf(stderr, "Неверный ввод!\nФормат ввода: %s <заданный каталог> <строка для поиска> <файл вывода> <кол-во процессов>\n", argv[0]); fprintf(stdout, "Повторите запуск программы!\n"); return 1; } const char *catalogPath = argv[1]; const char *stringForSearch = argv[2]; const char *outputFilePath = argv[3]; int maxNumOfProcesses = atoi(argv[4]); int currNumOfProcesses = 0; FILE *outputFilePointer = fopen(outputFilePath, "w"); if (outputFilePointer) { fprintf(stdout, "\n\t\tВывод списка найденных файлов в консоль:\n\n"); searchFiles(stringForSearch, catalogPath, outputFilePointer, maxNumOfProcesses, &currNumOfProcesses); fclose(outputFilePointer); fprintf(stdout, "\n\t\tЗапись в файл успешно завершена!\n"); } else { fprintf(stdout, "\nНе удалось открыть файл для записи! Повторите запуск программы\n"); } return 0; }