1 /* file_util.c - convenience routines for common stat operations
3 Copyright (C) 2009 Ubiq Technologies <graham.gower@gmail.com>
6 Copyright (C) 2001 University of Southern California
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
22 #include <sys/types.h>
27 #include "sprintf_alloc.h"
28 #include "file_util.h"
30 #include "libbb/libbb.h"
32 #if defined HAVE_SHA256
37 file_exists(const char *file_name
)
41 if (stat(file_name
, &st
) == -1)
48 file_is_dir(const char *file_name
)
52 if (stat(file_name
, &st
) == -1)
55 return S_ISDIR(st
.st_mode
);
58 /* read a single line from a file, stopping at a newline or EOF.
59 If a newline is read, it will appear in the resulting string.
60 Return value is a malloc'ed char * which should be freed at
61 some point by the caller.
63 Return value is NULL if the file is at EOF when called.
66 file_read_line_alloc(FILE *fp
)
71 unsigned int line_size
= 0;
76 while (fgets(buf
, BUFSIZ
, fp
)) {
77 buf_len
= strlen(buf
);
78 if (buf
[buf_len
- 1] == '\n') {
85 line
= xrealloc(line
, line_size
+1);
86 strncat(line
, buf
, line_size
);
88 line_size
= buf_len
+ 1;
99 file_move(const char *src
, const char *dest
)
103 err
= rename(src
, dest
);
105 if (errno
== EXDEV
) {
106 /* src & dest live on different file systems */
107 err
= file_copy(src
, dest
);
111 opkg_perror(ERROR
, "Failed to rename %s to %s",
120 file_copy(const char *src
, const char *dest
)
124 err
= copy_file(src
, dest
, FILEUTILS_FORCE
| FILEUTILS_PRESERVE_STATUS
);
126 opkg_msg(ERROR
, "Failed to copy file %s to %s.\n",
133 file_mkdir_hier(const char *path
, long mode
)
135 return make_directory(path
, mode
, FILEUTILS_RECUR
);
138 char *file_md5sum_alloc(const char *file_name
)
140 static const int md5sum_bin_len
= 16;
141 static const int md5sum_hex_len
= 32;
143 static const unsigned char bin2hex
[16] = {
153 unsigned char md5sum_bin
[md5sum_bin_len
];
155 md5sum_hex
= xcalloc(1, md5sum_hex_len
+ 1);
157 file
= fopen(file_name
, "r");
159 opkg_perror(ERROR
, "Failed to open file %s", file_name
);
164 err
= md5_stream(file
, md5sum_bin
);
166 opkg_msg(ERROR
, "Could't compute md5sum for %s.\n", file_name
);
174 for (i
=0; i
< md5sum_bin_len
; i
++) {
175 md5sum_hex
[i
*2] = bin2hex
[md5sum_bin
[i
] >> 4];
176 md5sum_hex
[i
*2+1] = bin2hex
[md5sum_bin
[i
] & 0xf];
179 md5sum_hex
[md5sum_hex_len
] = '\0';
185 char *file_sha256sum_alloc(const char *file_name
)
187 static const int sha256sum_bin_len
= 32;
188 static const int sha256sum_hex_len
= 64;
190 static const unsigned char bin2hex
[16] = {
200 unsigned char sha256sum_bin
[sha256sum_bin_len
];
202 sha256sum_hex
= xcalloc(1, sha256sum_hex_len
+ 1);
204 file
= fopen(file_name
, "r");
206 opkg_perror(ERROR
, "Failed to open file %s", file_name
);
211 err
= sha256_stream(file
, sha256sum_bin
);
213 opkg_msg(ERROR
, "Could't compute sha256sum for %s.\n", file_name
);
221 for (i
=0; i
< sha256sum_bin_len
; i
++) {
222 sha256sum_hex
[i
*2] = bin2hex
[sha256sum_bin
[i
] >> 4];
223 sha256sum_hex
[i
*2+1] = bin2hex
[sha256sum_bin
[i
] & 0xf];
226 sha256sum_hex
[sha256sum_hex_len
] = '\0';
228 return sha256sum_hex
;
235 rm_r(const char *path
)
243 opkg_perror(ERROR
, "Failed to open dir %s", path
);
247 if (fchdir(dirfd(dir
)) == -1) {
248 opkg_perror(ERROR
, "Failed to change to dir %s", path
);
255 if ((dent
= readdir(dir
)) == NULL
) {
257 opkg_perror(ERROR
, "Failed to read dir %s",
264 if (!strcmp(dent
->d_name
, ".") || !strcmp(dent
->d_name
, ".."))
268 if (dent
->d_type
== DT_DIR
) {
269 if ((ret
= rm_r(dent
->d_name
)) == -1)
272 } else if (dent
->d_type
== DT_UNKNOWN
)
276 if ((ret
= lstat(dent
->d_name
, &st
)) == -1) {
277 opkg_perror(ERROR
, "Failed to lstat %s",
281 if (S_ISDIR(st
.st_mode
)) {
282 if ((ret
= rm_r(dent
->d_name
)) == -1)
288 if ((ret
= unlink(dent
->d_name
)) == -1) {
289 opkg_perror(ERROR
, "Failed to unlink %s", dent
->d_name
);
294 if (chdir("..") == -1) {
296 opkg_perror(ERROR
, "Failed to change to dir %s/..", path
);
299 if (rmdir(path
) == -1 ) {
301 opkg_perror(ERROR
, "Failed to remove dir %s", path
);
304 if (closedir(dir
) == -1) {
306 opkg_perror(ERROR
, "Failed to close dir %s", path
);