summaryrefslogtreecommitdiff
path: root/src/libsystem/libsystem.h
blob: 7819aa7d7ca2be084409d12701ddabe2e50b4bee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/

/*
 * libsystem
 *
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the License);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @file libsystem.h
 *
 * system utility library
 *
 * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
 *
 */

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#ifndef __cplusplus
#include <stdbool.h>
#endif
#include <unistd.h>
#include <string.h>
#include <dirent.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Many functions have no effects except the return value and their
 * return value depends only on the parameters and/or global
 * variables. Such a function can be subject to common subexpression
 * elimination and loop optimization just as an arithmetic operator
 * would be. These functions should be declared with the attribute
 * pure.
 */
#define _pure_ __attribute__ ((pure))

/**
 * The cleanup attribute runs a function when the variable goes out of
 * scope. This attribute can only be applied to auto function scope
 * variables; it may not be applied to parameters or variables with
 * static storage duration. The function must take one parameter, a
 * pointer to a type compatible with the variable. The return value of
 * the function (if any) is ignored.
 */
#define _cleanup_(x) __attribute__((cleanup(x)))

/**
 * whitespaces such like space, tab or newlines
 */
#define WHITESPACE " \t\n\r"

/**
 * newlines
 */
#define NEWLINE "\n\r"

/**
 * single or double quotes
 */
#define QUOTES "\"\'"

/**
 * comment start specifiers such like sharp(#) or semicolon(;)
 */
#define COMMENTS "#;"

/**
 * @defgroup GCC_CLEANUP_ATT_GROUP gcc cleanup attribute
 *
 * @{
 */

static inline void __cleanup_free_func(void *p) {
        free(*(void**) p);
}

static inline void __cleanup_close_func(int *fd) {
        if (*fd >= 0)
                close(*fd);
}

static inline void __cleanup_fclose_func(FILE **f) {
        if (*f)
                fclose(*f);
}

static inline void __cleanup_pclose_func(FILE **f) {
        if (*f)
                pclose(*f);
}

static inline void __cleanup_closedir_func(DIR **d) {
        if (*d)
                closedir(*d);
}

static inline const char *startswith(const char *s, const char *prefix) {
        if (strncmp(s, prefix, strlen(prefix)) == 0)
                return s + strlen(prefix);
        return NULL;
}

static inline bool isempty(const char *p) {
        return !p || !p[0];
}

/**
 * Declare value with cleanup attribute. free() is called when is
 * going out the scope.
 */
#define _cleanup_free_ _cleanup_(__cleanup_free_func)

/**
 * Declare value with cleanup attribute. close() is called when is
 * going out the scope.
 */
#define _cleanup_close_ _cleanup_(__cleanup_close_func)

/**
 * Declare value with cleanup attribute. fclose() is called when is
 * going out the scope.
 */
#define _cleanup_fclose_ _cleanup_(__cleanup_fclose_func)

/**
 * Declare value with cleanup attribute. pclose() is called when is
 * going out the scope.
 */
#define _cleanup_pclose_ _cleanup_(__cleanup_pclose_func)

/**
 * Declare value with cleanup attribute. closedir() is called when is
 * going out the scope.
 */
#define _cleanup_closedir_ _cleanup_(__cleanup_closedir_func)
/**
 * @}
 */

/**
 * Allocate n number of size t memory.
 */
#define new(t, n) ((t*) malloc(sizeof(t) * (n)))

/**
 * Allocate n number of size t memory. And initialize to 0 all.
 */
#define new0(t, n) ((t*) calloc((n), sizeof(t)))

/**
 * Allocate n number memory.
 */
#define malloc0(n) (calloc((n), 1))

/**
 * @brief Parse boolean type string.
 *
 * @param v String to parse.
 *
 * @return TRUE on "1", 'y', 'Y', 't', 'T' and "on". FALSE on "0",
 * 'n', 'N', 'f', 'F', "off".
 */
int parse_boolean(const char *v) _pure_;

/**
 * @brief Parse byte type string.
 *
 * @param b Byte string. This can be only digit number with byte unit
 * "BKMG". B is byte, K is kilo byte, M is mega byte and G is gira
 * byte. Byte is default.
 * @param s Parsed byte size is filled.
 *
 * @return 0 on success, -errno on failure.
 */
int parse_bytes(const char *b, size_t *s) _pure_;

/**
 * @brief Parse percentage type string.
 *
 * @param string Percentage string to parse. Such like "70%".
 * @param percent Parsed percentage size is filled.
 *
 * @return 0 on success, -errno on failure.
 */
int parse_percent(const char *string, size_t *percent) _pure_;

/**
 * @brief check the path string is started with '/'
 *
 * @param p a path to check
 *
 * @return true if p started with '/', otherwise false.
 */
bool path_is_absolute(const char *p);

/**
 * @brief Removes redundant inner and trailing slashes. Modifies the
 * passed string in-place. For example, if "///foo//bar/" is given
 * then the path will be changed as "/foo/bar"
 *
 * @param path a path to modify.
 *
 * @return modified path pointer. It maybe identical with given path.
 */
char *path_kill_slashes(char *path);

/**
 * Get element number of array.
 */
#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))

/**
 * Iterate for each struct reference.
 */
#define FOREACH_STRUCT_REF(s, f, i)                  \
        for ((i) = 0; s[(i)].f != NULL; (i)++)

/**
 * @brief Iterate for each directory entries exclude "." and "..".
 */
#define FOREACH_DIRENT(de, d, on_error)                                 \
        for (errno = 0, de = readdir(d);; errno = 0, de = readdir(d))   \
                if (!de) {                                              \
                        if (errno > 0) {                                \
                                on_error;                               \
                        }                                               \
                        break;                                          \
                } else if (streq(de->d_name, ".") ||                    \
                           streq(de->d_name, ".."))                     \
                        continue;                                       \
                else

/**
 * @brief Check string is digit.
 *
 * @param s String to check.
 * @param l Length to check.
 *
 * @return TRUE on all the characters are digit. FALSE on the others.
 */
bool is_number(const char *s, int l);

/**
 * @brief Run cp with given src, dst with option. Internally, directly
 * calls /bin/cp with given arguments.
 * @todo change direct calls of /bin/cp to c api.
 *
 * @param src source
 * @param dst destination
 * @param option cp option
 * @param timeout_msec timeout milliseconds
 *
 * @return return exit code of /bin/cp or negative errno.
 */
int do_copy(const char *src, const char *dst, const char *option, int64_t timeout_msec);

/**
 * @brief Make a directory. If parent directories are also absent,
 * make them also. Corresponding with "mkdir -p".
 *
 * @param path Path to make directory.
 * @param mode The directory mode.
 *
 * @return 0 on success, -errno on failure.
 */
int do_mkdir(const char *path, mode_t mode);

/**
 * @brief Remove all elements in path recursivly.
 *
 * @param path Path to make directory.
 *
 * @return 0 on success, -errno on failure.
 */
int rmdir_recursive(const char *path);

/**
 * @defgroup FILE_READ_WRITE_GROUP File Read/Write utility
 *
 * @{
 */

/**
 * file write flags
 */
enum file_write_flags {
        /** Append line-end(\\n) at the end of file. In case of string
         * write, if given string has already line-end characters
         * then this flag has no effect. */
        FILE_WRITE_NEWLINE_IF_NOT       =  1 << 0,
        /** Run fflush(3) after file write. */
        FILE_WRITE_WITH_FFLUSH          =  1 << 1,
        /** Open file as append mode. */
        FILE_WRITE_APPEND               =  1 << 2,
};

/**
 * @brief Write strings to FILE
 *
 * @param f File pointer.
 * @param str Strings to write.
 * @param flags Optional flags to write file. For
 * ::FILE_WRITE_NEWLINE_IF_NOT, if str has already line-end,
 * ::FILE_WRITE_NEWLINE_IF_NOT will has no effect. For detail, see
 * ::file_write_flags.
 *
 * @return 0 on success, -errno on failure.
 */
int write_str_to_file(FILE *f, const char *str, enum file_write_flags flags);

/**
 * @brief Write strings to path.
 *
 * @param path File path.
 * @param str Strings to write.
 * @param flags Optional flags to write file. For
 * ::FILE_WRITE_NEWLINE_IF_NOT, if str has already line-end,
 * ::FILE_WRITE_NEWLINE_IF_NOT will has no effect. For detail, see
 * ::file_write_flags.
 *
 * @return 0 on success, -errno on failure.
 */
int write_str_to_path(const char *path, const char *str, enum file_write_flags flags);

/**
 * @brief Write signed decimal integer to FILE.
 *
 * @param f File pointer.
 * @param i Signed integer to write.
 * @param flags Optional flags to write file. if
 * ::FILE_WRITE_NEWLINE_IF_NOT is set, line-end added. For detail, see
 * ::file_write_flags.
 *
 * @return 0 on success, -errno on failure.
 */
int write_int32_to_file(FILE *f, int32_t i, enum file_write_flags flags);

/**
 * @brief Write signed decimal integer to path.
 *
 * @param path File path.
 * @param i Signed integer to write.
 * @param flags Optional flags to write file. if
 * ::FILE_WRITE_NEWLINE_IF_NOT is set, line-end added. For detail, see
 * ::file_write_flags.
 *
 * @return 0 on success, -errno on failure.
 */
int write_int32_to_path(const char *path, int32_t i, enum file_write_flags flags);

/**
 * @brief Write unsigned decimal integer to FILE.
 *
 * @param f File pointer
 * @param u Unsigned integer to write.
 * @param flags Optional flags to write file. if
 * ::FILE_WRITE_NEWLINE_IF_NOT is set, line-end added. For detail, see
 * ::file_write_flags.
 *
 * @return 0 on success, -errno on failure.
 */
int write_uint32_to_file(FILE *f, uint32_t u, enum file_write_flags flags);

/**
 * @brief Write unsigned decimal integer to path.
 *
 * @param path File path.
 * @param u Unsigned integer to write.
 * @param flags Optional flags to write file. if
 * ::FILE_WRITE_NEWLINE_IF_NOT is set, line-end added. For detail, see
 * ::file_write_flags.
 *
 * @return 0 on success, -errno on failure.
 */
int write_uint32_to_path(const char *path, uint32_t u, enum file_write_flags flags);

/**
 * @brief Read the first line from FILE
 *
 * @param f File pointer.
 * @param line Duplicated string line is filled. This value has to
 * be free-ed by caller.
 *
 * @return 0 on success, -errno on failure.
 */
int read_one_line_from_file(FILE *f, char **line);

/**
 * @brief Read the first line from path
 *
 * @param path File path.
 * @param line Duplicated string line is filled. This value has to
 * be free-ed by caller.
 *
 * @return 0 on success, -errno on failure.
 */
int read_one_line_from_path(const char *path, char **line);

/**
 * @brief Read signed decimal integer from FILE.
 *
 * @param f File pointer.
 * @param i signed int value pointer.
 *
 * @return 0 on success, -errno on failure.
 */
int read_int32_from_file(FILE *f, int32_t *i);

/**
 * @brief Read signed decimalinteger from path.
 *
 * @param path File path.
 * @param i signed int value pointer.
 *
 * @return 0 on success, -errno on failure.
 */
int read_int32_from_path(const char *path, int32_t *i);

/**
 * @brief Read unsigned decimalinteger from FILE.
 *
 * @param f File pointer.
 * @param u unsigned int value pointer.
 *
 * @return 0 on success, -errno on failure.
 */
int read_uint32_from_file(FILE *f, uint32_t *u);

/**
 * @brief Read unsigned decimal integer from path
 *
 * @param path File path.
 * @param u unsigned int value pointer.
 *
 * @return 0 on success, -errno on failure.
 */
int read_uint32_from_path(const char *path, uint32_t *u);
/**
 * @}
 */

/**
 * @defgroup STRING_GROUP String helper
 *
 * @{
 */

/**
 * Compare two strings. TRUE on same, FALSE on others.
 * Same with (strcmp((a),(b)) == 0)
 */
#define streq(a,b) (strcmp((a),(b)) == 0)
/**
 * Compare two strings for n length. TRUE on same, FALSE on others.
 * Same with (strncmp((a), (b), (n)) == 0)
 */
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)

/**
 * Compare two strings. Similar to streq() but ignore case. TRUE on
 * same, FALSE on others.
 * Same with (strcasecmp((a),(b)) == 0)
 */
#define strcaseeq(a,b) (strcasecmp((a),(b)) == 0)

/**
 * Compare two strings for n length. Similar to strneq() but ignore
 * case. TRUE on same, FALSE on others.
 * Same with (strcasecmp((a),(b)) == 0)
 */
#define strncaseeq(a, b, n) (strncasecmp((a), (b), (n)) == 0)

/**
 * Iterate string in strings which include null characters.
 * For example,
 *\code{.c}
const char str[] = {
        "foo\0"
        "bar\0";
};

const char *s;

NULSTR_FOREACH(s, str) {
        // do something here
}
 *\endcode
 */
#define NULSTR_FOREACH(i, l)                                    \
        for ((i) = (l); (i) && *(i); (i) = strchr((i), 0)+1)

/**
 * @brief Like streq(), but tries to make sense of NULL pointers.
 *
 * @param a String.
 * @param b String.
 *
 * @return TRUE on same, FALSE on the others.
 */
bool streq_ptr(const char *a, const char *b) _pure_;

/**
 * @brief Truncate line end characters.
 *
 * @param s String to truncate.
 *
 * @return Result string.
 */
char *truncate_nl(char *s);

/**
 * @brief Append suffix string to sting s with size b.
 *
 * @param s Ahead string.
 * @param suffix The second string.
 * @param b suffix size to append.
 *
 * @return Result string. This string has to be free-ed by caller.
 */
char *strnappend(const char *s, const char *suffix, size_t b);

/**
 * @brief Append suffix string to sting s.
 *
 * @param s Ahead string.
 * @param suffix The second string.
 *
 * @return Result string. This string has to be free-ed by caller.
 */
char *strappend(const char *s, const char *suffix);

/**
 * @brief Drops trailing whitespaces.
 *
 * @param s String.
 *
 * @return The pointer to the first non-space character.
 */
char *strstrip(char *s);

/**
 * @brief duplicate string without leading and trailing whitespaces
 *
 * @param str a target string to duplicate
 * @param ret newly allocated string is filled
 *
 * @return 0 on success, -errno on failure.
 */
int strdup_strip(const char *str, char **ret);

/**
 * @brief duplicate string without leading and trailing whitespaces,
 * duplicated string is not over given length len
 *
 * @param str a target string to duplicate
 * @param len maxium length of duplicate
 * @param ret newly allocated string is filled
 *
 * @return 0 on success, -errno on failure.
 */
int strndup_strip(const char *str, size_t len, char **ret);

/**
 * @brief nulstr is similar to string list but each strings ends with
 * null and the strings are put at one memory buffer. For example,
 * "foo" and "bar" string can be represented "foo\0bar". This function
 * check nulstr is containing the needle string.
 *
 * @param nulstr a nulstr
 * @param needle a needle string to find
 *
 * @return true if the needle found, otherwise false.
 */
bool nulstr_contains(const char*nulstr, const char *needle);

/**
 * @brief check a string ends with postfix pattern
 *
 * @param s a string to check
 * @param postfix postfix string
 *
 * @return if s is ended with postfix string the pointer of the
 * string, matched pointer of s is returned. Otherwise NULL.
 */
char* endswith(const char *s, const char *postfix);

/**
 * @brief split a string into words. This api generally is not called
 * directly, #FOREACH_WORD_SEPARATOR or #FOREACH_WORD are using
 * this. If separator does not include quotes then quoted words are
 * assumed as single word.
 *
 * @param c string to split
 * @param l splitted word length
 * @param separator separator strings such like #WHITESPACE
 * @param state a state internally used
 *
 * @return a splitted current word pointer
 */
char *split(const char *c, size_t *l, const char *separator, char **state);

/**
 * @brief Iterate for each words. If separator does not include quotes
 * then quoted words are assumed as single word.
 *
 * @param word Each word
 * @param length Length of word
 * @param s Target string
 * @param separator Seperator string
 * @param state Used only internal split().
 */
#define FOREACH_WORD_SEPARATOR(word, length, s, separator, state)       \
        for ((state) = NULL, (word) = split((s), &(length), (separator), &(state)); (word); (word) = split((s), &(length), (separator), &(state)))

/**
 * @brief Iterate for each words. (Seperators are WHITESPACES.) Quoted
 * words are assumed as single word.
 *
 * @param word Each word
 * @param length Length of word
 * @param s Target string
 * @param state Used only internal split().
 */
#define FOREACH_WORD(word, length, s, state)                            \
        FOREACH_WORD_SEPARATOR(word, length, s, WHITESPACE, state)

/**
 * @brief Duplicate string and strip quotes from the string.
 *
 * @param str String to duplicate.
 * @param quotes Quote characters to strip. Predefined #QUOTES can be
 * used to specify quote and double quote.
 *
 * @return Result string. This value has to be free-ed by caller.
 */
char *strdup_unquote(const char *str, const char *quotes);
/**
 * @}
 */

/**
 * @defgroup STRV_GROUP String List
 *
 * @{
 */

/**
 * iterate for each elements of string list.
 */
#define FOREACH_STRV(s, l)                      \
        for ((s) = (l); (s) && *(s); (s)++)

/**
 * @brief Split given string to string list with separator.
 *
 * @param str string to split as string list.
 * @param strv Splitted string list is filled. This string list has to
 *   be free-ed.
 * @param separator sperators to split the string.
 *
 * @return 0 on success, -errno on failure.
 */
int str_to_strv(const char *str, char ***strv, const char *separator);

/**
 * @brief Get elements of string list. #sizeof_strv() does not count
 * end of list NULL. For example, for {"foo", "bar", NULL} string
 * list, #sizeof_strv() returns 2.
 *
 * @param strv string list.
 *
 * @return number of string list.
 */
size_t sizeof_strv(char **strv);

/**
 * @brief Merge two string lists. If {"foo", "bar"} and {"baz", "qux"}
 * are given, the result is {"foo", "bar", "baz", "quz"}.
 *
 * @param first The first string list.
 * @param second The second string list.
 * @param strv Merged string list.
 * @param free_second If TRUE is given, the second string list will be
 * free-ed. If FALSE, no action.
 *
 * @return number of string list.
 */
int strv_attach(char **first, char **second, char ***strv, bool free_second);

/**
 * @brief Free all given string list
 *
 * @param strv string list to free.
 */
void strv_free_full(char **strv);
/**
 * @}
 */

/**
 * @brief Check given path is directory or not
 *
 * @param path path to check
 *
 * @return TRUE if path is directory, FALSE on others.
 */
bool isdir(const char *path);

/**
 * @brief Simple file create api similar to touch(1)
 *
 * @param path file path
 *
 * @return 0 on success, -errno on failure.
 */
int touch(const char *path);

/**
 * @defgroup PROC_GROUP proc group
 *
 * @brief A set utility library for /proc. Some of library functions
 * are only able to be successful root uid with security permissions.
 *
 * @{
 */

/**
 * @brief Get string with operator from /proc/cmdline. If foo=bar is
 * included in /proc/cmdline and want to get the bar, then:
 * \code{.c}
        char *buf;

        cmdline_get_str(&buf, "foo=");
 * \endcode
 *
 * @param buf The value string is filled to here. This value has to be
 * free-ed by caller.
 * @param op An operator string.
 *
 * @return Result string. This value has to be free-ed by caller.
 */
ssize_t cmdline_get_str(char **buf, const char *op);

/**
 * @brief Get PID of process.
 *
 * @param pname Process name.
 *
 * @return PID on successful find. If not found, 0 is returned. And
 * -errno is returned on failure.
 */
int pid_of(const char *pname);

/**
 * @brief Check mount entry. Multiple matches of conditoin are able to
 * be set with mnt_fsname, mnt_dir, mnt_type or mnt_opts. If multiple
 * matches are given, return true if a entry satisfied all matches.
 *
 * \code{.c}
// check cgroup is mounted
if (is_mounted("cgroup", NULL, NULL, NULL))
        printf("cgroup is mounted\n");

// check /tmp is mounted
if (is_mounted("tmpfs", "/tmp", NULL, NULL))
        printf("/tmp is mounted\n");

// check cgroup is mounted as cgroup2
if (is_mounted("cgroup", "/sys/fs/cgroup", "cgroup2", NULL))
        printf("cgroup is mounted as cgroup2\n");
 * \endcode
 *
 * @param fsname find matched mount filesystem name
 * @param dir find matched mount dir(path) name
 * @param type find matched mount type name
 * @param opts find matched mount option name
 *
 * @return true if matched mount entry found, otherwise false.
 */
bool mnt_is_mounted(const char *fsname, const char *dir, const char *type, const char *opts);
/**
 * @}
 */

/**
 * @defgroup EXEC_GROUP exec group
 *
 * @brief fork() and exec() utility
 * @{
 */

/**
 * @brief Traditional fork() and exec() helper.
 *
 * @param argv array of pointers to null-terminated strings that
 * represent the argument list available to the new program. The first
 * argument should point to the filename associated with the file
 * being executed. The array of pointers must be terminated by a NULL pointer.
 * @param envp specify the environment of the executed program via the
 * argument envp. The envp argument is an array of pointers to
 * null-terminated strings and must be terminated by a NULL pointer.
 * @param timeout_msec timeout millisecond to prevent infinite
 * waiting. If negative is given, the parent will not wait the
 * child. In other word, the parent will return immediately. If 0 is
 * given, parent will wait the child infinitly. And if positive value
 * is given parent will wait given milliseconds and expired return
 * -1. If the child is exit within the tiemout millisecond return with
 * child exit code.
 *
 * @return exit code of child. It is fully depend on the child
 * process. If the child exit with 1 then this function also return 1.
 * Negative errno on error. -ETIME on timer expired.
 */
int do_fork_exec(char *const argv[], char * const envp[], int64_t timeout_msec);

/**
 * @}
 */

/**
 * @defgroup TIME_UTIL_GROUP time util group
 *
 * @brief time utility libraries
 * @{
 */

/** millisecond per second */
#define MSEC_PER_SEC            1000ULL
/** microsecond per second */
#define USEC_PER_SEC            ((uint64_t) 1000000ULL)
/** microsecond per millisecond */
#define USEC_PER_MSEC           ((uint64_t) 1000ULL)
/** nanosecond per second */
#define NSEC_PER_SEC            ((uint64_t) 1000000000ULL)
/** nanosecond per microsecond */
#define NSEC_PER_MSEC           ((uint64_t) 1000000ULL)
/** nanosecond per microsecond */
#define NSEC_PER_USEC           ((uint64_t) 1000ULL)

/** microsecond per minute */
#define USEC_PER_MINUTE         ((uint64_t) (60ULL*USEC_PER_SEC))
/** nanosecond per minute */
#define NSEC_PER_MINUTE         ((uint64_t) (60ULL*NSEC_PER_SEC))
/** microsecond per hour */
#define USEC_PER_HOUR           ((uint64_t) (60ULL*USEC_PER_MINUTE))
/** nanosecond per hour */
#define NSEC_PER_HOUR           ((uint64_t) (60ULL*NSEC_PER_MINUTE))
/** microsecond per day */
#define USEC_PER_DAY            ((uint64_t) (24ULL*USEC_PER_HOUR))
/** nanosecond per day */
#define NSEC_PER_DAY            ((uint64_t) (24ULL*NSEC_PER_HOUR))
/** microsecond per week */
#define USEC_PER_WEEK           ((uint64_t) (7ULL*USEC_PER_DAY))
/** nanosecond per week */
#define NSEC_PER_WEEK           ((uint64_t) (7ULL*NSEC_PER_DAY))
/** microsecond per month */
#define USEC_PER_MONTH          ((uint64_t) (2629800ULL*USEC_PER_SEC))
/** nanosecond per month */
#define NSEC_PER_MONTH          ((uint64_t) (2629800ULL*NSEC_PER_SEC))
/** microsecond per year */
#define USEC_PER_YEAR           ((uint64_t) (31557600ULL*USEC_PER_SEC))
/** nanosecond per year */
#define NSEC_PER_YEAR           ((uint64_t) (31557600ULL*NSEC_PER_SEC))

/** frequently used time format string: 12:34 */
#define HH_MM                           "%H:%M"
/** frequently used time format string: 12:34:56 */
#define HH_MM_SS                        "%H:%M:%S"

/** frequently used time format string: 2015-01-23 */
#define YYYY_MM_DD                      "%Y-%m-%d"
/** frequently used time format string: 2015-01-23 12:34 */
#define YYYY_MM_DD_HH_MM                "%Y-%m-%d %H:%M"
/** frequently used time format string: 2015-01-23 12:34:56 */
#define YYYY_MM_DD_HH_MM_SS             "%Y-%m-%d %H:%M:%S"
/** frequently used time format string: 2015-01-23 12:34:56 KST */
#define YYYY_MM_DD_HH_MM_SS_Z           "%Y-%m-%d %H:%M:%S %Z"

/** frequently used time format string: Fri 2015-01-23 */
#define DOW_YYYY_MM_DD                  "%a %Y-%m-%d"
/** frequently used time format string: Fri 2015-01-23 12:34 */
#define DOW_YYYY_MM_DD_HH_MM            "%a %Y-%m-%d %H:%M"
/** frequently used time format string: Fri 2015-01-23 12:34:56 */
#define DOW_YYYY_MM_DD_HH_MM_SS         "%a %Y-%m-%d %H:%M:%S"
/** frequently used time format string: Fri 2015-01-23 12:34:56 KST */
#define DOW_YYYY_MM_DD_HH_MM_SS_Z       "%a %Y-%m-%d %H:%M:%S %Z"

/**
 * @brief Convert time_t to given format time string.
 *
 * @param sec time second to convert
 * @param format format string
 * @param time string pointer to converted time is filled. On
 * successful return, this value has to be free-ed by caller.
 *
 * @return 0 on success, -errno on failure.
 */
int sec_to_timestr(time_t sec, const char *format, char **time);

/**
 * @brief Convert time_t to \%a \%Y-\%m-\%d \%H:\%M:\%S \%Z format time string.
 *
 * @param sec time second to convert
 * @param time string pointer to converted time is filled. On
 * successful return, this value has to be free-ed by caller.
 *
 * @return 0 on success, -errno on failure.
 */
int sec_to_timestr_full(time_t sec, char **time);

/**
 * @brief Convert given format time string to time_t.
 *
 * @param format format string
 * @param time time string to convert to time_t
 * @param sec converted time_t
 *
 * @return 0 on success, -errno on failure.
 */
int timestr_to_sec(const char *format, const char *time, time_t *sec);

/**
 * @brief Make struct timeval from millisecond
 *
 * @param msec millisecond to Convert
 * @param tv struct timeval to be filled
 */
void msec_to_timeval(uint64_t msec, struct timeval *tv);

/**
 * @}
 */

#ifdef __cplusplus
}
#endif