Advertisement
Alyks

lab2

Apr 21st, 2021
928
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.27 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement