Alyks

lab3

Apr 21st, 2021
833
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×