aboutsummaryrefslogtreecommitdiff
path: root/src/files.c
blob: 6842d634c0901fe7dd9b79274b97fe9bd19e8763 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

const char *get_filename_ext(const char *filename) {
  const char *dot = strrchr(filename, '.');
  if (!dot || dot == filename) return "";
  return dot + 1;
}

void cpdir(const char *path, const char *dest) {
  DIR *dirp = opendir(path);
  struct dirent *dirp_ent;

  struct stat dest_st;
  stat(path, &dest_st);
  if ((dest_st.st_mode & S_IFDIR) != 0) {
    mkdir(dest, dest_st.st_mode);
  }

  while ((dirp_ent = readdir(dirp))) {
    if (dirp_ent->d_name[0] == '.' &&
      (strlen(dirp_ent->d_name) == 1 ||
	      (strlen(dirp_ent->d_name) == 2 &&
	      dirp_ent->d_name[1] == '.')
      )
    )
      continue;
    char rfile_line[1024];
    struct stat st;
    char *filename = malloc(sizeof(path) + sizeof(dirp_ent->d_name) + 2);
    snprintf(
    	filename,
    	sizeof(path) + sizeof(dirp_ent->d_name) + 2,
    	"%s/%s",
    	path,
    	dirp_ent->d_name
   	);
    stat(filename, &st);
    if (st.st_mode) {
      char *newfile = malloc(sizeof(dest) + sizeof(dirp_ent->d_name) + 2);
      snprintf(
      	newfile,
      	sizeof(dest) + sizeof(dirp_ent->d_name) + 2,
      	"%s/%s",
        dest,
        dirp_ent->d_name
      );
      if ((st.st_mode & S_IFDIR) != 0) {
        mkdir(newfile, st.st_mode);
        cpdir(filename, newfile);
        continue;
      }
      FILE *rfile = fopen(dirp_ent->d_name, "r");
      FILE *wfile = fopen(newfile, "w+");
      if (!rfile || !wfile) {
        continue;
      }
      while (1) {
	      size_t ret = fread(rfile_line, 1, 1024, rfile);
	      if (ret != sizeof(rfile_line) / sizeof(rfile_line[0]) && ferror(rfile)) {
	        fprintf(stderr, "file read failed: %zu\n", ret);
	        break;
	      }
	      if (feof(rfile)) {
	        fclose(rfile);
	        fclose(wfile);
	        break;
	      }
	      size_t write = fwrite(rfile_line, 1, ret, wfile);
	      if (write != sizeof(rfile_line) / sizeof(rfile_line[0])) {
	        fprintf(stderr, "file write failed: %zu\n", ret);
	        break;
	      }
	      free(newfile);
	      if (feof(rfile)) {
	        fclose(rfile);
	        fclose(wfile);
	        break;
	      }
      }
    }
    free(filename);
  }
}