2 Functions for file input/output.
14 #include <time.h> /* localtime */
23 Create a new file and open it for writing; creating new filenames if the file
25 RETURNS file descriptor
27 int create_and_open_file(
28 char * restrict filename
,
30 const char * restrict prefix
,
31 const char * restrict extension
34 time_t t
= time(NULL
);
35 struct tm tm
= *localtime(&t
);
39 snprintf(filename
, filename_size
, "%s%s_%04u%02u%02u%02u%02u.%s", data_folder(), prefix
,
40 tm
.tm_year
+ 1900, tm
.tm_mon
+ 1, tm
.tm_mday
, tm
.tm_hour
, tm
.tm_min
, extension
);
42 snprintf(filename
, filename_size
, "%s%s_%04u%02u%02u%02u%02u_%u.%s", data_folder(), prefix
,
43 tm
.tm_year
+ 1900, tm
.tm_mon
+ 1, tm
.tm_mday
, tm
.tm_hour
, tm
.tm_min
, attempt
, extension
);
46 int fd
= open(filename
, O_WRONLY
| O_CREAT
| O_EXCL
, S_IRUSR
| S_IWUSR
);
53 /* We will never be able to create the file */
54 if (errno
!= EEXIST
) {
63 RETURNS the number of bytes read or -1 if failed to open/be read
70 FILE * h
= fopen(filename
, "rb");
77 char * dst_buf2
= (char *)dst_buf
;
81 size_t rd
= fread(dst_buf2
+ total_read
, 1, buf_len
- total_read
, h
);
89 } while (buf_len
> total_read
&& (file_unfinished
= (feof(h
) == 0)));
93 file_unfinished
= (feof(h
) == 0);
97 if (file_unfinished
) {
99 snprintf(s
, MAX_PAGE_SIZ
, "file %s longer than buffer available for reading\n", filename
);
100 flog_crit("file", s
);
108 RETURNS the number of ASCII characters read or -1 if failed to open/be read
111 char * restrict dst_buf
,
113 const char * restrict filename
115 FILE * h
= fopen(filename
, "r"); /* text file, hopefully ASCII */
121 bool file_unfinished
;
124 size_t rd
= fread(dst_buf
+ total_read
, 1, buf_len
- total_read
, h
);
126 if (ferror(h
) != 0) {
128 snprintf(s
, MAX_PAGE_SIZ
, "%s: %s", filename
, strerror(errno
));
129 flog_warn("file", s
);
137 } while (buf_len
> total_read
&& (file_unfinished
= (feof(h
) == 0)));
141 file_unfinished
= (feof(h
) == 0);
145 if (file_unfinished
) {
147 snprintf(s
, MAX_PAGE_SIZ
, "%s: larger than buffer space", filename
);
148 flog_crit("file", s
);
153 dst_buf
[total_read
] = 0;
158 const char * restrict a
,
159 const char * restrict b
161 size_t len_a
= strlen(a
);
162 size_t len_b
= strlen(b
);
164 if (len_a
<= len_b
) {
168 size_t offset
= len_a
- len_b
;
170 for (u16 i
= 0; i
< len_b
; ++i
) {
171 if (a
[offset
+ i
] != b
[i
]) {
180 static u32 allocated
;
181 static u32 filenames_found
;
182 static u32 _max_files
;
184 static void _recurse_find_files(
185 const char * restrict root
,
186 const char * restrict extension
,
190 struct dirent
* entry
;
192 if (!(dir
= opendir(root
))) {
196 while (filenames_found
<= _max_files
&& (entry
= readdir(dir
)) != NULL
) {
197 if (entry
->d_name
[0] == '.') { /* ignore special and hidden files */
201 u32 strl
= strlen(root
) + strlen(entry
->d_name
) + 2;
202 if (strl
>= MAX_PATH_SIZ
) {
203 flog_crit("file", "path too long");
206 if (!ends_in(entry
->d_name
, extension
)) { /* try following as if folder */
207 char * path
= malloc(strl
);
210 flog_crit("file", "find files: system out of memory");
213 snprintf(path
, strl
, "%s%s/", root
, entry
->d_name
);
214 _recurse_find_files(path
, extension
, filenames
);
218 filenames
[filenames_found
] = malloc(strl
);
220 if (filenames
[filenames_found
] == NULL
) {
221 flog_crit("file", "find files: system out of memory");
224 snprintf(filenames
[filenames_found
], strl
, "%s%s", root
, entry
->d_name
);
227 if (filenames_found
> _max_files
) {
229 snprintf(s
, MAX_PAGE_SIZ
, "maximum number of files (%u) reached", _max_files
);
230 flog_crit("file", s
);
239 Searches for and allocates the space needed for the relative path to the files
240 found ending with the text present in extension.
241 At most fills max_files file names.
242 RETURN number of file names saved
244 u32
recurse_find_files(
245 const char * restrict root
,
246 const char * restrict extension
,
251 _max_files
= max_files
;
252 _recurse_find_files(root
, extension
, filenames
);
253 return filenames_found
;