Commit | Line | Data |
---|---|---|
4cf40131 ACM |
1 | #include <sys/mman.h> |
2 | #include <sys/stat.h> | |
3 | #include <sys/types.h> | |
4 | #include <fcntl.h> | |
5 | #include <string.h> | |
6 | #include <unistd.h> | |
7 | #include "util.h" | |
8 | ||
9 | int mkdir_p(char *path, mode_t mode) | |
10 | { | |
11 | struct stat st; | |
12 | int err; | |
13 | char *d = path; | |
14 | ||
15 | if (*d != '/') | |
16 | return -1; | |
17 | ||
18 | if (stat(path, &st) == 0) | |
19 | return 0; | |
20 | ||
21 | while (*++d == '/'); | |
22 | ||
23 | while ((d = strchr(d, '/'))) { | |
24 | *d = '\0'; | |
25 | err = stat(path, &st) && mkdir(path, mode); | |
26 | *d++ = '/'; | |
27 | if (err) | |
28 | return -1; | |
29 | while (*d == '/') | |
30 | ++d; | |
31 | } | |
32 | return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; | |
33 | } | |
34 | ||
9e201442 ACM |
35 | static int slow_copyfile(const char *from, const char *to) |
36 | { | |
37 | int err = 0; | |
38 | char *line = NULL; | |
39 | size_t n; | |
40 | FILE *from_fp = fopen(from, "r"), *to_fp; | |
41 | ||
42 | if (from_fp == NULL) | |
43 | goto out; | |
44 | ||
45 | to_fp = fopen(to, "w"); | |
46 | if (to_fp == NULL) | |
47 | goto out_fclose_from; | |
48 | ||
49 | while (getline(&line, &n, from_fp) > 0) | |
50 | if (fputs(line, to_fp) == EOF) | |
51 | goto out_fclose_to; | |
52 | err = 0; | |
53 | out_fclose_to: | |
54 | fclose(to_fp); | |
55 | free(line); | |
56 | out_fclose_from: | |
57 | fclose(from_fp); | |
58 | out: | |
59 | return err; | |
60 | } | |
61 | ||
4cf40131 ACM |
62 | int copyfile(const char *from, const char *to) |
63 | { | |
64 | int fromfd, tofd; | |
65 | struct stat st; | |
66 | void *addr; | |
67 | int err = -1; | |
68 | ||
69 | if (stat(from, &st)) | |
70 | goto out; | |
71 | ||
9e201442 ACM |
72 | if (st.st_size == 0) /* /proc? do it slowly... */ |
73 | return slow_copyfile(from, to); | |
74 | ||
4cf40131 ACM |
75 | fromfd = open(from, O_RDONLY); |
76 | if (fromfd < 0) | |
77 | goto out; | |
78 | ||
79 | tofd = creat(to, 0755); | |
80 | if (tofd < 0) | |
81 | goto out_close_from; | |
82 | ||
83 | addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0); | |
84 | if (addr == MAP_FAILED) | |
85 | goto out_close_to; | |
86 | ||
87 | if (write(tofd, addr, st.st_size) == st.st_size) | |
88 | err = 0; | |
89 | ||
90 | munmap(addr, st.st_size); | |
91 | out_close_to: | |
92 | close(tofd); | |
93 | if (err) | |
94 | unlink(to); | |
95 | out_close_from: | |
96 | close(fromfd); | |
97 | out: | |
98 | return err; | |
99 | } |