Alyks

lab2

Apr 21st, 2021
730
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 <sys/stat.h>
  6. #include <errno.h>
  7. #include <time.h>
  8.  
  9. // Найти совпадающие по содержимому (сравнить побайтно) файлы в двух заданных каталогах
  10. // (аргументы 1 и 2 командной строки) и всех их подкаталогах. Вывести на консоль и в файл
  11. // (аргумент 3 командной строки) полный путь, размер, дату создания, права доступа, номер индексного дескриптора
  12. // и размер файла.
  13.  
  14. const int strSize = 512;
  15. char *dir1;
  16. char *dir2;
  17. char *execFileName;
  18. char *outputFilePath;
  19. char *outputBuffer;
  20. const int outputBufferLength = 80;
  21. int outputBufferIndex = 0;
  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. struct stat getFileInfo(FILE *file) {
  61.     struct stat buf;
  62.     fstat(fileno(file), &buf);
  63.     return buf;
  64. }
  65.  
  66. char *getDate(time_t unixDate) {
  67.     struct tm *tm = localtime(&unixDate);
  68.     char *date = calloc(1, strSize);
  69.     if(checkPointer(date, execFileName, 0)) return "";
  70.     strftime(date, strSize, "%Y-%m-%d %H:%M:%S", tm);
  71.     return date;
  72. }
  73.  
  74. void printOutputBuffer() {
  75.     FILE *file = fopen(outputFilePath, "a");
  76.  
  77.     if(file == NULL) {
  78.         fprintf(stderr, "%s: %s: %s\n", execFileName, outputFilePath, strerror(errno));
  79.     } else {
  80.         fprintf(file, "%s", outputBuffer);
  81.         if(fclose(file) != 0) {
  82.             fprintf(stderr, "%s: %s: %s\n", execFileName, outputFilePath, strerror(errno));
  83.         }
  84.     }
  85.  
  86.     printf("%s", outputBuffer);
  87.     outputBufferIndex = 0;
  88.     free(outputBuffer);
  89.     outputBuffer = calloc(outputBufferLength, strSize);
  90.     checkPointer(outputBuffer, execFileName, 1);
  91. }
  92.  
  93. void closeFiles(FILE *file1, FILE *file2, char *filePath1, char *filePath2) {
  94.     if (file1 != NULL && fclose(file1) != 0) {
  95.         fprintf(stderr, "%s: %s: %s\n", execFileName, filePath1, strerror(errno));
  96.     }
  97.  
  98.     if (file2 != NULL && fclose(file2) != 0) {
  99.         fprintf(stderr, "%s: %s: %s\n", execFileName, filePath2, strerror(errno));
  100.     }
  101. }
  102.  
  103. int filesEqual(FILE *file1, FILE *file2, char *filePath1, char *filePath2) {
  104.     const int bufferSize = 1024 * 1024 * 50; // 50 mb
  105.     char *buffer1 = calloc(1, bufferSize);
  106.     char *buffer2 = calloc(1, bufferSize);
  107.     unsigned long occupiedBytes1 = 0;
  108.     unsigned long occupiedBytes2 = 0;
  109.  
  110.     if(checkPointer(buffer1, filePath1, 0) || checkPointer(buffer2, filePath2, 0)) return 0;
  111.  
  112.     while(1) {
  113.         occupiedBytes1 += fread(buffer1, sizeof(char), bufferSize, file1);
  114.         occupiedBytes2 += fread(buffer2, sizeof(char), bufferSize, file2);
  115.  
  116.         if(occupiedBytes1 != occupiedBytes2) {
  117.             free(buffer1);
  118.             free(buffer2);
  119.             return 0;
  120.         }
  121.  
  122.         if(occupiedBytes1 == bufferSize || feof(file1) != 0 && feof(file2) != 0) {
  123.             if(memcmp(buffer1, buffer2, bufferSize) == 0) {
  124.                 free(buffer1);
  125.                 free(buffer2);
  126.  
  127.                 if(feof(file1) != 0 && feof(file2) != 0) return 1;
  128.  
  129.                 buffer1 = calloc(1, bufferSize);
  130.                 buffer2 = calloc(1, bufferSize);
  131.                 if(checkPointer(buffer1, filePath1, 0) || checkPointer(buffer2, filePath2, 0)) return 0;
  132.             } else {
  133.                 free(buffer1);
  134.                 free(buffer2);
  135.                 return 0;
  136.             }
  137.         }
  138.     }
  139. }
  140.  
  141. void handleFile2(char *filePath1, char *filePath2) {
  142.     FILE *file1 = fopen(filePath1, "rb");
  143.     FILE *file2 = fopen(filePath2, "rb");
  144.  
  145.     if(file1 == NULL) addToBlacklist(filePath1);
  146.     if(file2 == NULL) addToBlacklist(filePath2);
  147.  
  148.     if (file1 == NULL || file2 == NULL) {
  149.         closeFiles(file1, file2, filePath1, filePath2);
  150.         return;
  151.     }
  152.  
  153.     if(filesEqual(file1, file2, filePath1, filePath2)) {
  154.         struct stat fileInfo1 = getFileInfo(file1);
  155.         struct stat fileInfo2 = getFileInfo(file2);
  156.         char *str1 = calloc(1, strSize);
  157.         char *str2 = calloc(1, strSize);
  158.  
  159.         if(checkPointer(str1, filePath1, 0) || checkPointer(str2, filePath2, 0)) return;
  160.  
  161.         sprintf(str1, "%s %ld %s %u %lu = ", filePath1,
  162.                 fileInfo1.st_size, getDate(fileInfo1.st_ctim.tv_sec), fileInfo1.st_mode, fileInfo1.st_ino);
  163.         strcat(outputBuffer, str1);
  164.         sprintf(str2, "%s %ld %s %u %lu\n", filePath2,
  165.                 fileInfo2.st_size, getDate(fileInfo2.st_ctim.tv_sec), fileInfo2.st_mode, fileInfo2.st_ino);
  166.         strcat(outputBuffer, str2);
  167.         outputBufferIndex++;
  168.  
  169.         if (outputBufferIndex == outputBufferLength) {
  170.             printOutputBuffer();
  171.         }
  172.  
  173.         free(str1);
  174.         free(str2);
  175.     }
  176.  
  177.     if(fclose(file1) != 0) {
  178.         fprintf(stderr, "%s: %s: %s\n", execFileName, filePath1, strerror(errno));
  179.     }
  180.  
  181.     if(fclose(file2) != 0) {
  182.         fprintf(stderr, "%s: %s: %s\n", execFileName, filePath2, strerror(errno));
  183.     }
  184. }
  185.  
  186. void handleFile1(char *filePath, char *_) {
  187.     findFiles(dir2, handleFile2, filePath);
  188. }
  189.  
  190. void findFiles(char *dirname, void (*callback)(char *, char *), char *cbArg) {
  191.     DIR *dir;
  192.     struct dirent *ent;
  193.  
  194.     if ((dir = opendir(dirname)) == NULL) {
  195.         addToBlacklist(dirname);
  196.         return;
  197.     }
  198.  
  199.     errno = 0;
  200.     while ((ent = readdir(dir)) != NULL) {
  201.         char *temp = calloc(1, strSize);
  202.  
  203.         if(checkPointer(temp, dirname, 0)) return;
  204.  
  205.         strcpy(temp, dirname);
  206.         strcat(temp, ent->d_name);
  207.  
  208.         if (ent->d_type == DT_REG) {
  209.             callback(temp, cbArg);
  210.         } else if (ent->d_type == DT_DIR && strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0) {
  211.             strcat(temp, "/");
  212.             findFiles(temp, callback, cbArg);
  213.         }
  214.  
  215.         free(temp);
  216.         errno = 0;
  217.     }
  218.  
  219.     if(errno != 0) {
  220.         fprintf(stderr, "%s: %s: %s\n", execFileName, dirname, strerror(errno));
  221.     }
  222.  
  223.     if(closedir(dir) == -1) {
  224.         fprintf(stderr, "%s: %s: %s\n", execFileName, dirname, strerror(errno));
  225.     }
  226. }
  227.  
  228. char *addSlash(char *str) {
  229.     int length = strlen(str);
  230.  
  231.     if (str[length - 1] != '/') {
  232.         char *copy = malloc(strlen(str));
  233.         strcpy(copy, str);
  234.         strcat(copy, "/");
  235.         return copy;
  236.     }
  237.  
  238.     return str;
  239. }
  240.  
  241. int isDirectory(char *str) {
  242.     DIR *dir = opendir(str);
  243.  
  244.     if (dir != NULL) {
  245.         closedir(dir);
  246.         return 1;
  247.     }
  248.  
  249.     return 0;
  250. }
  251.  
  252. void checkForErrors(int argc, char **argv) {
  253.     if (argc < 2) {
  254.         fprintf(stderr, "%s: First argument is not specified: you didn't provide first directory\n", execFileName);
  255.         exit(1);
  256.     }
  257.  
  258.     if (argc < 3) {
  259.         fprintf(stderr, "%s: Second argument is not specified: you didn't provide second directory\n", execFileName);
  260.         exit(2);
  261.     }
  262.  
  263.     if(argc < 4) {
  264.         fprintf(stderr, "%s: Third argument is not specified: you didn't provide output file path\n", execFileName);
  265.         exit(3);
  266.     }
  267.  
  268.     if (!isDirectory(argv[1])) {
  269.         fprintf(stderr, "%s: First argument must be a valid directory\n", execFileName);
  270.         exit(4);
  271.     }
  272.  
  273.     if (!isDirectory(argv[2])) {
  274.         fprintf(stderr, "%s: Second argument must be a valid directory\n", execFileName);
  275.         exit(5);
  276.     }
  277. }
  278.  
  279. char *getExecFileName(char *path) {
  280.     int lastSlashIndex = 0;
  281.     int length = strlen(path);
  282.  
  283.     for(int i = 0; i < length; i++) {
  284.         if(path[i] == '/') lastSlashIndex = i;
  285.     }
  286.  
  287.     char *result = malloc(length - lastSlashIndex);
  288.     checkPointer(result, path, 1);
  289.  
  290.     for(int i = 0; i < length - lastSlashIndex; i++) {
  291.         result[i] = path[lastSlashIndex + i + 1];
  292.     }
  293.  
  294.     result[length - lastSlashIndex] = '\0';
  295.     return result;
  296. }
  297.  
  298. int main(int argc, char **argv) {
  299.     execFileName = getExecFileName(argv[0]);
  300.     checkForErrors(argc, argv);
  301.     dir1 = addSlash(argv[1]);
  302.     dir2 = addSlash(argv[2]);
  303.     outputFilePath = argv[3];
  304.     outputBuffer = calloc(outputBufferLength, strSize);
  305.     checkPointer(outputBuffer, argv[0], 1);
  306.     findFiles(dir1, handleFile1, NULL);
  307.     printOutputBuffer();
  308.     free(outputBuffer);
  309.     return 0;
  310. }
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.

×