Directory: | src/ |
---|---|
File: | src/file.c |
Date: | 2024-04-25 03:45:42 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 56 | 84 | 66.7% |
Branches: | 20 | 52 | 38.5% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Copyright (c) 2022 Egor Tensin <egor@tensin.name> | ||
3 | * This file is part of the "cimple" project. | ||
4 | * For details, see https://github.com/egor-tensin/cimple. | ||
5 | * Distributed under the MIT License. | ||
6 | */ | ||
7 | |||
8 | #include "file.h" | ||
9 | #include "compiler.h" | ||
10 | #include "log.h" | ||
11 | |||
12 | #include <fcntl.h> | ||
13 | #include <ftw.h> | ||
14 | #include <stdio.h> | ||
15 | #include <stdlib.h> | ||
16 | #include <sys/stat.h> | ||
17 | #include <unistd.h> | ||
18 | |||
19 | 403638 | static int unlink_cb(const char *fpath, UNUSED const struct stat *sb, UNUSED int typeflag, | |
20 | UNUSED struct FTW *ftwbuf) | ||
21 | { | ||
22 | 403638 | int ret = 0; | |
23 | |||
24 | 403638 | ret = remove(fpath); | |
25 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 403638 times.
|
403638 | if (ret < 0) { |
26 | ✗ | log_errno("remove"); | |
27 | ✗ | return ret; | |
28 | } | ||
29 | |||
30 | 403638 | return ret; | |
31 | } | ||
32 | |||
33 | 9180 | int rm_rf(const char *dir) | |
34 | { | ||
35 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9180 times.
|
9180 | log("Recursively removing directory: %s\n", dir); |
36 | 9180 | return nftw(dir, unlink_cb, 64, FTW_DEPTH | FTW_PHYS); | |
37 | } | ||
38 | |||
39 | 18360 | int my_chdir(const char *dir, char **old) | |
40 | { | ||
41 | 18360 | int ret = 0; | |
42 | |||
43 |
2/2✓ Branch 0 taken 9180 times.
✓ Branch 1 taken 9180 times.
|
18360 | if (old) { |
44 | 9180 | *old = get_current_dir_name(); | |
45 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9180 times.
|
9180 | if (!*old) { |
46 | ✗ | log_errno("get_current_dir_name"); | |
47 | ✗ | return -1; | |
48 | } | ||
49 | } | ||
50 | |||
51 | 18360 | ret = chdir(dir); | |
52 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18360 times.
|
18360 | if (ret < 0) { |
53 | ✗ | log_errno("chdir"); | |
54 | ✗ | goto free_old; | |
55 | } | ||
56 | |||
57 | 18360 | return ret; | |
58 | |||
59 | ✗ | free_old: | |
60 | ✗ | if (old) | |
61 | ✗ | free(*old); | |
62 | |||
63 | ✗ | return ret; | |
64 | } | ||
65 | |||
66 | 20 | char *my_readlink(const char *path) | |
67 | { | ||
68 | 20 | size_t current_size = 256; | |
69 | 20 | char *buf = NULL; | |
70 | |||
71 | ✗ | while (1) { | |
72 | 20 | char *tmp_buf = realloc(buf, current_size); | |
73 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | if (!tmp_buf) { |
74 | ✗ | log_errno("realloc"); | |
75 | ✗ | goto free; | |
76 | } | ||
77 | 20 | buf = tmp_buf; | |
78 | |||
79 | 20 | ssize_t res = readlink(path, buf, current_size); | |
80 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | if (res < 0) { |
81 | ✗ | log_errno("readlink"); | |
82 | ✗ | goto free; | |
83 | } | ||
84 | |||
85 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | if ((size_t)res == current_size) { |
86 | ✗ | current_size *= 2; | |
87 | ✗ | continue; | |
88 | } | ||
89 | |||
90 | 20 | buf[res] = '\0'; | |
91 | 20 | break; | |
92 | } | ||
93 | |||
94 | 20 | return buf; | |
95 | |||
96 | ✗ | free: | |
97 | ✗ | free(buf); | |
98 | |||
99 | ✗ | return NULL; | |
100 | } | ||
101 | |||
102 | 9234 | int file_dup(int fd) | |
103 | { | ||
104 | 9234 | int ret = 0; | |
105 | |||
106 | 9234 | ret = fcntl(fd, F_DUPFD_CLOEXEC, 0); | |
107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9234 times.
|
9234 | if (ret < 0) { |
108 | ✗ | log_errno("fcntl"); | |
109 | ✗ | return ret; | |
110 | } | ||
111 | |||
112 | 9234 | return ret; | |
113 | } | ||
114 | |||
115 | 110566 | void file_close(int fd) | |
116 | { | ||
117 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 110566 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
110566 | log_errno_if(close(fd), "close"); |
118 | 110566 | } | |
119 | |||
120 | 36720 | int file_exists(const char *path) | |
121 | { | ||
122 | struct stat stat; | ||
123 | 36720 | int ret = lstat(path, &stat); | |
124 |
3/4✓ Branch 0 taken 9180 times.
✓ Branch 1 taken 27540 times.
✓ Branch 2 taken 9180 times.
✗ Branch 3 not taken.
|
36720 | return !ret && S_ISREG(stat.st_mode); |
125 | } | ||
126 | |||
127 | 9180 | int file_read(int fd, unsigned char **_contents, size_t *_size) | |
128 | { | ||
129 | 9180 | size_t alloc_size = 256; | |
130 | 9180 | unsigned char *contents = NULL; | |
131 | 9180 | size_t size = 0; | |
132 | |||
133 | 261952 | while (1) { | |
134 | 271132 | unsigned char *tmp_contents = realloc(contents, alloc_size); | |
135 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 271132 times.
|
271132 | if (!tmp_contents) { |
136 | ✗ | log_errno("realloc"); | |
137 | ✗ | free(contents); | |
138 | ✗ | return -1; | |
139 | } | ||
140 | 271132 | contents = tmp_contents; | |
141 | |||
142 | 271132 | ssize_t read_size = read(fd, contents + size, alloc_size - size); | |
143 | |||
144 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 271132 times.
|
271132 | if (read_size < 0) { |
145 | ✗ | log_errno("read"); | |
146 | ✗ | free(contents); | |
147 | ✗ | return read_size; | |
148 | } | ||
149 | |||
150 |
2/2✓ Branch 0 taken 9180 times.
✓ Branch 1 taken 261952 times.
|
271132 | if (!read_size) { |
151 | 9180 | *_contents = contents; | |
152 | 9180 | *_size = size; | |
153 | 9180 | return 0; | |
154 | } | ||
155 | |||
156 | 261952 | size += read_size; | |
157 | |||
158 |
2/2✓ Branch 0 taken 49896 times.
✓ Branch 1 taken 212056 times.
|
261952 | if (size == alloc_size) { |
159 | 49896 | alloc_size *= 2; | |
160 | } | ||
161 | } | ||
162 | } | ||
163 |