Skip to content
Newer
Older
100644 302 lines (249 sloc) 5.95 KB
8f4af65 @muennich Refactored, new files util.[ch], C89
authored Feb 3, 2011
1 /* sxiv: util.c
2 * Copyright (c) 2011 Bert Muennich <muennich at informatik.hu-berlin.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include <stdlib.h>
26cc5af @muennich Read filenames from stdin
authored Feb 14, 2011
20 #include <string.h>
92709b2 @muennich Use directory structure in cache dir
authored Apr 7, 2011
21 #include <sys/types.h>
22 #include <sys/stat.h>
c21a3e3 @muennich Write thumbnail cache files on exit
authored Apr 7, 2011
23 #include <unistd.h>
24 #include <errno.h>
8f4af65 @muennich Refactored, new files util.[ch], C89
authored Feb 3, 2011
25
26 #include "options.h"
27 #include "util.h"
28
b8ff167 @muennich Major code refactoring
authored Jul 26, 2011
29 enum {
30 DNAME_CNT = 512,
31 FNAME_LEN = 1024
32 };
26cc5af @muennich Read filenames from stdin
authored Feb 14, 2011
33
8f4af65 @muennich Refactored, new files util.[ch], C89
authored Feb 3, 2011
34 void cleanup();
35
36 void* s_malloc(size_t size) {
37 void *ptr;
38
39 if (!(ptr = malloc(size)))
40 die("could not allocate memory");
41 return ptr;
42 }
43
44 void* s_realloc(void *ptr, size_t size) {
45 if (!(ptr = realloc(ptr, size)))
46 die("could not allocate memory");
47 return ptr;
48 }
49
50 void warn(const char* fmt, ...) {
51 va_list args;
52
53 if (!fmt || options->quiet)
54 return;
55
56 va_start(args, fmt);
57 fprintf(stderr, "sxiv: warning: ");
e8cf8da @muennich Fixed die/warn in util.c
authored Feb 3, 2011
58 vfprintf(stderr, fmt, args);
8f4af65 @muennich Refactored, new files util.[ch], C89
authored Feb 3, 2011
59 fprintf(stderr, "\n");
60 va_end(args);
61 }
62
63 void die(const char* fmt, ...) {
64 va_list args;
65
66 if (!fmt)
67 return;
68
69 va_start(args, fmt);
70 fprintf(stderr, "sxiv: error: ");
e8cf8da @muennich Fixed die/warn in util.c
authored Feb 3, 2011
71 vfprintf(stderr, fmt, args);
8f4af65 @muennich Refactored, new files util.[ch], C89
authored Feb 3, 2011
72 fprintf(stderr, "\n");
73 va_end(args);
74
75 cleanup();
76 exit(1);
77 }
bad9a70 @muennich Display filesize in window title
authored Feb 3, 2011
78
79 void size_readable(float *size, const char **unit) {
80 const char *units[] = { "", "K", "M", "G" };
81 int i;
82
b8ff167 @muennich Major code refactoring
authored Jul 26, 2011
83 for (i = 0; i < LEN(units) && *size > 1024; i++)
bad9a70 @muennich Display filesize in window title
authored Feb 3, 2011
84 *size /= 1024;
85 *unit = units[MIN(i, LEN(units) - 1)];
86 }
26cc5af @muennich Read filenames from stdin
authored Feb 14, 2011
87
c21a3e3 @muennich Write thumbnail cache files on exit
authored Apr 7, 2011
88 char* absolute_path(const char *filename) {
89 size_t len;
90 char *path = NULL;
91 const char *basename;
92 char *dirname = NULL;
93 char *cwd = NULL;
94 char *twd = NULL;
95 char *dir;
96 char *s;
97
98 if (!filename || *filename == '\0' || *filename == '/')
99 return NULL;
100
101 len = FNAME_LEN;
102 cwd = (char*) s_malloc(len);
103 while (!(s = getcwd(cwd, len)) && errno == ERANGE) {
104 len *= 2;
105 cwd = (char*) s_realloc(cwd, len);
106 }
107 if (!s)
108 goto error;
109
110 s = strrchr(filename, '/');
111 if (s) {
112 len = s - filename;
113 dirname = (char*) s_malloc(len + 1);
114 strncpy(dirname, filename, len);
115 dirname[len] = '\0';
116 basename = s + 1;
117
118 if (chdir(cwd))
119 /* we're not able to come back afterwards */
120 goto error;
121 if (chdir(dirname))
122 goto error;
123
124 len = FNAME_LEN;
125 twd = (char*) s_malloc(len);
126 while (!(s = getcwd(twd, len)) && errno == ERANGE) {
127 len *= 2;
128 twd = (char*) s_realloc(twd, len);
129 }
130 if (chdir(cwd))
f93f4d8 @muennich Write cache file for thumbnail directly after creating it
authored Apr 7, 2011
131 die("could not revert to prior working directory");
c21a3e3 @muennich Write thumbnail cache files on exit
authored Apr 7, 2011
132 if (!s)
133 goto error;
134 dir = twd;
135 } else {
136 /* only a single filename given */
137 basename = filename;
138 dir = cwd;
139 }
140
141 len = strlen(dir) + strlen(basename) + 2;
142 path = (char*) s_malloc(len);
143 snprintf(path, len, "%s/%s", dir, basename);
144
ea23115 @muennich Use getline instead of readline
authored May 29, 2011
145 goto end;
c21a3e3 @muennich Write thumbnail cache files on exit
authored Apr 7, 2011
146
147 error:
148 if (path) {
149 free(path);
150 path = NULL;
151 }
152
153 end:
154 if (dirname)
155 free(dirname);
156 if (cwd)
157 free(cwd);
158 if (twd)
159 free(twd);
160
161 return path;
162 }
163
a90bd1c @muennich Refactored recursive directory util functions
authored Apr 8, 2011
164 int r_opendir(r_dir_t *rdir, const char *dirname) {
165 if (!rdir || !dirname || !*dirname)
166 return -1;
167
168 if (!(rdir->dir = opendir(dirname))) {
169 rdir->name = NULL;
170 rdir->stack = NULL;
171 return -1;
172 }
173
174 rdir->stcap = DNAME_CNT;
175 rdir->stack = (char**) s_malloc(rdir->stcap * sizeof(char*));
176 rdir->stlen = 0;
177
178 rdir->name = (char*) dirname;
179 rdir->d = 0;
180
181 return 0;
182 }
183
184 int r_closedir(r_dir_t *rdir) {
185 int ret = 0;
186
187 if (!rdir)
188 return -1;
189
190 if (rdir->stack) {
191 while (rdir->stlen > 0)
192 free(rdir->stack[--rdir->stlen]);
193 free(rdir->stack);
194 rdir->stack = NULL;
195 }
196
197 if (rdir->dir) {
198 if (!(ret = closedir(rdir->dir)))
199 rdir->dir = NULL;
200 }
201
202 if (rdir->d && rdir->name) {
203 free(rdir->name);
204 rdir->name = NULL;
205 }
206
207 return ret;
208 }
209
210 char* r_readdir(r_dir_t *rdir) {
211 size_t len;
212 char *filename;
213 struct dirent *dentry;
214 struct stat fstats;
215
216 if (!rdir || !rdir->dir || !rdir->name)
217 return NULL;
218
219 while (1) {
220 if (rdir->dir && (dentry = readdir(rdir->dir))) {
221 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
222 continue;
223
224 len = strlen(rdir->name) + strlen(dentry->d_name) + 2;
225 filename = (char*) s_malloc(len);
226 snprintf(filename, len, "%s%s%s", rdir->name,
227 rdir->name[strlen(rdir->name)-1] == '/' ? "" : "/",
228 dentry->d_name);
229
230 if (!stat(filename, &fstats) && S_ISDIR(fstats.st_mode)) {
231 /* put subdirectory on the stack */
232 if (rdir->stlen == rdir->stcap) {
233 rdir->stcap *= 2;
234 rdir->stack = (char**) s_realloc(rdir->stack,
235 rdir->stcap * sizeof(char*));
236 }
237 rdir->stack[rdir->stlen++] = filename;
238 continue;
239 }
240 return filename;
241 }
242
243 if (rdir->stlen > 0) {
244 /* open next subdirectory */
245 closedir(rdir->dir);
246 if (rdir->d)
247 free(rdir->name);
248 rdir->name = rdir->stack[--rdir->stlen];
249 rdir->d = 1;
250 if (!(rdir->dir = opendir(rdir->name)))
251 warn("could not open directory: %s", rdir->name);
252 continue;
253 }
254
255 /* no more entries */
256 break;
257 }
258
259 return NULL;
260 }
261
262 int r_mkdir(const char *path) {
92709b2 @muennich Use directory structure in cache dir
authored Apr 7, 2011
263 char *dir, *d;
264 struct stat stats;
265 int err = 0;
266
267 if (!path || !*path)
268 return -1;
269
270 if (!stat(path, &stats)) {
271 if (S_ISDIR(stats.st_mode)) {
272 return 0;
273 } else {
274 warn("not a directory: %s", path);
275 return -1;
276 }
277 }
278
279 d = dir = (char*) s_malloc(strlen(path) + 1);
280 strcpy(dir, path);
281
282 while (d != NULL && !err) {
283 d = strchr(d + 1, '/');
284 if (d != NULL)
285 *d = '\0';
286 if (access(dir, F_OK) && errno == ENOENT) {
287 if (mkdir(dir, 0755)) {
288 warn("could not create directory: %s", dir);
289 err = -1;
290 }
291 } else if (stat(dir, &stats) || !S_ISDIR(stats.st_mode)) {
292 warn("not a directory: %s", dir);
293 err = -1;
294 }
295 if (d != NULL)
296 *d = '/';
297 }
298 free(dir);
299
300 return err;
301 }
Something went wrong with that request. Please try again.