Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <string.h>
- #include <dirent.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <unistd.h>
- #include <sys/wait.h>
- // Написать программу поиска одинаковых по содержимому файлов в двух каталогов, например, Dir1 и Dir2.
- // Пользователь задаёт имена Dir1 и Dir2. В результате работы программы файлы, имеющиеся в Dir1,
- // сравниваются с файлами в Dir2 по их содержимому. Процедуры сравнения должны запускаться в
- // отдельном процессе для каждой пары сравниваемых файлов. Каждый процесс выводит на экран свой pid,
- // имя файла, общее число просмотренных байт и результаты сравнения. Число одновременно работающих процессов
- // не должно превышать N (вводится пользователем). Скопировать несколько файлов из каталога /etc в свой
- // домашний каталог. Проверить работу программы для каталога /etc и домашнего каталога.
- const int strSize = 512;
- char *dir1;
- char *dir2;
- char *execFileName;
- int maxProcessesCount;
- void findFiles(char *, void(*callback)(char *, char *), char *);
- int checkPointer(void *pointer, char *filePath, int closeProg) {
- if(pointer == NULL) {
- fprintf(stderr, "%s: %s: %s\n", execFileName, filePath, strerror(errno));
- if(closeProg) exit(errno);
- return 1;
- }
- return 0;
- }
- int contains(char **arr, int arrLength, char *str) {
- for (int i = 0; i < arrLength; i++) {
- if (arr[i] != NULL && strcmp(arr[i], str) == 0) return 1;
- }
- return 0;
- }
- void addToBlacklist(char *path) {
- static char **blacklist = NULL;
- static int blacklistIndex = 0;
- int blacklistLength = 1000;
- if (blacklist == NULL) blacklist = calloc(blacklistLength, strSize);
- if (!contains(blacklist, blacklistLength, path)) {
- blacklist[blacklistIndex] = malloc(strSize);
- if(checkPointer(blacklist[blacklistIndex], path, 0)) return;
- strcpy(blacklist[blacklistIndex], path);
- blacklistIndex = (blacklistIndex + 1) % blacklistLength;
- fprintf(stderr, "%s: %s: %s\n", execFileName, path, strerror(errno));
- }
- }
- void closeFiles(FILE *file1, FILE *file2, char *filePath1, char *filePath2) {
- if (file1 != NULL && fclose(file1) != 0) {
- fprintf(stderr, "%s: %s: %s\n", execFileName, filePath1, strerror(errno));
- }
- if (file2 != NULL && fclose(file2) != 0) {
- fprintf(stderr, "%s: %s: %s\n", execFileName, filePath2, strerror(errno));
- }
- }
- void compareFiles(FILE *file1, FILE *file2, char *filePath1, char *filePath2) {
- static int processes = 0;
- if(processes > maxProcessesCount) {
- wait(NULL);
- processes--;
- }
- pid_t pid = fork();
- processes++;
- if(pid == -1) {
- fprintf(stderr, "%s: Impossible to create a process\n", execFileName);
- return;
- }
- if(pid == 0) {
- const int bufferSize = 1024 * 1024 * 50; // 50 mb
- char *buffer1 = calloc(1, bufferSize);
- char *buffer2 = calloc(1, bufferSize);
- checkPointer(buffer1, filePath1, 1);
- checkPointer(buffer2, filePath2, 1);
- unsigned long occupiedBytes1 = 0;
- unsigned long occupiedBytes2 = 0;
- while(1) {
- occupiedBytes1 += fread(buffer1, sizeof(char), bufferSize, file1);
- occupiedBytes2 += fread(buffer2, sizeof(char), bufferSize, file2);
- if(occupiedBytes1 != occupiedBytes2) {
- free(buffer1);
- free(buffer2);
- exit(0);
- }
- if(occupiedBytes1 == bufferSize || feof(file1) != 0 && feof(file2) != 0) {
- if(memcmp(buffer1, buffer2, bufferSize) == 0) {
- free(buffer1);
- free(buffer2);
- if(feof(file1) != 0 && feof(file2) != 0) {
- printf("pid: %d %s %lu = %s %lu\n", getpid(), filePath1, occupiedBytes1, filePath2, occupiedBytes2);
- exit(0);
- }
- buffer1 = calloc(1, bufferSize);
- buffer2 = calloc(1, bufferSize);
- checkPointer(buffer1, filePath1, 1);
- checkPointer(buffer2, filePath2, 1);
- } else {
- free(buffer1);
- free(buffer2);
- exit(0);
- }
- }
- }
- }
- }
- void handleFile2(char *filePath1, char *filePath2) {
- FILE *file1 = fopen(filePath1, "rb");
- FILE *file2 = fopen(filePath2, "rb");
- if(file1 == NULL) addToBlacklist(filePath1);
- if(file2 == NULL) addToBlacklist(filePath2);
- if (file1 == NULL || file2 == NULL) {
- closeFiles(file1, file2, filePath1, filePath2);
- return;
- }
- compareFiles(file1, file2, filePath1, filePath2);
- if(fclose(file1) != 0) {
- fprintf(stderr, "%s: %s: %s\n", execFileName, filePath1, strerror(errno));
- }
- if(fclose(file2) != 0) {
- fprintf(stderr, "%s: %s: %s\n", execFileName, filePath2, strerror(errno));
- }
- }
- void handleFile1(char *filePath, char *_) {
- findFiles(dir2, handleFile2, filePath);
- }
- void findFiles(char *dirname, void (*callback)(char *, char *), char *cbArg) {
- DIR *dir;
- struct dirent *ent;
- if ((dir = opendir(dirname)) == NULL) {
- addToBlacklist(dirname);
- return;
- }
- errno = 0;
- while ((ent = readdir(dir)) != NULL) {
- char *temp = calloc(1, strSize);
- if(checkPointer(temp, dirname, 0)) return;
- strcpy(temp, dirname);
- strcat(temp, ent->d_name);
- if (ent->d_type == DT_REG) {
- callback(temp, cbArg);
- } else if (ent->d_type == DT_DIR && strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) {
- strcat(temp, "/");
- findFiles(temp, callback, cbArg);
- }
- free(temp);
- errno = 0;
- }
- if(errno != 0) {
- fprintf(stderr, "%s: %s: %s\n", execFileName, dirname, strerror(errno));
- }
- if(closedir(dir) == -1) {
- fprintf(stderr, "%s: %s: %s\n", execFileName, dirname, strerror(errno));
- }
- }
- char *addSlash(char *str) {
- int length = strlen(str);
- if (str[length - 1] != '/') {
- char *copy = malloc(strlen(str));
- strcpy(copy, str);
- strcat(copy, "/");
- return copy;
- }
- return str;
- }
- int isDirectory(char *str) {
- DIR *dir = opendir(str);
- if (dir != NULL) {
- closedir(dir);
- return 1;
- }
- return 0;
- }
- int isNumber(char *str) {
- for(int i = 0; i < strlen(str); i++) {
- if(str[i] < 48 || str[i] > 57) return 0;
- }
- return 1;
- }
- void checkForErrors(int argc, char **argv) {
- if (argc < 2) {
- fprintf(stderr, "%s: First argument is not specified: you didn't provide first directory\n", execFileName);
- exit(1);
- }
- if (argc < 3) {
- fprintf(stderr, "%s: Second argument is not specified: you didn't provide second directory\n", execFileName);
- exit(2);
- }
- if(argc < 4) {
- fprintf(stderr, "%s: Third argument is not specified: you didn't specified the number of concurrent processes\n", execFileName);
- exit(3);
- }
- if (!isDirectory(argv[1])) {
- fprintf(stderr, "%s: First argument must be a valid directory\n", execFileName);
- exit(4);
- }
- if (!isDirectory(argv[2])) {
- fprintf(stderr, "%s: Second argument must be a valid directory\n", execFileName);
- exit(5);
- }
- if(!isNumber(argv[3])) {
- fprintf(stderr, "%s: Third argument must be a positive integer\n", execFileName);
- exit(6);
- }
- if(atoi(argv[3]) < 1) {
- fprintf(stderr, "%s: Third argument must be greater than 0\n", execFileName);
- exit(7);
- }
- if(atoi(argv[3]) > 100) {
- fprintf(stderr, "%s: Third argument shouldn't be greater than 100\n", execFileName);
- exit(8);
- }
- }
- char *getExecFileName(char *path) {
- int lastSlashIndex = 0;
- int length = strlen(path);
- for(int i = 0; i < length; i++) {
- if(path[i] == '/') lastSlashIndex = i;
- }
- char *result = malloc(length - lastSlashIndex);
- checkPointer(result, path, 1);
- for(int i = 0; i < length - lastSlashIndex; i++) {
- result[i] = path[lastSlashIndex + i + 1];
- }
- result[length - lastSlashIndex] = '\0';
- return result;
- }
- int main(int argc, char **argv) {
- execFileName = getExecFileName(argv[0]);
- checkForErrors(argc, argv);
- dir1 = addSlash(argv[1]);
- dir2 = addSlash(argv[2]);
- maxProcessesCount = atoi(argv[3]);
- findFiles(dir1, handleFile1, NULL);
- while(wait(NULL) > 0) { }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement