Untitled

By Coral Wigeon, ago, written in C.
URL http://pastecode.org/index.php/view/74547114
Download Paste or View RawExpand paste to full width of browser | Change Viewing Options
  1. #define _GNU_SOURCE
  2. #define _NO_PASARAN
  3.  
  4. #include <limits.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <dirent.h>
  9. #include <errno.h>
  10. #include <sys/stat.h>
  11. #include <sys/types.h>
  12. #include <string.h>
  13.  
  14. #ifndef PATH_MAX
  15.     #define PATH_MAX 4096
  16. #endif
  17.  
  18. void print_usage() {
  19.     printf("Usage: backup source_dir destination_dir\n");
  20. }
  21.  
  22. int f_copy(char *src_file, char *dest_file, mode_t mode) {
  23.     char tail[9];
  24.     char middle_file[PATH_MAX + 1];
  25.  
  26.     int i;
  27.     for (i = 0; i < 8; ++i) {
  28.         tail[i] = (char)(rand() % 10) + '0';
  29.     }
  30.     tail[8] = '\0';
  31.    
  32.     int res = snprintf(middle_file, PATH_MAX, "%s%s", dest_file, tail);
  33.     if (res < 0 || res >= PATH_MAX) {
  34.         fprintf(stderr, \
  35.             "backup: path length limit exceeded while concatenating intermediate file '%s%s'; omitted\n", \
  36.             dest_file, tail);
  37.         return 666;
  38.     }
  39.    
  40.     FILE *src_FILE = fopen(src_file, "r");
  41.     FILE *dest_FILE = fopen(middle_file, "w");
  42.     if (!src_FILE) {
  43.         return 1;
  44.     }
  45.     if (!dest_FILE) {
  46.         return 2;
  47.     }
  48.    
  49.     int ch;
  50.     while (1) {
  51.         ch = getc(src_FILE);
  52.         if (ch == EOF) {
  53.             break;
  54.         }
  55.         putc(ch, dest_FILE);
  56.     }
  57.  
  58.     fclose(src_FILE);
  59.     fclose(dest_FILE);
  60.  
  61.     if (chmod(middle_file, mode)) {
  62.         fprintf(stderr, "backup: unable to chmod '%s': ", dest_file);
  63.         perror(NULL);
  64.     }
  65.  
  66.     unlink(dest_file);
  67.     rename(middle_file, dest_file);
  68.    
  69.     return 0;
  70. }
  71.  
  72. int f_case_copy(char *src_file, char *dest_file) {
  73.     struct stat src_stat, dest_stat;
  74.        
  75.     if (stat(src_file, &src_stat)) {
  76.         fprintf(stderr, "backup: failed to get file status on '%s': ", src_file);
  77.         perror(NULL);
  78.         return -1;
  79.     }
  80.  
  81.     int dest_stat_res;
  82.     dest_stat_res = stat(dest_file, &dest_stat);
  83.  
  84.     if (dest_stat_res || (!S_ISDIR(dest_stat.st_mode) && dest_stat.st_mtime < src_stat.st_mtime)) {
  85.         int res = f_copy(src_file, dest_file, src_stat.st_mode);
  86.         switch (res) {
  87.             case 1:  fprintf(stderr, "backup: failed to open file '%s' for reading: ", src_file);
  88.                 perror(NULL);
  89.                 return 1;
  90.                 break;
  91.             case 2:  fprintf(stderr, "backup: failed to open file '%s' for writing: ", dest_file);
  92.                 perror(NULL);
  93.                 return 2;
  94.                 break;
  95.         }
  96.     } else {
  97.         if (S_ISDIR(dest_stat.st_mode)) {
  98.             fprintf(stderr, "backup: unable to replace directory '%s' by file '%s'", dest_file, src_file);
  99.             perror(NULL);
  100.             return 3;
  101.         }
  102.     }
  103.     return 0;
  104. }
  105.  
  106. void rec_copy(char *src_dir_s, char *dest_dir_s) {
  107.     DIR *src_dir;
  108.     struct stat src_dir_stat, dest_dir_stat;
  109.  
  110.     if (!(src_dir = opendir(src_dir_s))) {
  111.         fprintf(stderr, "backup: skipping directory '%s': ", src_dir_s);
  112.         perror(NULL);
  113.         return;
  114.     }
  115.  
  116.     if (stat(src_dir_s, &src_dir_stat)) {
  117.         fprintf(stderr, "backup: failed to get directory status on '%s': ", src_dir_s);
  118.         perror(NULL);
  119.         return;
  120.     }
  121.  
  122.     if (stat(dest_dir_s, &dest_dir_stat)) {
  123.         if (mkdir(dest_dir_s, src_dir_stat.st_mode)) {
  124.             fprintf(stderr, "backup: failed to get status on '%s' and create such a directory at the same time: ", dest_dir_s);
  125.             perror(NULL);
  126.             return;
  127.         } else {
  128.             if (chmod(dest_dir_s, src_dir_stat.st_mode)) {
  129.                 fprintf(stderr, "backup: unable to chmod '%s': ", dest_dir_s);
  130.                 perror(NULL);
  131.             }            
  132.         }
  133.     } else {
  134.         if (!S_ISDIR(dest_dir_stat.st_mode)) {
  135.             fprintf(stderr, "backup: unable to copy to '%s', which exists and is not a directory: ", dest_dir_s);
  136.             perror(NULL);
  137.             return;
  138.         }
  139.     }
  140.  
  141.     struct dirent *src_dirent;
  142.     while ((src_dirent  = readdir(src_dir)) != NULL) {
  143.         struct stat f_stat;
  144.         char name_s[PATH_MAX + 1];
  145.  
  146.         int res = snprintf(name_s, PATH_MAX, "%s/%s", src_dir_s, src_dirent->d_name);
  147.         if (res < 0 || res >= PATH_MAX) {
  148.             fprintf(stderr, \
  149.                 "backup: path length limit exceeded while concatenating '%s/%s'; omitted\n", \
  150.                 src_dir_s, src_dirent->d_name);
  151.             continue;
  152.         }
  153.  
  154.         stat(name_s, &f_stat);
  155.         if (S_ISDIR(f_stat.st_mode)) {
  156.             if (strcmp(src_dirent->d_name, ".") && strcmp(src_dirent->d_name, "..")){
  157.                 char name2_s[PATH_MAX + 1];
  158.  
  159.                 int res = snprintf(name2_s, PATH_MAX, "%s/%s", dest_dir_s, src_dirent->d_name);
  160.                 if (res < 0 || res >= PATH_MAX) {
  161.                     fprintf(stderr, \
  162.                         "backup: path length limit exceeded while concatenating '%s/%s'; omitted\n", \
  163.                         dest_dir_s, src_dirent->d_name);
  164.                     continue;
  165.                 }
  166.  
  167.                 rec_copy(name_s, name2_s);
  168.             }
  169.         } else {
  170.             char name2_s[PATH_MAX + 1];
  171.  
  172.             int res = snprintf(name2_s, PATH_MAX, "%s/%s", dest_dir_s, src_dirent->d_name);
  173.             if (res < 0 || res >= PATH_MAX) {
  174.                 fprintf(stderr, \
  175.                     "backup: path length limit exceeded while concatenating '%s/%s'; omitted\n", \
  176.                     dest_dir_s, src_dirent->d_name);
  177.                 continue;
  178.             }
  179.            
  180.             f_case_copy(name_s, name2_s);            
  181.         }
  182.     }
  183.  
  184.     closedir(src_dir);
  185. }
  186.  
  187. int main(int argc, char **argv) {
  188.     if (argc != 3) {
  189.         print_usage();
  190.         exit(-1);
  191.     }
  192.  
  193.     char src_dir[PATH_MAX + 1];
  194.     char dest_dir[PATH_MAX + 1];
  195.  
  196.     if (!realpath(argv[1], src_dir)) {
  197.         fprintf(stderr, "backup: '%s': ", src_dir);
  198.         perror(NULL);
  199.         exit(-1);
  200.     }
  201.  
  202.     if (argv[2][0] != '/') {
  203.         char *cwd = get_current_dir_name();
  204.         int res = snprintf(dest_dir, PATH_MAX, "%s/%s", cwd, argv[2]);
  205.         free(cwd);
  206.         if (res < 0 || res >= PATH_MAX) {
  207.             fprintf(stderr, \
  208.                 "backup: path length limit exceeded while concatenating '%s/%s'; omitted\n", \
  209.                 cwd, argv[2]);
  210.             return -1;
  211.         }        
  212.     } else {
  213.         int res = snprintf(dest_dir, PATH_MAX, "%s", argv[2]);
  214.         if (res < 0 || res >= PATH_MAX) {
  215.             fprintf(stderr, \
  216.                 "backup: path length limit exceeded while dealing with '%s'; omitted\n", \
  217.                 argv[2]);
  218.             return -1;
  219.         }          
  220.     }
  221.  
  222.     rec_copy(src_dir, dest_dir);
  223.  
  224.     return 0;
  225. }
  226.  

Here you can reply to the paste above

Make Private