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