Line data Source code
1 : #include "fd_file_util.h"
2 :
3 : #include <stdio.h>
4 : #include <errno.h>
5 : #include <limits.h>
6 : #include <dirent.h>
7 : #include <fcntl.h>
8 : #include <stdlib.h>
9 : #include <unistd.h>
10 : #include <sys/stat.h>
11 :
12 : int
13 : fd_file_util_read_ulong( char const * path,
14 0 : ulong * value ) {
15 0 : int fd = open( path, O_RDONLY );
16 0 : if( FD_UNLIKELY( -1==fd ) ) return -1;
17 :
18 0 : char buf[ 32UL ];
19 0 : long bytes_read = read(fd, buf, sizeof(buf)-1UL );
20 0 : if( FD_UNLIKELY( -1==bytes_read ) ) {
21 0 : close(fd);
22 0 : return -1;
23 0 : }
24 :
25 0 : if( FD_UNLIKELY( !bytes_read || (ulong)bytes_read>=sizeof(buf)-1UL ) ) {
26 0 : errno = EINVAL;
27 0 : close(fd);
28 0 : return -1;
29 0 : }
30 :
31 0 : buf[ bytes_read ] = '\0';
32 :
33 0 : if( FD_UNLIKELY( -1==close( fd ) ) ) return -1;
34 :
35 0 : char *endptr;
36 0 : errno = 0;
37 0 : ulong _value = strtoul( buf, &endptr, 10 );
38 0 : if( FD_UNLIKELY( errno==ERANGE ) ) return -1;
39 0 : if( FD_UNLIKELY( *endptr!='\n' && *endptr!='\0' ) ) {
40 0 : errno = EINVAL;
41 0 : return -1;
42 0 : }
43 :
44 0 : *value = _value;
45 0 : return 0;
46 0 : }
47 :
48 : int
49 : fd_file_util_read_uint( char const * path,
50 0 : uint * value ) {
51 0 : ulong _value;
52 0 : int rc = fd_file_util_read_ulong( path, &_value );
53 0 : if( FD_UNLIKELY( -1==rc ) ) return -1;
54 0 : if( FD_UNLIKELY( _value>UINT_MAX ) ) {
55 0 : errno = ERANGE;
56 0 : return -1;
57 0 : }
58 0 : *value = (uint)_value;
59 0 : return 0;
60 0 : }
61 :
62 : int
63 : fd_file_util_write_ulong( char const * path,
64 0 : ulong value ) {
65 0 : int fd = open( path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR );
66 0 : if( FD_UNLIKELY( -1==fd ) ) return -1;
67 :
68 0 : char buf[ 32UL ];
69 0 : int len = snprintf( buf, sizeof(buf), "%lu\n", value );
70 0 : FD_TEST( len>=0 && (ulong)len<sizeof(buf) );
71 :
72 0 : long written = write( fd, buf, (ulong)len );
73 0 : if( FD_UNLIKELY( -1==written ) ) {
74 0 : close( fd );
75 0 : return -1;
76 0 : } else if( FD_UNLIKELY( written!=len ) ) {
77 0 : errno = EINTR;
78 0 : close( fd );
79 0 : return -1;
80 0 : }
81 :
82 0 : if( FD_UNLIKELY( -1==close( fd ) ) ) return -1;
83 0 : return 0;
84 0 : }
85 :
86 : int
87 : fd_file_util_mkdir_all( const char * _path,
88 : uint uid,
89 0 : uint gid ) {
90 0 : char path[ PATH_MAX+1UL ] = {0};
91 0 : strncpy( path, _path, PATH_MAX );
92 :
93 0 : char * p = path;
94 0 : if( FD_LIKELY( *p == '/' ) ) p++;
95 :
96 0 : while( FD_LIKELY( *p ) ) {
97 0 : if( FD_UNLIKELY( *p == '/' ) ) {
98 0 : *p = '\0';
99 :
100 0 : int error = mkdir( path, 0777 );
101 0 : if( FD_UNLIKELY( -1==error && errno!=EEXIST ) ) return -1;
102 0 : if( FD_LIKELY( !error ) ) {
103 : /* Only take ownership of directories that we actually created
104 : (to avoid, for example, chowning the root directory). */
105 0 : if( FD_UNLIKELY( -1==chown( path, uid, gid ) ) ) return -1;
106 0 : if( FD_UNLIKELY( -1==chmod( path, S_IRUSR | S_IWUSR | S_IXUSR ) ) ) return -1;
107 0 : }
108 :
109 0 : *p = '/';
110 0 : }
111 0 : p++;
112 0 : }
113 :
114 0 : int error = mkdir( path, 0777 );
115 0 : if( FD_UNLIKELY( error && errno!=EEXIST ) ) return -1;
116 0 : if( FD_LIKELY( !error ) ) {
117 0 : if( FD_UNLIKELY( chown( path, uid, gid ) ) ) return -1;
118 0 : if( FD_UNLIKELY( chmod( path, S_IRUSR | S_IWUSR | S_IXUSR ) ) ) return -1;
119 0 : }
120 :
121 0 : return 0;
122 0 : }
123 :
124 : int
125 : fd_file_util_rmtree( char const * path,
126 0 : int remove_root ) {
127 0 : DIR * dir = opendir( path );
128 0 : if( FD_UNLIKELY( !dir ) ) {
129 0 : if( FD_LIKELY( errno==ENOENT ) ) return 0;
130 0 : return -1;
131 0 : }
132 :
133 0 : struct dirent * entry;
134 0 : errno = 0;
135 0 : while(( entry = readdir( dir ) )) {
136 0 : if( FD_LIKELY( !strcmp( entry->d_name, "." ) || !strcmp( entry->d_name, ".." ) ) ) continue;
137 :
138 0 : char path1[ PATH_MAX ];
139 0 : if( FD_UNLIKELY( !fd_cstr_printf_check( path1, PATH_MAX, NULL, "%s/%s", path, entry->d_name ) ) ) {
140 0 : errno = ERANGE;
141 0 : closedir( dir ); /* Ignore error code, fd is always closed */
142 0 : return -1;
143 0 : }
144 :
145 0 : struct stat st;
146 0 : if( FD_UNLIKELY( lstat( path1, &st ) ) ) {
147 0 : if( FD_LIKELY( errno==ENOENT ) ) continue;
148 0 : closedir( dir ); /* Ignore error code, fd is always closed */
149 0 : return -1;
150 0 : }
151 :
152 0 : if( FD_UNLIKELY( S_ISDIR( st.st_mode ) ) ) {
153 0 : fd_file_util_rmtree( path1, 1 );
154 0 : } else {
155 0 : if( FD_UNLIKELY( -1==unlink( path1 ) && errno!=ENOENT ) ) {
156 0 : closedir( dir ); /* Ignore error code, fd is always closed */
157 0 : return -1;
158 0 : }
159 0 : }
160 0 : }
161 :
162 0 : if( FD_UNLIKELY( -1==closedir( dir ) ) ) return -1;
163 0 : if( FD_UNLIKELY( errno && errno!=ENOENT ) ) return -1;
164 0 : if( FD_LIKELY( remove_root && -1==rmdir( path ) ) ) return -1;
165 :
166 0 : return 0;
167 0 : }
168 :
169 : int
170 0 : fd_file_util_self_exe( char path[ static PATH_MAX ] ) {
171 0 : long count = readlink( "/proc/self/exe", path, PATH_MAX );
172 0 : if( FD_UNLIKELY( -1==count ) ) return -1;
173 0 : if( FD_UNLIKELY( count>=PATH_MAX ) ) {
174 0 : errno = ERANGE;
175 0 : return -1;
176 0 : }
177 :
178 0 : path[ count ] = '\0';
179 0 : return 0;
180 0 : }
|