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 0 : uint gid ) {
91 0 : char path[ PATH_MAX+1UL ] = {0};
92 0 : strncpy( path, _path, PATH_MAX );
93 :
94 0 : char * p = path;
95 0 : if( FD_LIKELY( *p == '/' ) ) p++;
96 :
97 0 : while( FD_LIKELY( *p ) ) {
98 0 : if( FD_UNLIKELY( *p == '/' ) ) {
99 0 : *p = '\0';
100 :
101 0 : int error = mkdir( path, 0777 );
102 0 : if( FD_UNLIKELY( -1==error && errno!=EEXIST ) ) return -1;
103 0 : if( FD_LIKELY( !error ) ) {
104 : /* Only take ownership of directories that we actually created
105 : (to avoid, for example, chowning the root directory). */
106 0 : if( FD_UNLIKELY( -1==chown( path, uid, gid ) ) ) return -1;
107 0 : if( FD_UNLIKELY( -1==chmod( path, S_IRUSR | S_IWUSR | S_IXUSR ) ) ) return -1;
108 0 : }
109 :
110 0 : *p = '/';
111 0 : }
112 0 : p++;
113 0 : }
114 :
115 0 : int error = mkdir( path, 0777 );
116 0 : if( FD_UNLIKELY( error && errno!=EEXIST ) ) return -1;
117 0 : if( FD_LIKELY( !error ) ) {
118 0 : if( FD_UNLIKELY( chown( path, uid, gid ) ) ) return -1;
119 0 : if( FD_UNLIKELY( chmod( path, S_IRUSR | S_IWUSR | S_IXUSR ) ) ) return -1;
120 0 : }
121 :
122 0 : return 0;
123 0 : }
124 :
125 : int
126 : fd_file_util_rmtree( char const * path,
127 0 : int remove_root ) {
128 0 : DIR * dir = opendir( path );
129 0 : if( FD_UNLIKELY( !dir ) ) {
130 0 : if( FD_LIKELY( errno==ENOENT ) ) return 0;
131 0 : return -1;
132 0 : }
133 :
134 0 : struct dirent * entry;
135 0 : errno = 0;
136 0 : while(( entry = readdir( dir ) )) {
137 0 : if( FD_LIKELY( !strcmp( entry->d_name, "." ) || !strcmp( entry->d_name, ".." ) ) ) continue;
138 :
139 0 : char path1[ PATH_MAX ];
140 0 : if( FD_UNLIKELY( !fd_cstr_printf_check( path1, PATH_MAX, NULL, "%s/%s", path, entry->d_name ) ) ) {
141 0 : errno = ERANGE;
142 0 : closedir( dir ); /* Ignore error code, fd is always closed */
143 0 : return -1;
144 0 : }
145 :
146 0 : struct stat st;
147 0 : if( FD_UNLIKELY( lstat( path1, &st ) ) ) {
148 0 : if( FD_LIKELY( errno==ENOENT ) ) continue;
149 0 : closedir( dir ); /* Ignore error code, fd is always closed */
150 0 : return -1;
151 0 : }
152 :
153 0 : if( FD_UNLIKELY( S_ISDIR( st.st_mode ) ) ) {
154 0 : fd_file_util_rmtree( path1, 1 );
155 0 : } else {
156 0 : if( FD_UNLIKELY( -1==unlink( path1 ) && errno!=ENOENT ) ) {
157 0 : closedir( dir ); /* Ignore error code, fd is always closed */
158 0 : return -1;
159 0 : }
160 0 : }
161 0 : }
162 :
163 0 : if( FD_UNLIKELY( -1==closedir( dir ) ) ) return -1;
164 0 : if( FD_UNLIKELY( errno && errno!=ENOENT ) ) return -1;
165 0 : if( FD_LIKELY( remove_root && -1==rmdir( path ) ) ) return -1;
166 :
167 0 : return 0;
168 0 : }
169 :
170 : int
171 0 : fd_file_util_self_exe( char path[ static PATH_MAX ] ) {
172 0 : long count = readlink( "/proc/self/exe", path, PATH_MAX );
173 0 : if( FD_UNLIKELY( -1==count ) ) return -1;
174 0 : if( FD_UNLIKELY( count>=PATH_MAX ) ) {
175 0 : errno = ERANGE;
176 0 : return -1;
177 0 : }
178 :
179 0 : path[ count ] = '\0';
180 0 : return 0;
181 0 : }
182 :
183 : char *
184 : fd_file_util_read_all( char const * path,
185 0 : ulong * out_sz ) {
186 0 : int fd = open( path, O_RDONLY );
187 0 : if( FD_UNLIKELY( -1==fd ) ) return MAP_FAILED;
188 :
189 0 : struct stat st;
190 0 : if( FD_UNLIKELY( fstat( fd, &st ) ) ) {
191 0 : if( FD_UNLIKELY( -1==close( fd ) ) ) FD_LOG_WARNING(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
192 0 : return MAP_FAILED;
193 0 : }
194 :
195 0 : ulong toml_sz = (ulong)st.st_size;
196 0 : if( FD_UNLIKELY( toml_sz==0UL ) ) {
197 0 : if( FD_UNLIKELY( -1==close( fd ) ) ) FD_LOG_WARNING(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
198 0 : errno = EINVAL;
199 0 : return MAP_FAILED;
200 0 : }
201 :
202 0 : void * mem = mmap( NULL, toml_sz, PROT_READ, MAP_PRIVATE, fd, 0 );
203 0 : if( FD_UNLIKELY( mem==MAP_FAILED ) ) {
204 0 : if( FD_UNLIKELY( -1==close( fd ) ) ) FD_LOG_WARNING(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
205 0 : return MAP_FAILED;
206 0 : }
207 :
208 0 : if( FD_UNLIKELY( -1==close( fd ) ) ) FD_LOG_WARNING(( "close() failed (%i-%s)", errno, fd_io_strerror( errno ) ));
209 :
210 0 : *out_sz = toml_sz;
211 0 : return (char *)mem;
212 0 : }
|