/[path-sandbox]/trunk/libsbutil/src/file.c
Gentoo

Contents of /trunk/libsbutil/src/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 370 - (show annotations) (download) (as text)
Sun Nov 9 10:29:58 2008 UTC (5 years, 9 months ago) by vapier
File MIME type: text/x-csrc
File size: 9485 byte(s)
consolidate all random system includes into headers.h
1 /*
2 * file.c
3 *
4 * Miscellaneous file related macro's and functions.
5 *
6 * Copyright 1999-2008 Gentoo Foundation
7 * Copyright 2004-2007 Martin Schlemmer <azarah@nosferatu.za.org>
8 * Licensed under the GPL-2
9 */
10
11 #include "headers.h"
12 #include "rcscripts/rcutil.h"
13
14 bool
15 rc_file_exists (const char *pathname)
16 {
17 struct stat buf;
18 int retval;
19
20 if (!check_str (pathname))
21 return FALSE;
22
23 retval = lstat (pathname, &buf);
24 if (-1 != retval)
25 retval = TRUE;
26 else
27 retval = FALSE;
28
29 return retval;
30 }
31
32 bool
33 rc_is_file (const char *pathname, bool follow_link)
34 {
35 struct stat buf;
36 int retval;
37
38 if (!check_str (pathname))
39 return FALSE;
40
41 retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf);
42 if ((-1 != retval) && (S_ISREG (buf.st_mode)))
43 retval = TRUE;
44 else
45 retval = FALSE;
46
47 return retval;
48 }
49
50 bool
51 rc_is_link (const char *pathname)
52 {
53 struct stat buf;
54 int retval;
55
56 if (!check_str (pathname))
57 return FALSE;
58
59 retval = lstat (pathname, &buf);
60 if ((-1 != retval) && (S_ISLNK (buf.st_mode)))
61 retval = TRUE;
62 else
63 retval = FALSE;
64
65 return retval;
66 }
67
68 bool
69 rc_is_dir (const char *pathname, bool follow_link)
70 {
71 struct stat buf;
72 int retval;
73
74 if (!check_str (pathname))
75 return FALSE;
76
77 retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf);
78 if ((-1 != retval) && (S_ISDIR (buf.st_mode)))
79 retval = TRUE;
80 else
81 retval = FALSE;
82
83 return retval;
84 }
85
86 off_t
87 rc_get_size (const char *pathname, bool follow_link)
88 {
89 struct stat buf;
90 int retval;
91
92 if (!check_str (pathname))
93 return 0;
94
95 retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf);
96 if (-1 != retval)
97 retval = buf.st_size;
98 else
99 retval = 0;
100
101 return retval;
102 }
103
104 time_t
105 rc_get_mtime (const char *pathname, bool follow_link)
106 {
107 struct stat buf;
108 int retval;
109
110 if (!check_str (pathname))
111 return 0;
112
113 retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf);
114 if (-1 != retval)
115 retval = buf.st_mtime;
116 else
117 retval = 0;
118
119 return retval;
120 }
121
122 #if !defined(HAVE_REMOVE)
123 int
124 remove (const char *pathname)
125 {
126 int retval;
127
128 if (!check_arg_str (pathname))
129 return -1;
130
131 if (rc_is_dir (pathname, FALSE))
132 retval = rmdir (pathname);
133 else
134 retval = unlink (pathname);
135
136 if (0 != errno)
137 {
138 rc_errno_set (errno);
139 DBG_MSG ("Failed to remove() '%s'!\n", pathname);
140 }
141
142 return retval;
143 }
144 #endif
145
146 int
147 rc_mktree (const char *pathname, mode_t mode)
148 {
149 char *temp_name = NULL;
150 char *temp_token = NULL;
151 char *token_p;
152 char *token;
153 int retval;
154 int lenght;
155
156 if (!check_arg_str (pathname))
157 return -1;
158
159 /* Lenght of 'pathname' + extra for "./" if needed */
160 lenght = strlen (pathname) + 2;
161 /* lenght + '\0' */
162 temp_name = xmalloc (lenght + 1);
163 if (NULL == temp_name)
164 return -1;
165
166 temp_token = xstrndup (pathname, strlen (pathname));
167 if (NULL == temp_token)
168 goto error;
169
170 token_p = temp_token;
171
172 if (pathname[0] == '/')
173 temp_name[0] = '\0';
174 else
175 /* If not an absolute path, make it local */
176 strncpy (temp_name, ".", lenght);
177
178 token = strsep (&token_p, "/");
179 /* First token might be "", but that is OK as it will be when the
180 * pathname starts with '/' */
181 while (NULL != token)
182 {
183 strncat (temp_name, "/", lenght - strlen (temp_name));
184 strncat (temp_name, token, lenght - strlen (temp_name));
185
186 /* If it does not exist, create the dir. If it does exit,
187 * but is not a directory, we will catch it below. */
188 if (!rc_file_exists (temp_name))
189 {
190 retval = mkdir (temp_name, mode);
191 if (-1 == retval)
192 {
193 rc_errno_set (errno);
194 DBG_MSG ("Failed to create directory '%s'!\n", temp_name);
195 goto error;
196 }
197 /* Not a directory or symlink pointing to a directory */
198 }
199 else if (!rc_is_dir (temp_name, TRUE))
200 {
201 rc_errno_set (ENOTDIR);
202 DBG_MSG ("Component in '%s' is not a directory!\n", temp_name);
203 goto error;
204 }
205
206 do
207 {
208 token = strsep (&token_p, "/");
209 /* The first "" was Ok, but rather skip double '/' after that */
210 }
211 while ((NULL != token) && (0 == strlen (token)));
212 }
213
214 free (temp_name);
215 free (temp_token);
216
217 return 0;
218
219 error:
220 free (temp_name);
221 free (temp_token);
222
223 return -1;
224 }
225
226 int
227 rc_rmtree (const char *pathname)
228 {
229 char **dirlist = NULL;
230 int i = 0;
231
232 if (!check_arg_str (pathname))
233 return -1;
234
235 if (!rc_file_exists (pathname))
236 {
237 rc_errno_set (ENOENT);
238 DBG_MSG ("'%s' does not exist!\n", pathname);
239 return -1;
240 }
241
242 if (!rc_is_dir (pathname, FALSE))
243 {
244 rc_errno_set (ENOTDIR);
245 DBG_MSG ("'%s' is not a directory!\n", pathname);
246 return -1;
247 }
248
249
250 dirlist = rc_ls_dir (pathname, TRUE, FALSE);
251 if ((NULL == dirlist) && (rc_errno_is_set ()))
252 {
253 /* Do not error out - caller should decide itself if it
254 * it is an issue */
255 DBG_MSG ("Failed to ls_dir() directory '%s'!\n", pathname);
256 return -1;
257 }
258
259 while ((NULL != dirlist) && (NULL != dirlist[i]))
260 {
261 /* If it is a directory, call rc_rmtree() again with
262 * it as argument */
263 if (rc_is_dir (dirlist[i], FALSE))
264 {
265 if (-1 == rc_rmtree (dirlist[i]))
266 {
267 DBG_MSG ("Failed to rm_tree() directory '%s'!\n", dirlist[i]);
268 goto error;
269 }
270 }
271
272 /* Now actually remove it. Note that if it was a directory,
273 * it should already be removed by above rc_rmtree() call */
274 if ((rc_file_exists (dirlist[i]) && (-1 == remove (dirlist[i]))))
275 {
276 rc_errno_set (errno);
277 DBG_MSG ("Failed to remove() '%s'!\n", dirlist[i]);
278 goto error;
279 }
280 i++;
281 }
282
283 str_list_free (dirlist);
284
285 /* Now remove the parent */
286 if (-1 == remove (pathname))
287 {
288 rc_errno_set (errno);
289 DBG_MSG ("Failed to remove '%s'!\n", pathname);
290 goto error;
291 }
292
293 return 0;
294 error:
295 str_list_free (dirlist);
296
297 return -1;
298 }
299
300 char **
301 rc_ls_dir (const char *pathname, bool hidden, bool sort)
302 {
303 DIR *dp;
304 struct dirent *dir_entry;
305 char **dirlist = NULL;
306
307 if (!check_arg_str (pathname))
308 return NULL;
309
310 if (!rc_is_dir (pathname, TRUE))
311 {
312 /* XXX: Should we error here? */
313 DBG_MSG ("'%s' is not a directory.\n", pathname);
314 return NULL;
315 }
316
317 dp = opendir (pathname);
318 if (NULL == dp)
319 {
320 rc_errno_set (errno);
321 DBG_MSG ("Failed to opendir() '%s'!\n", pathname);
322 /* errno will be set by opendir() */
323 goto error;
324 }
325
326 do
327 {
328 /* Clear errno to distinguish between EOF and error */
329 errno = 0;
330 dir_entry = readdir (dp);
331 /* Only an error if 'errno' != 0, else EOF */
332 if ((NULL == dir_entry) && (0 != errno))
333 {
334 rc_errno_set (errno);
335 DBG_MSG ("Failed to readdir() '%s'!\n", pathname);
336 goto error;
337 }
338 if ((NULL != dir_entry)
339 /* Should we display hidden files? */
340 && (hidden ? 1 : dir_entry->d_name[0] != '.'))
341 {
342 char *d_name = dir_entry->d_name;
343 char *str_ptr;
344
345 /* Do not list current or parent entries */
346 if ((0 == strcmp (d_name, ".")) || (0 == strcmp (d_name, "..")))
347 continue;
348
349 str_ptr = rc_strcatpaths (pathname, d_name);
350 if (NULL == str_ptr)
351 {
352 DBG_MSG ("Failed to allocate buffer!\n");
353 goto error;
354 }
355
356 if (sort)
357 str_list_add_item_sorted (dirlist, str_ptr, error);
358 else
359 str_list_add_item (dirlist, str_ptr, error);
360 }
361 }
362 while (NULL != dir_entry);
363
364 if (!check_strv (dirlist))
365 {
366 if (NULL != dirlist)
367 str_list_free (dirlist);
368
369 DBG_MSG ("Directory '%s' is empty.\n", pathname);
370 }
371
372 closedir (dp);
373
374 return dirlist;
375
376 error:
377 /* Free dirlist on error */
378 str_list_free (dirlist);
379
380 if (NULL != dp)
381 closedir (dp);
382
383 return NULL;
384 }
385
386
387 /*
388 * Below two functions (rc_file_map and rc_file_unmap) are
389 * from udev-050 (udev_utils.c).
390 * (Some are slightly modified, please check udev for originals.)
391 *
392 * Copyright 2004 Kay Sievers <kay@vrfy.org>
393 *
394 * This program is free software; you can redistribute it and/or modify it
395 * under the terms of the GNU General Public License as published by the
396 * Free Software Foundation version 2 of the License.
397 *
398 * This program is distributed in the hope that it will be useful, but
399 * WITHOUT ANY WARRANTY; without even the implied warranty of
400 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
401 * General Public License for more details.
402 *
403 * You should have received a copy of the GNU General Public License along
404 * with this program; if not, write to the Free Software Foundation, Inc.,
405 * 675 Mass Ave, Cambridge, MA 02139, USA.
406 *
407 */
408
409 int
410 rc_file_map (const char *filename, char **buf, size_t * bufsize)
411 {
412 struct stat stats;
413 int fd;
414
415 fd = open (filename, O_RDONLY);
416 if (fd < 0)
417 {
418 rc_errno_set (errno);
419 DBG_MSG ("Failed to open file!\n");
420 return -1;
421 }
422
423 if (fstat (fd, &stats) < 0)
424 {
425 rc_errno_set (errno);
426 DBG_MSG ("Failed to stat file!\n");
427
428 close (fd);
429
430 return -1;
431 }
432
433 if (0 == stats.st_size)
434 {
435 rc_errno_set (EINVAL);
436 DBG_MSG ("Failed to mmap file with 0 size!\n");
437
438 close (fd);
439
440 return -1;
441 }
442
443 *buf = mmap (NULL, stats.st_size, PROT_READ, MAP_SHARED, fd, 0);
444 if (*buf == MAP_FAILED)
445 {
446 rc_errno_set (errno);
447 DBG_MSG ("Failed to mmap file!\n");
448
449 close (fd);
450
451 return -1;
452 }
453 *bufsize = stats.st_size;
454
455 close (fd);
456
457 return 0;
458 }
459
460 void
461 rc_file_unmap (char *buf, size_t bufsize)
462 {
463 munmap (buf, bufsize);
464 }

  ViewVC Help
Powered by ViewVC 1.1.20