Krolyxon
Commit b096cbd

Branches

Refs →

nsxivutil.c

231 lines · 4.5 KB · C

1/* Copyright 2011 Bert Muennich
2 *
3 * This file is part of sxiv.
4 *
5 * sxiv is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published
7 * by the Free Software Foundation; either version 2 of the License,
8 * or (at your option) any later version.
9 *
10 * sxiv is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with sxiv. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdlib.h>
20#include <string.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <unistd.h>
24#include <errno.h>
25
26#include "options.h"
27#include "util.h"
28
29void cleanup(void);
30
31void* s_malloc(size_t size)
32{
33 void *ptr;
34
35 ptr = malloc(size);
36 if (ptr == NULL)
37 die("could not allocate memory");
38 return ptr;
39}
40
41void* s_realloc(void *ptr, size_t size)
42{
43 ptr = realloc(ptr, size);
44 if (ptr == NULL)
45 die("could not allocate memory");
46 return ptr;
47}
48
49char* s_strdup(const char *s)
50{
51 char *d = NULL;
52
53 if (s != NULL) {
54 d = malloc(strlen(s) + 1);
55 if (d == NULL)
56 die("could not allocate memory");
57 strcpy(d, s);
58 }
59 return d;
60}
61
62void warn(const char* fmt, ...)
63{
64 va_list args;
65
66 if (fmt == NULL || options->quiet)
67 return;
68
69 va_start(args, fmt);
70 fprintf(stderr, "sxiv: warning: ");
71 vfprintf(stderr, fmt, args);
72 fprintf(stderr, "\n");
73 va_end(args);
74}
75
76void die(const char* fmt, ...)
77{
78 va_list args;
79
80 if (fmt == NULL)
81 return;
82
83 va_start(args, fmt);
84 fprintf(stderr, "sxiv: error: ");
85 vfprintf(stderr, fmt, args);
86 fprintf(stderr, "\n");
87 va_end(args);
88
89 cleanup();
90 exit(EXIT_FAILURE);
91}
92
93void size_readable(float *size, const char **unit)
94{
95 const char *units[] = { "", "K", "M", "G" };
96 int i;
97
98 for (i = 0; i < ARRLEN(units) && *size > 1024.0; i++)
99 *size /= 1024.0;
100 *unit = units[MIN(i, ARRLEN(units) - 1)];
101}
102
103int r_opendir(r_dir_t *rdir, const char *dirname)
104{
105 if (*dirname == '\0')
106 return -1;
107
108 if ((rdir->dir = opendir(dirname)) == NULL) {
109 rdir->name = NULL;
110 rdir->stack = NULL;
111 return -1;
112 }
113
114 rdir->stcap = 512;
115 rdir->stack = (char**) s_malloc(rdir->stcap * sizeof(char*));
116 rdir->stlen = 0;
117
118 rdir->name = (char*) dirname;
119 rdir->d = 0;
120
121 return 0;
122}
123
124int r_closedir(r_dir_t *rdir)
125{
126 int ret = 0;
127
128 if (rdir->stack != NULL) {
129 while (rdir->stlen > 0)
130 free(rdir->stack[--rdir->stlen]);
131 free(rdir->stack);
132 rdir->stack = NULL;
133 }
134
135 if (rdir->dir != NULL) {
136 if ((ret = closedir(rdir->dir)) == 0)
137 rdir->dir = NULL;
138 }
139
140 if (rdir->d != 0) {
141 free(rdir->name);
142 rdir->name = NULL;
143 }
144
145 return ret;
146}
147
148char* r_readdir(r_dir_t *rdir)
149{
150 size_t len;
151 char *filename;
152 struct dirent *dentry;
153 struct stat fstats;
154
155 while (true) {
156 if (rdir->dir != NULL && (dentry = readdir(rdir->dir)) != NULL) {
157 if (dentry->d_name[0] == '.')
158 continue;
159
160 len = strlen(rdir->name) + strlen(dentry->d_name) + 2;
161 filename = (char*) s_malloc(len);
162 snprintf(filename, len, "%s%s%s", rdir->name,
163 rdir->name[strlen(rdir->name)-1] == '/' ? "" : "/",
164 dentry->d_name);
165
166 if (stat(filename, &fstats) < 0)
167 continue;
168 if (S_ISDIR(fstats.st_mode)) {
169 /* put subdirectory on the stack */
170 if (rdir->stlen == rdir->stcap) {
171 rdir->stcap *= 2;
172 rdir->stack = (char**) s_realloc(rdir->stack,
173 rdir->stcap * sizeof(char*));
174 }
175 rdir->stack[rdir->stlen++] = filename;
176 continue;
177 }
178 return filename;
179 }
180
181 if (rdir->stlen > 0) {
182 /* open next subdirectory */
183 closedir(rdir->dir);
184 if (rdir->d != 0)
185 free(rdir->name);
186 rdir->name = rdir->stack[--rdir->stlen];
187 rdir->d = 1;
188 if ((rdir->dir = opendir(rdir->name)) == NULL)
189 warn("could not open directory: %s", rdir->name);
190 continue;
191 }
192 /* no more entries */
193 break;
194 }
195 return NULL;
196}
197
198int r_mkdir(const char *path)
199{
200 char *dir, *d;
201 struct stat stats;
202 int err = 0;
203
204 if (*path == '\0')
205 return -1;
206
207 if (stat(path, &stats) == 0)
208 return S_ISDIR(stats.st_mode) ? 0 : -1;
209
210 d = dir = (char*) s_malloc(strlen(path) + 1);
211 strcpy(dir, path);
212
213 while (d != NULL && err == 0) {
214 d = strchr(d + 1, '/');
215 if (d != NULL)
216 *d = '\0';
217 if (access(dir, F_OK) < 0 && errno == ENOENT) {
218 if (mkdir(dir, 0755) < 0) {
219 warn("could not create directory: %s", dir);
220 err = -1;
221 }
222 } else if (stat(dir, &stats) < 0 || !S_ISDIR(stats.st_mode)) {
223 err = -1;
224 }
225 if (d != NULL)
226 *d = '/';
227 }
228 free(dir);
229
230 return err;
231}