1 /*
2 * Copyright (C) 1995, 1996 Karl-Johan Johnsson.
3 */
4
5 #include "global.h"
6 #include <sys/stat.h>
7 #include <paths.h>
8 #include "expand.h"
9 #include "file.h"
10
11 #if 0
12 # define FILE_MASK 0666
13 # define DIR_MASK 0777
14 #else
15 # define FILE_MASK (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
16 # define DIR_MASK ((FILE_MASK)|S_IXUSR|S_IXGRP|S_IXOTH)
17 #endif
18
19 #ifndef O_ACCMODE
20 # define O_ACCMODE 3
21 #endif
22
open_mkdir(char * path,int flags,int report)23 int open_mkdir(char *path, int flags, int report)
24 {
25 struct stat stat_buf;
26 char *c;
27 int fd;
28
29 if (flags & O_CREAT)
30 fd = open(path, flags, FILE_MASK);
31 else
32 fd = open(path, flags);
33
34 if (fd >= 0)
35 return fd;
36
37 if (errno == ENOENT && (flags & O_ACCMODE) != O_RDONLY) {
38 if (path[0] == '/')
39 c = strchr(path + 1, '/');
40 else
41 c = strchr(path, '/');
42
43 while (c) {
44 *c = '\0';
45 if (stat(path, &stat_buf) < 0 &&
46 (errno != ENOENT || mkdir(path, DIR_MASK) < 0)) {
47 *c++ = '/';
48 return -1;
49 }
50
51 *c++ = '/';
52 c = strchr(c, '/');
53 }
54 }
55
56 if (flags & O_CREAT)
57 fd = open(path, flags, FILE_MASK);
58 else
59 fd = open(path, flags);
60
61 if (fd < 0 && (report || errno != ENOENT)) {
62 int oerrno = errno;
63 perror(path);
64 errno = oerrno;
65 }
66
67 return fd;
68 }
69
open_expand(char * file_name,int flags,int report)70 int open_expand(char *file_name, int flags, int report)
71 {
72 char *path;
73 int fd;
74
75 path = expand_path(file_name);
76 if (!path)
77 return -1;
78
79 fd = open_mkdir(path, flags, report);
80 XtFree(path);
81
82 return fd;
83 }
84
fopen_mkdir(char * path,char * mode,int report)85 FILE *fopen_mkdir(char *path, char *mode, int report)
86 {
87 int fd, flags;
88 FILE *ret;
89
90 switch (*mode) {
91 case 'a':
92 flags = O_WRONLY|O_APPEND|O_CREAT;
93 break;
94 case 'r':
95 flags = O_RDONLY;
96 break;
97 case 'w':
98 flags = O_WRONLY|O_TRUNC|O_CREAT;
99 break;
100 default:
101 fputs("knews: invalid mode to fopen_mkdir.\n", stderr);
102 return NULL;
103 }
104
105 fd = open_mkdir(path, flags, report);
106 if (fd < 0)
107 return NULL;
108
109 ret = fdopen(fd, mode);
110 if (!ret) {
111 perror("fdopen");
112 close(fd);
113 }
114
115 return ret;
116 }
117
fopen_expand(char * file_name,char * mode,int report)118 FILE *fopen_expand(char *file_name, char *mode, int report)
119 {
120 char *path;
121 FILE *fp;
122
123 path = expand_path(file_name);
124 if (!path)
125 return NULL;
126
127 fp = fopen_mkdir(path, mode, report);
128 XtFree(path);
129
130 return fp;
131 }
132
unlink_expand(char * file_name)133 int unlink_expand(char *file_name)
134 {
135 char *path;
136 int ret;
137
138 path = expand_path(file_name);
139 if (!path)
140 return -1;
141
142 ret = unlink(path);
143 XtFree(path);
144
145 return ret;
146 }
147
chdir_mkdir(char * path)148 int chdir_mkdir(char *path)
149 {
150 char *c, *p;
151
152 if (path[0] == '~' && path[1] == '/')
153 path += 2;
154 if (chdir(path) == 0)
155 return 0;
156 if (errno != ENOENT) {
157 perror(path);
158 return -1;
159 }
160
161 c = path;
162 p = strchr(c, '/');
163 for (;;) {
164 int tmp;
165
166 if (p)
167 *p = '\0';
168 tmp = chdir(c);
169 if (tmp < 0 && errno == ENOENT && mkdir(c, DIR_MASK) == 0)
170 tmp = chdir(c);
171 if (p)
172 *p++ = '/';
173 if (tmp < 0) {
174 perror(path);
175 return -1;
176 }
177 c = p;
178 if (!c)
179 break;
180 p = strchr(c, '\n');
181 }
182
183 return 0;
184 }
185
create_temp_fd(char ** name)186 int create_temp_fd(char **name)
187 {
188 int fd;
189 char filename[FILENAME_MAX];
190 char *tmpdir;
191
192 if ((tmpdir = getenv("TMPDIR")) == NULL)
193 tmpdir = _PATH_TMP;
194 strlcpy(filename, tmpdir, FILENAME_MAX);
195 strlcat(filename, "/tmp.XXXXXX", FILENAME_MAX);
196
197 if ((fd = mkstemp(filename)) == -1)
198 *name = NULL;
199 else
200 *name = filename;
201
202 return fd;
203 }
204
create_temp_file(char ** name)205 FILE *create_temp_file(char **name)
206 {
207 int fd;
208
209 fd = create_temp_fd(name);
210 if (fd < 0)
211 return NULL;
212
213 return fdopen(fd, "w+");
214 }
215
snarf_file(int fd,long * lenp)216 char *snarf_file(int fd, long *lenp)
217 {
218 struct stat stat_buf;
219 char *buffer;
220 long len, pos, n;
221
222 if (fstat(fd, &stat_buf) < 0) {
223 perror("fstat");
224 return NULL;
225 }
226
227 if (!S_ISREG(stat_buf.st_mode)) {
228 fputs("snarf_file: not a regular file!\n", stderr);
229 errno = EINVAL;
230 return NULL;
231 }
232
233 pos = 0;
234 len = stat_buf.st_size + 256;
235 buffer = malloc(len + 1);
236 if (!buffer) {
237 perror("malloc");
238 return NULL;
239 }
240
241 while ((n = read(fd, buffer + pos, len - pos)) != 0)
242 if (n < 0)
243 if (errno == EINTR)
244 continue;
245 else {
246 perror("read");
247 free(buffer);
248 return NULL;
249 }
250 else {
251 pos += n;
252 if (pos == len) {
253 char *tmp;
254
255 len *= 2;
256 tmp = realloc(buffer, len + 1);
257 if (!tmp) {
258 perror("realloc");
259 free(buffer);
260 return NULL;
261 }
262 buffer = tmp;
263 }
264 }
265
266 buffer[pos] = '\0';
267 if (lenp)
268 *lenp = pos;
269
270 return buffer;
271 }
272
writen(int fd,char * buf,long n)273 int writen(int fd, char *buf, long n)
274 {
275 long i;
276
277 while (n > 0)
278 switch ((i = write(fd, buf, n))) {
279 case -1:
280 perror("write");
281 return -1;
282 case 0:
283 fputs("knews: write(..) = 0, weird...\n", stderr);
284 return -1;
285 default:
286 buf += i;
287 n -= i;
288 break;
289 }
290
291 return 0;
292 }
293