Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_file.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
27
28#include <stdio.h>
29#include <errno.h>
30#include <string.h>
31#include <sys/types.h>
32
33#include "nilorea/n_files.h"
34#include "nilorea/n_log.h"
35#include "nilorea/n_str.h"
36
37#ifndef __windows__
38#include <sys/stat.h>
39#include <sys/wait.h>
40#endif
41
42void usage(void) {
43 fprintf(stderr,
44 " -v version\n"
45 " -V log level: LOG_INFO, LOG_NOTICE, LOG_ERR, LOG_DEBUG\n"
46 " -h help\n");
47}
48
49void process_args(int argc, char** argv) {
50 int getoptret = 0,
51 log_level = LOG_DEBUG; /* default log level */
52
53 /* Arguments optionnels */
54 /* -v version
55 * -V log level
56 * -h help
57 */
58 while ((getoptret = getopt(argc, argv, "hvV:")) != EOF) {
59 switch (getoptret) {
60 case 'v':
61 fprintf(stderr, "Date de compilation : %s a %s.\n", __DATE__, __TIME__);
62 exit(1);
63 case 'V':
64 if (!strcmp("LOG_NULL", optarg))
66 else if (!strcmp("LOG_NOTICE", optarg))
68 else if (!strcmp("LOG_INFO", optarg))
70 else if (!strcmp("LOG_ERR", optarg))
72 else if (!strcmp("LOG_DEBUG", optarg))
74 else {
75 fprintf(stderr, "%s n'est pas un niveau de log valide.\n", optarg);
76 exit(-1);
77 }
78 break;
79 default:
80 case '?': {
81 if (optopt == 'V') {
82 fprintf(stderr, "\n Missing log level\n");
83 } else if (optopt == 'p') {
84 fprintf(stderr, "\n Missing port\n");
85 } else if (optopt != 's') {
86 fprintf(stderr, "\n Unknow missing option %c\n", optopt);
87 }
88 usage();
89 exit(1);
90 }
91 case 'h': {
92 usage();
93 exit(1);
94 }
95 }
96 }
98} /* void process_args( ... ) */
99
101 n_log(LOG_DEBUG, "Inlined func");
102}
103
104/* Regression for n_file_write_atomic + n_file_read_bounded (n_files.h). */
105static int test_atomic_file(void) {
106 const char* path = "nilorea_ex_file_atomic.dat";
107 const unsigned char payload[] = {0x00, 0x41, 0xff, 0x42, 0x00, 0x7a};
108 unsigned char* buf = NULL;
109 size_t len = 0;
110 int rc = 0;
111
112 if (n_file_write_atomic(path, payload, sizeof(payload), 0600) != TRUE) {
113 n_log(LOG_ERR, "n_file_write_atomic failed");
114 return 1;
115 }
116 if (n_file_read_bounded(path, sizeof(payload), &buf, &len) != TRUE) {
117 n_log(LOG_ERR, "n_file_read_bounded failed");
118 remove(path);
119 return 1;
120 }
121 if (len != sizeof(payload) || memcmp(buf, payload, len) != 0) {
122 n_log(LOG_ERR, "atomic write/read round-trip mismatch (len %zu)", len);
123 rc = 1;
124 }
125 Free(buf);
126
127 /* the cap must reject a file larger than max_size */
128 if (n_file_read_bounded(path, sizeof(payload) - 1, &buf, &len) != FALSE) {
129 n_log(LOG_ERR, "n_file_read_bounded ignored the size cap");
130 Free(buf);
131 rc = 1;
132 }
133
134 /* the requested mode is on the file, not just on the temporary it came from */
135#ifndef __windows__
136 {
137 struct stat st;
138 if (stat(path, &st) != 0 || (st.st_mode & 07777) != 0600) {
139 n_log(LOG_ERR, "n_file_write_atomic did not apply the 0600 mode");
140 rc = 1;
141 }
142 }
143#endif
144
145 /* atomic replace over the existing file, shorter content */
146 if (n_file_write_atomic(path, payload, 3, 0600) != TRUE) {
147 n_log(LOG_ERR, "n_file_write_atomic overwrite failed");
148 rc = 1;
149 } else if (n_file_read_bounded(path, 16, &buf, &len) != TRUE || len != 3) {
150 n_log(LOG_ERR, "overwrite length wrong (len %zu)", len);
151 Free(buf);
152 rc = 1;
153 } else {
154 Free(buf);
155 }
156
157 remove(path);
158 return rc;
159}
160
161int main(int argc, char** argv) {
162 /* processing args and set log_level */
163 process_args(argc, argv);
164
165 if (test_atomic_file() != 0)
166 return 1;
167
168 inlined_func();
169
170 n_log(LOG_INFO, "TRUE,true values: %d,%d / FALSE,false value: %d,%d", TRUE, true, FALSE, false);
171
172 n_log(LOG_INFO, "_str(\"TEST\")=\"%s\" , _str(NULL)=\"%s\"", _str("TEST"), _str(NULL));
173 n_log(LOG_INFO, "_strw(\"TEST\")=\"%s\" , _strw(NULL)=\"%s\"", _str("TEST"), _str(NULL));
174 N_STR* nstr = char_to_nstr("TEST");
175 n_log(LOG_INFO, "_nstr(nstrpointer)=\"%s\"", _nstr(nstr));
176 n_log(LOG_INFO, "_nstrp(nstrpointer)=\"%s\"", _nstrp(nstr));
177 free_nstr(&nstr);
178 n_log(LOG_INFO, "_nstr(nstrpointer_freed)=\"%s\"", _nstr(nstr));
179 n_log(LOG_INFO, "_nstrp(nstrpointer_freed)=\"%s\"", _nstrp(nstr));
180
181 char* data = NULL;
182 __n_assert(data, n_log(LOG_INFO, "data is NULL"));
183 Malloc(data, char, 1024);
184 __n_assert(data, n_log(LOG_INFO, "data is NULL"));
185 Free(data);
186 Malloc(data, char, 1024);
187 Realloc(data, char, 2048);
188 Free(data);
189 Malloc(data, char, 1024);
190 Reallocz(data, char, 1024, 2048);
191 FreeNoLog(data);
192 Alloca(data, 2048);
193 // Free( data ); alloca should not be free else it's double freeing on exit
194
195 n_log(LOG_INFO, "next_odd(10):%d , next_odd(11):%d", next_odd(10), next_odd(11));
196 n_log(LOG_INFO, "next_even(10):%d , next_even(11):%d", next_even(10), next_even(11));
197
199 ifzero(0) endif;
200 ifzero(1) endif;
201 ifnull(data) endif;
202 ifnull(NULL) endif;
203 iffalse(FALSE) endif;
204 iftrue(TRUE) endif;
205 checkerror();
206error:
207 if (get_error()) {
208 n_log(LOG_INFO, "got an error while processing test");
209 } else {
210 n_log(LOG_INFO, "All tests for checkerror() are OK");
211 }
212
213 if (file_exist(argv[0])) {
214 n_log(LOG_INFO, "%s exists !", argv[0]);
215 }
216
217 char *dir = NULL, *name = NULL;
218 dir = get_prog_dir();
219 name = get_prog_name();
220 n_log(LOG_INFO, "From %s/%s", dir, name);
221 Free(dir);
222 Free(name);
223
224 N_STR* out = NULL;
225 int ret = -1;
226 if (n_popen("ls -ltr", 2048, (void*)&out, &ret) == TRUE) {
227 n_log(LOG_INFO, "ls returned %d : %s", ret, _nstr(out));
228 } else {
229 n_log(LOG_ERR, "popen s returned an error");
230 }
231 free_nstr(&out);
232
233 char hidden_str[47] = "";
234 N_HIDE_STR(hidden_str, 'T', 'h', 'i', 's', ' ', 's', 't', 'r', 'i', 'n', 'g', ' ', 'w', 'i', 'l', 'l', ' ', 'b', 'e', ' ', 'h', 'i', 'd', 'd', 'e', 'n', ' ', 'i', 'n', ' ', 't', 'h', 'e', ' ', 'f', 'i', 'n', 'a', 'l', ' ', 'b', 'i', 'n', 'a', 'r', 'y', '\0');
235 printf("hidden str:%s\n", hidden_str);
236
237 /* test n_scan_dir and n_free_file_info from n_files.h */
238 LIST* file_list = new_generic_list(0);
239 if (n_scan_dir(".", file_list, 0) == TRUE) {
240 n_log(LOG_INFO, "n_scan_dir found %zu files in current directory", file_list->nb_items);
241 list_foreach(fnode, file_list) {
242 N_FILE_INFO* fi = (N_FILE_INFO*)fnode->ptr;
243 if (fi && fi->name) {
244 n_log(LOG_DEBUG, " file: %s (time: %ld)", fi->name, (long)fi->filetime);
245 }
246 }
247 } else {
248 n_log(LOG_ERR, "n_scan_dir failed");
249 }
250 list_destroy(&file_list);
251
252#ifndef __windows__
253 n_log(LOG_INFO, "before system_nb( sleep 3 )");
254 int pid = system_nb("sleep 3", NULL, NULL);
255 n_log(LOG_INFO, "after system_nb( sleep 3 )");
256 n_log(LOG_INFO, "wait for nb sys call");
257 wait(&pid);
258 n_log(LOG_INFO, "done");
259 n_daemonize();
260#endif
261 n_abort("Testing abort before exit");
262 n_log(LOG_INFO, "abort done");
263 exit(0);
264}
static void usage(void)
void process_args(int argc, char **argv)
int main(void)
Definition ex_atlas.c:117
void inlined_func(void)
Definition ex_common.c:99
static int log_level
static int test_atomic_file(void)
Definition ex_file.c:105
int getoptret
Definition ex_fluid.c:59
#define FreeNoLog(__ptr)
Free Handler without log.
Definition n_common.h:272
char * get_prog_name(void)
get current program name
Definition n_common.c:149
#define get_error()
pop up errors if any
Definition n_common.h:331
void N_HIDE_STR(char *buf,...)
store a hidden version of a string
Definition n_common.c:762
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition n_common.h:204
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:279
#define _str(__PTR)
define true
Definition n_common.h:193
#define ifzero
error checker type if( 0 != toto )
Definition n_common.h:309
pid_t system_nb(const char *command, int *infp, int *outfp)
Non blocking system call.
Definition n_common.c:693
#define iffalse
error checker type if( toto == FALSE )
Definition n_common.h:312
#define Reallocz(__ptr, __struct, __old_size, __size)
Realloc + zero new memory zone Handler to get errors.
Definition n_common.h:247
#define next_odd(__val)
next odd helper
Definition n_common.h:296
#define Alloca(__ptr, __size)
Malloca Handler to get errors and set to 0.
Definition n_common.h:216
#define endif
close a ifwhatever block
Definition n_common.h:325
#define ifnull
error checker type if( !toto )
Definition n_common.h:306
#define _nstrp(__PTR)
N_STR or NULL pointer for testing purposes.
Definition n_common.h:201
#define next_even(__val)
next even helper
Definition n_common.h:299
char * get_prog_dir(void)
get current program running directory
Definition n_common.c:117
#define FORCE_INLINE
FORCE_INLINE portable macro.
Definition n_common.h:164
#define iftrue
error checker type if( toto == FALSE )
Definition n_common.h:315
#define checkerror()
check for errors
Definition n_common.h:318
void n_abort(char const *format,...)
abort program with a text
Definition n_common.c:57
int n_daemonize(void)
Daemonize program.
Definition n_common.c:587
#define init_error_check()
init error checking in a function
Definition n_common.h:302
#define Realloc(__ptr, __struct, __size)
Realloc Handler to get errors.
Definition n_common.h:231
int file_exist(const char *filename)
test if file exist and if it's readable
Definition n_common.c:104
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:263
#define _nstr(__PTR)
N_STR or "NULL" string for logging purposes.
Definition n_common.h:199
int n_popen(char *cmd, size_t read_buf_size, void **nstr_output, int *ret)
launch a command and return output and status
Definition n_common.c:184
size_t nb_items
number of item currently in the list
Definition n_list.h:61
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper, safe for node removal during iteration.
Definition n_list.h:89
int list_destroy(LIST **list)
Empty and Free a list container.
Definition n_list.c:548
LIST * new_generic_list(size_t max_items)
Initialiaze a generic list container to max_items pointers.
Definition n_list.c:37
Structure of a generic LIST container.
Definition n_list.h:59
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:113
#define LOG_DEBUG
debug-level messages
Definition n_log.h:108
#define LOG_ERR
error conditions
Definition n_log.h:100
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
Definition n_log.c:123
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:104
#define LOG_NULL
no log output
Definition n_log.h:70
#define LOG_INFO
informational
Definition n_log.h:106
time_t filetime
file creation time
Definition n_files.h:50
char * name
file name
Definition n_files.h:48
int n_file_write_atomic(const char *path, const unsigned char *data, size_t len, int mode)
durably and atomically write len bytes to path: write a "<path>.tmp" sibling created with mode from t...
Definition n_files.c:466
int n_file_read_bounded(const char *path, size_t max_size, unsigned char **out, size_t *out_len)
read a whole file into a freshly allocated, NUL-terminated buffer, refusing a file larger than max_si...
Definition n_files.c:270
int n_scan_dir(const char *dir, LIST *result, const int recurse)
Scan a directory and append only regular files into a sorted list (oldest first).
Definition n_files.c:196
common file information
Definition n_files.h:46
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition n_str.h:203
N_STR * char_to_nstr(const char *src)
Convert a char into a N_STR, short version.
Definition n_str.c:262
A box including a string and his lenght.
Definition n_str.h:61
Files configuration header.
Generic log system.
N_STR and string function declaration.