Advertisement
Alyks

lab3

Apr 21st, 2021
1,320
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.15 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <dirent.h>
  4. #include <stdlib.h>
  5. #include <errno.h>
  6. #include <unistd.h>
  7. #include <sys/wait.h>
  8.  
  9. // Написать программу поиска одинаковых по содержимому файлов в двух каталогов, например, Dir1 и Dir2.
  10. // Пользователь задаёт имена Dir1 и Dir2. В результате работы программы файлы, имеющиеся в Dir1,
  11. // сравниваются с файлами в Dir2 по их содержимому. Процедуры сравнения должны запускаться в
  12. // отдельном процессе для каждой пары сравниваемых файлов. Каждый процесс выводит на экран свой pid,
  13. // имя файла, общее число просмотренных байт и результаты сравнения. Число одновременно работающих процессов
  14. // не должно превышать N (вводится пользователем). Скопировать несколько файлов из каталога /etc в свой
  15. // домашний каталог. Проверить работу программы для каталога /etc и домашнего каталога.
  16.  
  17. const int strSize = 512;
  18. char *dir1;
  19. char *dir2;
  20. char *execFileName;
  21. int maxProcessesCount;
  22.  
  23. void findFiles(char *, void(*callback)(char *, char *), char *);
  24.  
  25. int checkPointer(void *pointer, char *filePath, int closeProg) {
  26.     if(pointer == NULL) {
  27.         fprintf(stderr, "%s: %s: %s\n", execFileName, filePath, strerror(errno));
  28.         if(closeProg) exit(errno);
  29.         return 1;
  30.     }
  31.     return 0;
  32. }
  33.  
  34. int contains(char **arr, int arrLength, char *str) {
  35.     for (int i = 0; i < arrLength; i++) {
  36.         if (arr[i] != NULL && strcmp(arr[i], str) == 0) return 1;
  37.     }
  38.  
  39.     return 0;
  40. }
  41.  
  42. void addToBlacklist(char *path) {
  43.     static char **blacklist = NULL;
  44.     static int blacklistIndex = 0;
  45.     int blacklistLength = 1000;
  46.  
  47.     if (blacklist == NULL) blacklist = calloc(blacklistLength, strSize);
  48.  
  49.     if (!contains(blacklist, blacklistLength, path)) {
  50.         blacklist[blacklistIndex] = malloc(strSize);
  51.  
  52.         if(checkPointer(blacklist[blacklistIndex], path, 0)) return;
  53.  
  54.         strcpy(blacklist[blacklistIndex], path);
  55.         blacklistIndex = (blacklistIndex + 1) % blacklistLength;
  56.         fprintf(stderr, "%s: %s: %s\n", execFileName, path, strerror(errno));
  57.     }
  58. }
  59.  
  60. void closeFiles(FILE *file1, FILE *file2, char *filePath1, char *filePath2) {
  61.     if (file1 != NULL && fclose(file1) != 0) {
  62.         fprintf(stderr, "%s: %s: %s\n", execFileName, filePath1, strerror(errno));
  63.     }
  64.  
  65.     if (file2 != NULL && fclose(file2) != 0) {
  66.         fprintf(stderr, "%s: %s: %s\n", execFileName, filePath2, strerror(errno));
  67.     }
  68. }
  69.  
  70. void compareFiles(FILE *file1, FILE *file2, char *filePath1, char *filePath2) {
  71.     static int processes = 0;
  72.  
  73.     if(processes > maxProcessesCount) {
  74.         wait(NULL);
  75.         processes--;
  76.     }
  77.  
  78.     pid_t pid = fork();
  79.     processes++;
  80.  
  81.     if(pid == -1) {
  82.         fprintf(stderr, "%s: Impossible to create a process\n", execFileName);
  83.         return;
  84.     }
  85.  
  86.     if(pid == 0) {
  87.         const int bufferSize = 1024 * 1024 * 50; // 50 mb
  88.         char *buffer1 = calloc(1, bufferSize);
  89.         char *buffer2 = calloc(1, bufferSize);
  90.         checkPointer(buffer1, filePath1, 1);
  91.         checkPointer(buffer2, filePath2, 1);
  92.         unsigned long occupiedBytes1 = 0;
  93.         unsigned long occupiedBytes2 = 0;
  94.  
  95.         while(1) {
  96.             occupiedBytes1 += fread(buffer1, sizeof(char), bufferSize, file1);
  97.             occupiedBytes2 += fread(buffer2, sizeof(char), bufferSize, file2);
  98.  
  99.             if(occupiedBytes1 != occupiedBytes2) {
  100.                 free(buffer1);
  101.                 free(buffer2);
  102.                 exit(0);
  103.             }
  104.  
  105.             if(occupiedBytes1 == bufferSize || feof(file1) != 0 && feof(file2) != 0) {
  106.                 if(memcmp(buffer1, buffer2, bufferSize) == 0) {
  107.                     free(buffer1);
  108.                     free(buffer2);
  109.  
  110.                     if(feof(file1) != 0 && feof(file2) != 0) {
  111.                         printf("pid: %d %s %lu = %s %lu\n", getpid(), filePath1, occupiedBytes1, filePath2, occupiedBytes2);
  112.                         exit(0);
  113.                     }
  114.  
  115.                     buffer1 = calloc(1, bufferSize);
  116.                     buffer2 = calloc(1, bufferSize);
  117.                     checkPointer(buffer1, filePath1, 1);
  118.                     checkPointer(buffer2, filePath2, 1);
  119.                 } else {
  120.                     free(buffer1);
  121.                     free(buffer2);
  122.                     exit(0);
  123.                 }
  124.             }
  125.         }
  126.     }
  127. }
  128.  
  129. void handleFile2(char *filePath1, char *filePath2) {
  130.     FILE *file1 = fopen(filePath1, "rb");
  131.     FILE *file2 = fopen(filePath2, "rb");
  132.  
  133.     if(file1 == NULL) addToBlacklist(filePath1);
  134.     if(file2 == NULL) addToBlacklist(filePath2);
  135.  
  136.     if (file1 == NULL || file2 == NULL) {
  137.         closeFiles(file1, file2, filePath1, filePath2);
  138.         return;
  139.     }
  140.  
  141.     compareFiles(file1, file2, filePath1, filePath2);
  142.  
  143.     if(fclose(file1) != 0) {
  144.         fprintf(stderr, "%s: %s: %s\n", execFileName, filePath1, strerror(errno));
  145.     }
  146.  
  147.     if(fclose(file2) != 0) {
  148.         fprintf(stderr, "%s: %s: %s\n", execFileName, filePath2, strerror(errno));
  149.     }
  150. }
  151.  
  152. void handleFile1(char *filePath, char *_) {
  153.     findFiles(dir2, handleFile2, filePath);
  154. }
  155.  
  156. void findFiles(char *dirname, void (*callback)(char *, char *), char *cbArg) {
  157.     DIR *dir;
  158.     struct dirent *ent;
  159.  
  160.     if ((dir = opendir(dirname)) == NULL) {
  161.         addToBlacklist(dirname);
  162.         return;
  163.     }
  164.  
  165.     errno = 0;
  166.     while ((ent = readdir(dir)) != NULL) {
  167.         char *temp = calloc(1, strSize);
  168.  
  169.         if(checkPointer(temp, dirname, 0)) return;
  170.  
  171.         strcpy(temp, dirname);
  172.         strcat(temp, ent->d_name);
  173.  
  174.         if (ent->d_type == DT_REG) {
  175.             callback(temp, cbArg);
  176.         } else if (ent->d_type == DT_DIR && strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) {
  177.             strcat(temp, "/");
  178.             findFiles(temp, callback, cbArg);
  179.         }
  180.  
  181.         free(temp);
  182.         errno = 0;
  183.     }
  184.  
  185.     if(errno != 0) {
  186.         fprintf(stderr, "%s: %s: %s\n", execFileName, dirname, strerror(errno));
  187.     }
  188.  
  189.     if(closedir(dir) == -1) {
  190.         fprintf(stderr, "%s: %s: %s\n", execFileName, dirname, strerror(errno));
  191.     }
  192. }
  193.  
  194. char *addSlash(char *str) {
  195.     int length = strlen(str);
  196.  
  197.     if (str[length - 1] != '/') {
  198.         char *copy = malloc(strlen(str));
  199.         strcpy(copy, str);
  200.         strcat(copy, "/");
  201.         return copy;
  202.     }
  203.  
  204.     return str;
  205. }
  206.  
  207. int isDirectory(char *str) {
  208.     DIR *dir = opendir(str);
  209.  
  210.     if (dir != NULL) {
  211.         closedir(dir);
  212.         return 1;
  213.     }
  214.  
  215.     return 0;
  216. }
  217.  
  218. int isNumber(char *str) {
  219.     for(int i = 0; i < strlen(str); i++) {
  220.         if(str[i] < 48 || str[i] > 57) return 0;
  221.     }
  222.  
  223.     return 1;
  224. }
  225.  
  226. void checkForErrors(int argc, char **argv) {
  227.     if (argc < 2) {
  228.         fprintf(stderr, "%s: First argument is not specified: you didn't provide first directory\n", execFileName);
  229.         exit(1);
  230.     }
  231.  
  232.     if (argc < 3) {
  233.         fprintf(stderr, "%s: Second argument is not specified: you didn't provide second directory\n", execFileName);
  234.         exit(2);
  235.     }
  236.  
  237.     if(argc < 4) {
  238.         fprintf(stderr, "%s: Third argument is not specified: you didn't specified the number of concurrent processes\n", execFileName);
  239.         exit(3);
  240.     }
  241.  
  242.     if (!isDirectory(argv[1])) {
  243.         fprintf(stderr, "%s: First argument must be a valid directory\n", execFileName);
  244.         exit(4);
  245.     }
  246.  
  247.     if (!isDirectory(argv[2])) {
  248.         fprintf(stderr, "%s: Second argument must be a valid directory\n", execFileName);
  249.         exit(5);
  250.     }
  251.  
  252.     if(!isNumber(argv[3])) {
  253.         fprintf(stderr, "%s: Third argument must be a positive integer\n", execFileName);
  254.         exit(6);
  255.     }
  256.  
  257.     if(atoi(argv[3]) < 1) {
  258.         fprintf(stderr, "%s: Third argument must be greater than 0\n", execFileName);
  259.         exit(7);
  260.     }
  261.  
  262.     if(atoi(argv[3]) > 100) {
  263.         fprintf(stderr, "%s: Third argument shouldn't be greater than 100\n", execFileName);
  264.         exit(8);
  265.     }
  266. }
  267.  
  268. char *getExecFileName(char *path) {
  269.     int lastSlashIndex = 0;
  270.     int length = strlen(path);
  271.  
  272.     for(int i = 0; i < length; i++) {
  273.         if(path[i] == '/') lastSlashIndex = i;
  274.     }
  275.  
  276.     char *result = malloc(length - lastSlashIndex);
  277.     checkPointer(result, path, 1);
  278.  
  279.     for(int i = 0; i < length - lastSlashIndex; i++) {
  280.         result[i] = path[lastSlashIndex + i + 1];
  281.     }
  282.  
  283.     result[length - lastSlashIndex] = '\0';
  284.     return result;
  285. }
  286.  
  287. int main(int argc, char **argv) {
  288.     execFileName = getExecFileName(argv[0]);
  289.     checkForErrors(argc, argv);
  290.     dir1 = addSlash(argv[1]);
  291.     dir2 = addSlash(argv[2]);
  292.     maxProcessesCount = atoi(argv[3]);
  293.     findFiles(dir1, handleFile1, NULL);
  294.     while(wait(NULL) > 0) { }
  295.     return 0;
  296. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement