diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk3sf.ctr |
Initial commit
Diffstat (limited to 'support/dktools/dk3sf.ctr')
-rw-r--r-- | support/dktools/dk3sf.ctr | 4689 |
1 files changed, 4689 insertions, 0 deletions
diff --git a/support/dktools/dk3sf.ctr b/support/dktools/dk3sf.ctr new file mode 100644 index 0000000000..b12b4621cd --- /dev/null +++ b/support/dktools/dk3sf.ctr @@ -0,0 +1,4689 @@ +%% options + +copyright owner = Dirk Krause +copyright year = 2011-xxxx +license = bsd + + + +%% header + +#include "dk3conf.h" +#include "dk3types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if DK3_ON_WINDOWS + +/** Retrieve information about a file. + @param st File information buffer. + @param fn File name. + @param app Application structure, used for diagnostics. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c16_stat_app(dk3_stat_t *st, dk3_c16_t const *fn, dk3_app_t *app); + +/** Open a file. + @param fn File name. + @param mo Mode. + @param app Application structure, used for diagnostics. + @return FILE pointer on success, NULL on error. +*/ +FILE * +dk3sf_c16_fopen_app(dk3_c16_t const *fn, dk3_c16_t const *mo, dk3_app_t *app); + +/** Convert timestamp to text. + @param dest Destination buffer. + @param sz Size of \a dest (number of characters). + @param timer Timestamp to convert. + @param app Application structure, used for diagnostics. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c16_time_convert_app( + dk3_c16_t *dest, size_t sz, dk3_time_t const *timer, dk3_app_t *app +); + +/** Get current working directory. + @param dest Destination buffer. + @param sz Size of \a dest. + The size must not exceed INT_MAX/2. + Practically this is not a limitation + as the useful buffer size is DK3_MAX_PATH elements. + @param app Application structure, used for diagnostics. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c16_getcwd_app(dk3_c16_t *dest, size_t sz, dk3_app_t *app); + +/** Find executable file. + @param d Destination buffer. + @param s Size of \a d (number of characters). + The size must not exceed 2^31-1. Practically this is not a + limitation as the useful buffer size is DK3_MAX_PATH elements. + @param w Current working directory. + @param c Command as typed in the command line. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c16_find_exec_app( + dk3_c16_t *d, size_t s, dk3_c16_t const *w, dk3_c16_t const *c, dk3_app_t *app +); + +/** Find users home directory. + @param d Destination buffer. + @param s Size of \a d (number of characters). + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c16_get_home_app(dk3_c16_t *d, size_t s, dk3_app_t *app); + + +/** Remove (unlink) path. + @param n Path name. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c16_remove_file_app(dk3_c16_t const *n, dk3_app_t *app); + + +/** Remove directory. + @param n Directory name. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c16_remove_dir_app(dk3_c16_t const *n, dk3_app_t *app); + +/** Retrieve host name (short name, without DNS domain). + @param db Destination buffer. + @param sz Size of \a db (number of characters). + The size must not exceed INT_MAX. Practically this is not a + limitation as I have never seen host names longer than 80 characters. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c16_get_hostname_app(dk3_c16_t *db, size_t sz, dk3_app_t *app); + +/** Get login name. + @param d Destination buffer. + @param s Size of \a d (number of characters). + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c16_get_logname_app(dk3_c16_t *d, size_t s, dk3_app_t *app); + + +/** Create directory if it does not yet exist. + @param p Path name. + @param mo Creation mode. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c16_mkdir_app(dk3_c16_t const *p, int mo, dk3_app_t *app);; + +/** Get environment variable. + @param name Environment variable name. + @return Value on success, NULL on error. +*/ +dk3_c16_t * +dk3sf_c16_getenv(dk3_c16_t const *name); + +#else + + +#endif + +/** Retrieve information about a file. + @param st File information buffer. + @param fn File name. + @param app Application structure, used for diagnostics. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c8_stat_app(dk3_stat_t *st, char const *fn, dk3_app_t *app); + +/** Open a file. + @param fn File name. + @param mo Mode. + @param app Application structure, used for diagnostics. + @return FILE pointer on success, NULL on error. +*/ +FILE * +dk3sf_c8_fopen_app(char const *fn, char const *mo, dk3_app_t *app); + +/** Convert timestamp to text. + @param dest Destination buffer. + @param sz Size of \a dest (number of characters). + @param timer Timestamp to convert. + @param app Application structure, used for diagnostics. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c8_time_convert_app( + char *dest, size_t sz, dk3_time_t const *timer, dk3_app_t *app +); + +/** Get current working directory. + @param dest Destination buffer. + @param sz Size of \a dest. + On some platforms the size is converted to int, so it + should not exceed 32767. Practically this is not a limitation + as the userful buffer size is DK3_MAX_PATH. + @param app Application structure, used for diagnostics. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c8_getcwd_app(char *dest, size_t sz, dk3_app_t *app); + +/** Read input line. + @param db Destination buffer. + @param sz Size of \a db (number of characters). + @param fi Input file. + @return 1 on success, 0 on error. +*/ +int +dk3sf_fgets(dkChar *db, size_t sz, FILE *fi); + +/** Read input line. + @param db Destination buffer. + @param sz Size of \a db (number of characters). + The size must not exceed 32767 as it is converted to int on some + systems. + @param fi Input file. + @param fn Input file name, may be NULL. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_fgets_fn_app( + dkChar *db, size_t sz, FILE *fi, dkChar const *fn, dk3_app_t *app +); + +/** Write string to file. + @param st String to write. + @param fi File to write to. + @return 1 on success, 0 on error. +*/ +int +dk3sf_fputs(dkChar const *st, FILE *fi); + +/** Write string to file, report errors if any. + @param st String to write. + @param fi Output file to write to. + @param fn File name for error messages, may be NULL. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_fputs_fn_app(dkChar const *st,FILE *fi,dkChar const *fn,dk3_app_t *app); + +/** Write array of line strings to file. + @param txt Pointer to array of lines. + @param fi Output file to write to. + @return 1 on success, 0 on error. +*/ +int +dk3sf_fputt(dkChar const * const *txt, FILE *fi); + +/** Write one character to file. + @param ch Character to write. + @param fi File to write to. + @return 1 on success, 0 on error. +*/ +int +dk3sf_fputc(dkChar ch, FILE *fi); + +/** Write one character to file. + @param ch Character to write. + @param fi File to write to. + @param fn File name of output file. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_fputc_fn_app(dkChar ch, FILE *fi, dkChar const *fn, dk3_app_t *app); + +/** Write byte order marker 0xFEFF to standard output. +*/ +void +dk3sf_initialize_stdout(void); + +/** Only set stdout mode, do not write byte order marker + 0xFEFF to standard output. +*/ +void +dk3sf_initialize_stdout_no_bom(void); + +/** Write byte order marker 0xFEFF to standard error output. +*/ +void +dk3sf_initialize_stderr(void); + +/** Write byte order marker 0xFEFF to file. + @param fipo File to set up. +*/ +void +dk3sf_initialize_file(FILE *fipo); + +/** Prepare standard output and standard error output for multibyte + characters (write byte order marker 0xFEFF). +*/ +void +dk3sf_initialize_output(void); + +/** Get current timestamp. + @param timer Pointer to result variable. + @return 1 on success, 0 on error. +*/ +int +dk3sf_time(dk3_time_t *timer); + +/** Find executable file. + @param d Destination buffer. + @param s Size of \a d (number of characters). + The size should not exceed 2^32-1 as it is converted to + a DWORD. Practically this is not a restriction as DK3_MAX_PATH + is the useful buffer size. + @param w Current working directory. + @param c Command as typed in the command line. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c8_find_exec_app( + char *d, size_t s, char const *w, char const *c, dk3_app_t *app +); + +/** Find users home directory. + @param d Destination buffer. + @param s Size of \a d (number of characters). + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c8_get_home_app(char *d, size_t s, dk3_app_t *app); + +/** Get current users login name. + @param d Destination buffer. + @param s Size of \a d (number of characters). + @param app Application structure for diagnostics, may be NULL. +*/ +int +dk3sf_c8_get_logname_app(char *d, size_t s, dk3_app_t *app); + +/** Create directory if it does not yet exist. + @param p Path name. + @param mo Creation mode. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c8_mkdir_app(char const *p, int mo, dk3_app_t *app); + +/** Remove (unlink) path. + @param n Path name. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c8_remove_file_app(char const *n, dk3_app_t *app); + +/** Remove directory. + @param n Directory name. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c8_remove_dir_app(char const *n, dk3_app_t *app); + +/** Get current process ID. + @return Process ID. +*/ +dk3_um_t +dk3sf_getpid(void); + +/** Check whether we must expand a file name. + @param fn File name to check. + @return 1 for "must expand", 0 for "no need to expand". +*/ +int +dk3sf_must_expand(dkChar const *fn); + +/** Retrieve host name (short name). + @param db Destination buffer. + @param sz Size of \a db (number of characters). + The size must not exceed 2^32-1. Practically this is not a + limitation as the useful buffer size for host name is below 256. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c8_get_hostname_app(char *db, size_t sz, dk3_app_t *app); + +/** Print 8-bit character to file, convert to 16 bit if necessary. + @param c Character to print. + @param f File to write to. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c8_fputc(char c, FILE *f); + +/** Print 8-bit character string to file, convert to 16 bit if necessary. + @param s String to print. + @param f File to write to. + @return 1 on success, 0 on error. +*/ +int +dk3sf_c8_fputs(char const *s, FILE *f); + +/** Read bytes from file descriptor into buffer. + @param fd File descriptor. + @param buf Buffer. + @param s Size of \a buf. + The size must not exceed 65535 as it is converted to unsigned int + on some systems. + @param app Application structure for diagnostics, may be NULL. + @return Number of bytes read. +*/ +size_t +dk3sf_read_app(int fd, void *buf, size_t s, dk3_app_t *app); + +/** Write bytes to file descriptor. + @param fd File descriptor. + @param buf Buffer to write. + @param s Size of \a buf in bytes. + The size must not exceed 65535 as it is converted to unsigned int + on some systems. + @param app Application structure for diagnostics, may be NULL. + @return 1 for success (all bytes written), 0 on error. +*/ +int +dk3sf_write_app(int fd, char const *buf, size_t s, dk3_app_t *app); + +/** Read from file. + @param db Destination buffer. + @param sz Size of one element. + @param ne Number of elements. + @param fi File to read from. + @param app Application structure for diagnostics, may be NULL. + @return Number of elements read. +*/ +size_t +dk3sf_fread_app(void *db, size_t sz, size_t ne, FILE *fi, dk3_app_t *app); + +/** Write to file. + @param sb Source buffer. + @param sz Size of one element. + @param ne Number of elements. + @param fi File to write to. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success (all elements written), 0 on error. +*/ +int +dk3sf_fwrite_app(void const *sb,size_t sz,size_t ne,FILE *fi,dk3_app_t *app); + +/** Inspect file, search for byte order marker. + The function inspects the first 4 bytes from file and attempts + to find the file encoding (DK3_FILE_ENCODING_xxx). + If there is no BOM at the beginning of the file the default + value \a dv is returned. A value for \a dv can be obtained + from dk3app_get_output_encoding() or by inspecting the DK3_CHAR_SIZE + value and the language setting (ending on "UTF-8" or "utf8"?). + @param fn File name. + @param dv Default value for file encoding. + @param app Application structure for diagnostics, may be NULL. + @return File encoding if BOM found, default value \a dv otherwise. +*/ +int +dk3sf_inspect_bom_app(dkChar const *fn, int dv, dk3_app_t *app); + +/** Inspect file, search for byte order marker. If byte order marker + is found save number of bytes to skip at beginning of file + to variable. + The function inspects the first 4 bytes from file and attempts + to find the file encoding (DK3_FILE_ENCODING_xxx). + If there is no BOM at the beginning of the file the default + value \a dv is returned. A value for \a dv can be obtained + from dk3app_get_output_encoding() or by inspecting the DK3_CHAR_SIZE + value and the language setting (ending on "UTF-8" or "utf8"?). + @param fn File name. + @param dv Default value for file encoding. + @param skb Pointer to size_t variable for number of bytes + to skip at the beginning of the file. + @param app Application structure for diagnostics, may be NULL. + @return File encoding if BOM found, default value \a dv otherwise. +*/ +int +dk3sf_inspect_bom_skip_app( + dkChar const *fn, + int dv, + size_t *skb, + dk3_app_t *app +); + +/** Attempt to apply an encoding found from BOM to an input FILE. + This function has an effect on Windows systems only. + For \a enc we can handle DK3_FILE_ENCODING_ASCII (mapped to + _O_TEXT), DK3_FILE_ENCODING_UTF8 (mapped to _O_U8TEXT) and + DK3_FILE_ENCODING_UTF16_LSB (mapped to _O_U16TEXT). + @param fipo File pointer. + @param enc Encoding found from dk3sf_inspect_bom_app(). + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_apply_bom_to_file_app(FILE *fipo, int enc, dk3_app_t *app); + +/** Get environment variable. + @param name Environment variable name. + @return Value on success, NULL on error. +*/ +char * +dk3sf_c8_getenv(char const *name); + +/** Check whether or not the given file name is a directory. + @param n File name. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success (is directory), 0 on error. +*/ +int +dk3sf_is_dir_app(dkChar const *n, dk3_app_t *app); + +/** Change into directory. + * @param dn Directory name. + * @param app Application structure for diagnostics, may be NULL. + * @return 1 on success, 0 on error. + */ +int +dk3sf_chdir_app(dkChar const *dn, dk3_app_t *app); + +/** Check whether we need to re-build a destination file from a source. + * @param dn Destination file name. + * @param sn Source file name. + * @return 1 for rebuild necessary, 0 for not necessary. + */ +int +dk3sf_must_rebuild(dkChar const *dn, dkChar const *sn); + +/** Create 8-bit file name from dkChar file name. + @param fnb File name buffer for result. + @param szfnb Size of @a fnb (number of bytes). + @param src Source file name. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_filename_to_c8( + char *fnb, size_t szfnb, dkChar const *src, dk3_app_t *app +); + +/** Retrieve a double value in POSIX notation from a string. + The sscanf() function depends on the current locale setting. + This function retrieves and saves the current locale setting, + establishes C locale temporarily for the the sscanf() call and + restores the original setting before exiting. + @param txt Text to inspect. + @param v Pointer to result variable. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_scan_double_app(dkChar const *txt, double *v, dk3_app_t *app); + +/** Convert timestamp to human readable date and time. + @param dest Destination structure. + @param timer Source timestamp. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_localtime_app(dk3_tm_t *dest, dk3_time_t *timer, dk3_app_t *app); + +/** Retrieve maximum number of open files. + @return Maximum number of open files. +*/ +int +dk3sf_get_max_files(void); + +/** Report error detailes. + @param app Application structure for diagnostics. + @param err Error code from errno. + @param fctn Function name. +*/ +void +dk3sf_report_errno(dk3_app_t *app, int err, dkChar const *fctn); + +/** Close a file. + @param fipo FILE to close. + @param fn File name, may be NULL. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_fclose_fn_app(FILE *fipo, dkChar const *fn, dk3_app_t *app); + +/** Close a file. + @param fipo FILE to close. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_fclose_app(FILE *fipo, dk3_app_t *app); + +/** Retrieve information about a file. + @param st File information buffer. + @param fn File name. + @param app Application structure, used for diagnostics. + @return 1 on success, 0 on error. +*/ +int +dk3sf_stat_app(dk3_stat_t *st, dkChar const *fn, dk3_app_t *app); + +/** Open a file. + @param fn File name. + @param mo Mode. + @param app Application structure, used for diagnostics. + @return FILE pointer on success, NULL on error. +*/ +FILE * +dk3sf_fopen_app(dkChar const *fn, dkChar const *mo, dk3_app_t *app); + +/** Convert timestamp to text. + @param dest Destination buffer. + @param sz Size of \a dest (number of dkChar). + @param timer Timestamp to convert. + @param app Application structure, used for diagnostics. + @return 1 on success, 0 on error. +*/ +int +dk3sf_time_convert_app( + dkChar *dest, + size_t sz, + dk3_time_t const *timer, + dk3_app_t *app +); + +/** Get current working directory. + @param dest Destination buffer. + @param sz Size of \a dest (number of dkChar). + The size must not exceed INT_MAX/2. Practically this is not a + limitation as the useful buffer size is DK3_MAX_PATH elements. + @param app Application structure, used for diagnostics. + @return 1 on success, 0 on error. +*/ +int +dk3sf_getcwd_app(dkChar *dest, size_t sz, dk3_app_t *app); + +/** Find executable file. + @param d Destination buffer. + @param s Size of \a d (number of dkChar). + The size must not exceed 2^31-1. Practically this is not a + limitation as the useful buffer size is DK3_MAX_PATH elements. + @param w Current working directory. + @param c Command as typed in the command line. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_find_exec_app( + dkChar *d, + size_t s, + dkChar const *w, + dkChar const *c, + dk3_app_t *app +); + +/** Get login name. + @param d Destination buffer. + @param s Size of \a d (number of dkChar). + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_get_logname_app(dkChar *d, size_t s, dk3_app_t *app); + +/** Find users home directory. + @param d Destination buffer. + @param s Size of \a d (number of dkChar). + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_get_home_app(dkChar *d, size_t s, dk3_app_t *app); + +/** Create directory if it does not yet exist. + @param p Path name. + @param mo Creation mode. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_mkdir_app(dkChar const *p, int mo, dk3_app_t *app); + +/** Remove (unlink) path. + @param n Path name. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_remove_file_app(dkChar const *n, dk3_app_t *app); + +/** Remove directory. + @param n Directory name. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_remove_dir_app(dkChar const *n, dk3_app_t *app); + +/** Retrieve host name (short name, without DNS domain). + @param db Destination buffer. + @param sz Size of \a db (number of dkChar). + The size must not exceed 2^31-1. Practically this is not a + limitation as I have never seen host names longer than 80 characters. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +int +dk3sf_get_hostname_app(dkChar *db, size_t sz, dk3_app_t *app); + +/** Get environment variable. + @param name Environment variable name. + @return Value on success, NULL on error. +*/ +dkChar * +dk3sf_getenv(dkChar const *name); + +#ifdef __cplusplus +} +#endif + + + +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "No functions to support large characters!" +#else +#if DK3_ON_WINDOWS + +/** Macro to choose correct character size for sscanf()/swscanf(). +*/ +#define dk3sf_sscanf3(s,f,d) swscanf(s,f,d) + +/** Macro to choose correct character size for sprintf()/swprintf(). + NOTE: The first argument must be a *buffer*, *not* a pointer. +*/ +#define dk3sf_sprintf3(s,f,d) swprintf(s,(sizeof(s)/sizeof(wchar_t)),f,d) +#else +#error "16 bit characters are supported on Windows platforms only!" +#endif +#endif +#else + + +/** Macro to choose correct character size for sscanf(). +*/ +#define dk3sf_sscanf3(s,f,d) sscanf(s,f,d) + +/** Macro to choose correct character size for sprintf(). + NOTE: The first argument *must* be a buffer, *not* a pointer. +*/ +#define dk3sf_sprintf3(s,f,d) sprintf(s,f,d) + +#endif + + + +%% module + +#include "dk3all.h" + + + +$(trace-include) + + + +#if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH + +/** File path component separator. +*/ +#define DK3_C8_SEP '\\' + +/** Not a file path component separator. +*/ +#define DK3_C8_NOSEP '/' + +#else + +/** File path component separator. +*/ +#define DK3_C8_SEP '/' + +/** Not a file path component separator. +*/ +#define DK3_C8_NOSEP '\\' + +#endif + + + +/** Add bit to set after testing another bit. +*/ +#define DK3SF_ADDIF(a,b) if(m & a) { back |= b; } + + + +/** Function names used in error messages. +*/ +dkChar const * const dk3sf_function_names[] = { +$!string-table macro=dkT +# +# 0 +# + +# +# 1 +# +fclose: +# +# 2 +# +rmdir: +# +# 3 +# +unlink: +# +# 4 +# +getpwuid: +# +# 5 +# +lstat64: +# +# 6 +# +stat64: +# +# 7 +# +stat: +# +# 8 +# +lstat: +# +# 9 +# +fopen: +# +# 10 +# +localtime_r: +# +# 11 +# +getcwd: +# +# 12 +# +mkdir: +# +# 13 +# +gethostname: +# +# 14 +# +read: +# +# 15 +# +_read: +# +# 16 +# +write: +# +# 17 +# +_write: +# +# 18 +# +fread: +# +# 19 +# +_fread: +# +# 20 +# +fwrite: +# +# 21 +# +_fwrite: +# +# 22 +# +chdir: +# +# 23 +# +fputs: +# +# 24 +# +fputc: +# +# 25 +# +fgets: +$!end +}; + + + +void +dk3sf_report_errno(dk3_app_t *app, int err, dkChar const *fctn) +{ +#if (DK3_CHAR_SIZE == 1) && DK3_HAVE_STRERROR && (!DK3_ON_WINDOWS) + dkChar const *msgarray[2]; +#if DK3_HAVE_GETENV && DK3_HAVE_SETLOCALE + char const *oldlocale = NULL; + char const *langptr = NULL; +#endif + if((app) && (fctn)) { + msgarray[0] = fctn; + errno = 0; +#if DK3_HAVE_GETENV && DK3_HAVE_SETLOCALE + langptr = getenv("LANG"); + if(langptr) { + oldlocale = setlocale(LC_MESSAGES, langptr); + } +#endif + msgarray[1] = strerror(err); + if(0 == errno) { + dk3app_log_3(app, DK3_LL_ERROR, msgarray, 0, 1, dk3sf_function_names[0]); + } +#if DK3_HAVE_GETENV && DK3_HAVE_SETLOCALE + if(langptr) { + if(oldlocale) { setlocale(LC_MESSAGES, oldlocale); } + } +#endif + } +#endif +} + + + + +#if DK3_ON_WINDOWS +/* +++ Windows +++ */ + + + +/** Unlocalized 8-bit character keywords used by module. +*/ +static char const * const dk3sf_kw_win_c8[] = { +/* 0 */ "HOMEDRIVE", +/* 1 */ "HOMEPATH", +/* 2 */ "USERPROFILE", +/* 3 */ "LOCALAPPDATA", +/* 4 */ "\\AppData\\Local", +/* 5 */ "APPDATA", +/* 6 */ "\\AppData\\Roaming", +/* 7 */ "TEMP", +/* 8 */ "TMP", +/* 9 */ "\\AppData\\Local\\Temp", +NULL +}; + + + +/** Unlocalized 16-bit character keywords used by module. +*/ +static wchar_t const * const dk3sf_kw_win_c16[] = { +/* 0 */ L"HOMEDRIVE", +/* 1 */ L"HOMEPATH", +/* 2 */ L"USERPROFILE", +/* 3 */ L"LOCALAPPDATA", +/* 4 */ L"\\AppData\\Local", +/* 5 */ L"APPDATA", +/* 6 */ L"\\AppData\\Roaming", +/* 7 */ L"TEMP", +/* 8 */ L"TMP", +/* 9 */ L"\\AppData\\Local\\Temp", +NULL +}; + + + +dk3_um_t +dk3sf_getpid(void) +{ + dk3_um_t back; + back = (dk3_um_t)_getpid(); + return back; +} + + + +dk3_c16_t * +dk3sf_c16_getenv(dk3_c16_t const *name) +{ + dk3_c16_t *back = NULL; + if(name) { + back = _wgetenv(name); + } + return back; +} + + +dk3_c8_t * +dk3sf_c8_getenv(char const *name) +{ + char *back = NULL; + if(name) { + back = getenv(name); + } + return back; +} + + +int +dk3sf_c16_remove_dir_app(dk3_c16_t const *n, dk3_app_t *app) +{ + int back = 0; + if(n) { + if(_wrmdir(n) == 0) { + back = 1; + } else { + if(app) { + /* Failed to remove directory! */ +#if DK3_CHAR_SIZE == 2 + dk3app_log_i3(app, DK3_LL_ERROR, 69, 70, n); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 68); +#endif + } + } + } + return back; +} + + + +int +dk3sf_c8_remove_dir_app(char const *n, dk3_app_t *app) +{ + int back = 0; + if(n) { + if(_rmdir(n) == 0) { + back = 1; + } else { + if(app) { + /* Failed to remove directory! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 69, 70, n); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 68); +#endif + } + } + } + return back; +} + + +int +dk3sf_c16_remove_file_app(dk3_c16_t const *n, dk3_app_t *app) +{ + int back = 0; + if(n) { + if(_wunlink(n) == 0) { + back = 1; + } else { + if(app) { + /* Failed to remove file! */ +#if DK3_CHAR_SIZE == 2 + dk3app_log_i3(app, DK3_LL_ERROR, 88, 89, n); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 90); +#endif + } + } + } + return back; +} + + +int +dk3sf_c8_remove_file_app(char const *n, dk3_app_t *app) +{ + int back = 0; + if(n) { + if(_unlink(n) == 0) { + back = 1; + } else { + if(app) { + /* ERROR: Failed to remove file! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 88, 89, n); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 90); +#endif + } + } + } + return back; +} + + +/** Attempt to retrieve home directory name. + @param d Destination buffer. + @param sz Size of \a d (number of characters). + @param n1 Name of first environment variable to check. + @param n2 Name of second environment variable to check. + @param n3 Trailing string to remove if found. + @return 1 on success, 0 on error. +*/ +static +int +dk3sf_c8_attempt_home( + char *d, size_t sz, char const *n1, char const *n2, char const *n3 +) +{ + int back = 0; + char *p1 = NULL; /* Value of first environment variable. */ + char *p2 = NULL; /* Value of second environment variable. */ + size_t s = 0; /* Buffer size needed. */ + size_t s2 = 0; /* Size of trailing part to remove. */ + p2 = NULL; + $? "+ dk3sf_c8_attempt_home \"%!8s\" \"%!8s\" \"%!8s\"", TR_8STR(n1), TR_8STR(n2), TR_8STR(n3) + p1 = getenv(n1); + if(p1) { + if(n2) { p2 = getenv(n2); } + if((p2) || (!(n2))) { + s = dk3str_c8_len(p1); + if(p2) { s += dk3str_c8_len(p2); } + if(s < sz) { + dk3str_c8_cpy_not_overlapped(d, p1); + if(p2) { dk3str_c8_cat(d, p2); } + if(n3) { + s2 = dk3str_c8_len(n3); + if(s2 < 2) { + if(dk3str_c8_casecmp(&(d[s - s2]), n3) == 0) { + d[s - s2] = '\0'; + back = 1; + } + } + } else { + back = 1; + } + } + } + $!trace-code if(back) { + $? ". home = \"%!8s\"", d + $!trace-code } + } $? "- dk3sf_c8_attempt_home %d", back + return back; +} + + +int +dk3sf_c8_get_home_app(char *d, size_t s, dk3_app_t *app) +{ + int back = 0; + if((d) && (s)) { + back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[0], dk3sf_kw_win_c8[1], NULL); + if(!back) { + back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[2], NULL, NULL); + } + if(!back) { + back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[3], NULL, dk3sf_kw_win_c8[4]); + } + if(!back) { + back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[5], NULL, dk3sf_kw_win_c8[6]); + } + if(!back) { + back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[7], NULL, dk3sf_kw_win_c8[9]); + } + if(!back) { + back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[8], NULL, dk3sf_kw_win_c8[9]); + } + if(!back) { + back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[3], NULL, NULL); + } + if(!back) { + back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[5], NULL, NULL); + } + if(!back) { + back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[7], NULL, NULL); + } + if(!back) { + back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[8], NULL, NULL); + } + $!trace-code if(back) { + $? ". home = \"%!8s\"", d + $!trace-code } + } + return back; +} + + + +/** Attempt to retrieve home directory name. + @param d Destination buffer. + @param sz Size of \a d (number of characters). + @param n1 Name of first environment variable to check. + @param n2 Name of second environment variable to check. + @param n3 Trailing string to remove if found. + @return 1 on success, 0 on error. +*/ +static +int +dk3sf_c16_attempt_home( + dk3_c16_t *d, size_t sz, + dk3_c16_t const *n1, dk3_c16_t const *n2, dk3_c16_t const *n3 +) +{ + int back = 0; + dk3_c16_t *p1 = NULL; /* Value of first environment variable. */ + dk3_c16_t *p2 = NULL; /* Value of second environment variable. */ + size_t s = 0; /* Buffer size needed. */ + size_t s2 = 0; /* Size of trailing text to remove. */ + p2 = NULL; + $? "+ dk3sf_c8_attempt_home \"%ls\" \"%ls\" \"%ls\"", TR_LSTR(n1), TR_LSTR(n2), TR_LSTR(n3) + p1 = _wgetenv(n1); + if(p1) { + if(n2) { p2 = _wgetenv(n2); } + if((p2) || (!(n2))) { + s = dk3str_c16_len(p1); + if(p2) { s += dk3str_c16_len(p2); } + if(s < sz) { + dk3str_c16_cpy(d, p1); + if(p2) { dk3str_c16_cat(d, p2); } + if(n3) { + s2 = dk3str_c16_len(n3); + if(s2 < 2) { + if(dk3str_c16_casecmp(&(d[s - s2]), n3) == 0) { + d[s - s2] = 0x0000U; + back = 1; + } + } + } else { + back = 1; + } + } + } + $!trace-code if(back) { + $? ". home = \"%ls\"", d + $!trace-code } + } $? "- dk3sf_c8_attempt_home %d", back + return back; +} + + + +int +dk3sf_c16_get_home_app(dk3_c16_t *d, size_t s, dk3_app_t *app) +{ + int back = 0; + if((d) && (s)) { + back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[0], dk3sf_kw_win_c16[1], NULL); + if(!back) { + back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[2], NULL, NULL); + } + if(!back) { + back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[3], NULL, dk3sf_kw_win_c16[4]); + } + if(!back) { + back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[5], NULL, dk3sf_kw_win_c16[6]); + } + if(!back) { + back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[7], NULL, dk3sf_kw_win_c16[9]); + } + if(!back) { + back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[8], NULL, dk3sf_kw_win_c16[9]); + } + if(!back) { + back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[3], NULL, NULL); + } + if(!back) { + back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[5], NULL, NULL); + } + if(!back) { + back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[7], NULL, NULL); + } + if(!back) { + back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[8], NULL, NULL); + } + $!trace-code if(back) { + $? ". home = \"%ls\"", d + $!trace-code } + } + return back; +} + + +int +dk3sf_c8_get_logname_app(char *d, size_t s, dk3_app_t *app) +{ + int back = 0; + DWORD sz = 0; /* Buffer size / Result length. */ + sz = (DWORD)s; + if((d) && (s)) { + if(GetUserNameA(d, &sz)) { + if(sz) { + d[((size_t)sz < s) ? ((size_t)sz) : (s - 1)] = '\0'; + back = 1; + } + } else { + if(app) { + /* Failed to find current user name */ + dk3app_log_i1(app, DK3_LL_ERROR, 43); + } + } + } + return back; +} + + + +int +dk3sf_c16_get_logname_app(dk3_c16_t *d, size_t s, dk3_app_t *app) +{ + int back = 0; + DWORD sz = 0; /* Buffer size / result length. */ + if((d) && (s)) { + sz = (DWORD)s; + if(GetUserNameW(d, &sz)) { + if(sz) { + d[((size_t)sz < s) ? ((size_t)sz) : (s - 1)] = 0U; + back = 1; + } + } else { + if(app) { + /* Failed to find current user name */ + dk3app_log_i1(app, DK3_LL_ERROR, 43); + } + } + } + return back; +} + + +int +dk3sf_time(dk3_time_t *timer) +{ + int back = 1; + _time64(timer); + return back; +} + + + +static +int +dk3sf_convert_file_type(int m) +{ + int back = 0; + switch(m & _S_IFMT) { +#ifdef _S_IFIFO + case _S_IFIFO: back = DK3_FT_FIFO; break; +#endif +#ifdef _S_IFCHR + case _S_IFCHR: back = DK3_FT_SPECIAL_CHAR; break; +#endif +#ifdef _S_IFDIR + case _S_IFDIR: back = DK3_FT_DIRECTORY; break; +#endif +#ifdef _S_IFBLK + case _S_IFBLK: back = DK3_FT_SPECIAL_BLOCK; break; +#endif +#ifdef _S_IFREG + case _S_IFREG: back = DK3_FT_REGULAR; break; +#endif + } + return back; +} + + + +static +int +dk3sf_convert_file_permissions(int m) +{ + int back = 0; + DK3SF_ADDIF(_S_IREAD,DK3_FPERM_U_READ) + DK3SF_ADDIF(_S_IWRITE,DK3_FPERM_U_WRITE) + DK3SF_ADDIF(_S_IEXEC,DK3_FPERM_U_EXEC) + return back; +} + + + +/** Convert file permissions back from dktools to system values. + @param m File permissions in dktools notation. + @return File permissions in system notation. +*/ +static +int +dk3sf_convert_back_file_permissions(int m) +{ + int back = 0; + DK3SF_ADDIF(DK3_FPERM_U_READ,S_IREAD) + DK3SF_ADDIF(DK3_FPERM_U_WRITE,S_IWRITE) + DK3SF_ADDIF(DK3_FPERM_U_EXEC,S_IEXEC) + return back; +} + + + +static +void +dk3sf_convert_filetime(dk3_time_t *pd, FILETIME *ps) +{ + __int64 i1; + __int64 i2; + i1 = (__int64)(ps->dwHighDateTime); + i2 = (__int64)(ps->dwLowDateTime); + i1 = ((i1 << 32) & 0xFFFFFFFF00000000UL) | (i2 & 0x00000000FFFFFFFFUL); + *pd = (dk3_time_t)i1; +} + + + +int +dk3sf_c8_stat_app(dk3_stat_t *st, char const *fn, dk3_app_t *app) +{ + WIN32_FIND_DATAA wfd; + DWORD dwFileAttributes; + HANDLE hFFF; + int ec = 0; + int back = 0; + struct __stat64 stb; /* Internal buffer for _stat64(). */ + $? "+ dk3sf_c8_stat_app \"%!8s\"", fn + if((st) && (fn)) { + dk3mem_res((void *)st, sizeof(dk3_stat_t)); + st->cReparse = 0x00; + st->dwReparse = (DWORD)0; + if(_stat64(fn, &stb) == 0) { + back = 1; + st->u = (dk3_um_t)(stb.st_uid); + st->g = (dk3_um_t)(stb.st_gid); + st->device = (dk3_um_t)(stb.st_dev); + st->rdev = (dk3_um_t)(stb.st_rdev); + st->inode = (dk3_um_t)(stb.st_ino); + st->nlink = (dk3_um_t)(stb.st_nlink); + st->cre = (dk3_time_t)(stb.st_ctime); + st->mod = (dk3_time_t)(stb.st_mtime); + st->acc = (dk3_time_t)(stb.st_atime); + st->ft = dk3sf_convert_file_type(stb.st_mode); + st->perm = dk3sf_convert_file_permissions(stb.st_mode); + st->sz = (dk3_um_t)(stb.st_size); + st->lsz = st->sz; + st->ai = 0x00; + dk3mem_cpy((void *)(&(st->lcre)), (void *)(&(st->cre)), sizeof(dk3_time_t)); + dk3mem_cpy((void *)(&(st->lmod)), (void *)(&(st->mod)), sizeof(dk3_time_t)); + dk3mem_cpy((void *)(&(st->lacc)), (void *)(&(st->acc)), sizeof(dk3_time_t)); + st->lu = st->u; + st->lg = st->g; + st->ldevice = st->device; + st->lrdev = st->rdev; + st->linode = st->inode; + st->lnlink = st->nlink; + st->lft = st->ft; + st->lperm = st->perm; + st->lsz = st->sz; +#if VERSION_BEFORE_2012_04_14 + if(DK3_FT_DIRECTORY == st->ft) { + WIN32_FIND_DATAA wfdFileDetails; + HANDLE hFileSearch; + $? ". check directory" + hFileSearch = FindFirstFileA(fn, &wfdFileDetails); + if(INVALID_HANDLE_VALUE != hFileSearch) { + if(FILE_ATTRIBUTE_REPARSE_POINT & (wfdFileDetails.dwFileAttributes)) { + if(IO_REPARSE_TAG_MOUNT_POINT == wfdFileDetails.dwReserved0) { + /* ##### st->ft = DK3_FT_WINDOWS_MOUNT_POINT; */ + } else { + if(IO_REPARSE_TAG_SYMLINK == wfdFileDetails.dwReserved0) { + /* Symbolic link */ + st->lsz = dk3ma_um_add_ok( + dk3ma_um_mul_ok( + (dk3_um_t)(wfdFileDetails.nFileSizeHigh), + dk3ma_um_add_ok( + (dk3_um_t)(MAXDWORD), + DK3_UM_1, + &ec + ), + &ec + ), + (dk3_um_t)(wfdFileDetails.nFileSizeLow), + &ec + ); + dk3sf_convert_filetime(&(st->lcre), &(wfdFileDetails.ftCreationTime)); + dk3sf_convert_filetime(&(st->lmod), &(wfdFileDetails.ftLastWriteTime)); + dk3sf_convert_filetime(&(st->lacc), &(wfdFileDetails.ftLastAccessTime)); + st->ft |= DK3_FT_SYMLINK; + } else { + } + } + } + FindClose(hFileSearch); + } + } +#else + dwFileAttributes = GetFileAttributesA(fn); + if(INVALID_FILE_ATTRIBUTES != dwFileAttributes) { + if(dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + st->cReparse = 'r'; + hFFF = FindFirstFileA(fn, &wfd); + if(INVALID_HANDLE_VALUE != hFFF) { + if((wfd.dwFileAttributes) & FILE_ATTRIBUTE_REPARSE_POINT) { + st->dwReparse = wfd.dwReserved0; + switch(wfd.dwReserved0) { + case IO_REPARSE_TAG_MOUNT_POINT: { + st->cReparse = 'm'; + } break; + case IO_REPARSE_TAG_SYMLINK: { + st->cReparse = 'l'; + } break; + } + } + FindClose(hFFF); + } + } + } +#endif + } else { + if(app) { + /* stat() failed! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 61, 62, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 73); +#endif + } + } + } $? "- dk3sf_c8_stat_app %d", back + return back; +} + + + +/** Check whether opening a file is allowed. + @param fn File name. + @param want_to_write Flag: Write access is wanted. + @param app Application structure for diagnostics, may be NULL. + @return 1 for write allowed, 0 for write denied. +*/ +static +int +dk3sf_c8_check_open_file(char const *fn, int want_to_write, dk3_app_t *app) +{ + int back = 1; + dk3_stat_t stb; /* Internal buffer for checks. */ + if(dk3sf_c8_stat_app(&stb, fn, NULL)) { + if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) { + if(app) { + back = 0; + /* ERROR: Name refers a directory! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 74, 75, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 76); +#endif + } + } + if(want_to_write) { + /* Place for additional checks to write files here. */ + } + } + return back; +} + + + +FILE * +dk3sf_c8_fopen_app(char const *fn, char const *mo, dk3_app_t *app) +{ + FILE *back = NULL; + char const *moptr = NULL; /* Check mode string. */ + int want_to_write = 0; /* Flag: Write access wanted. */ + $? "+ dk3sf_c8_fopen_app \"%!8s\"", TR_8STR(fn) + if((fn) && (mo)) { + moptr = mo; + while(*moptr) { + switch(*moptr) { + case 'w': case 'a': case '+': { want_to_write = 1; } break; + } + moptr++; + } + if(dk3sf_c8_check_open_file(fn, want_to_write, app)) { + back = fopen(fn, mo); + if(!(back)) { + if(app) { + /* Failed to open file for writing! */ + if(want_to_write) { +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 77, 78, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 79); +#endif + } else { +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 143, 144, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 145); +#endif + } + } + } + } + } $? "- dk3sf_c8_fopen_app %!8s", TR_8PTR(back) + return back; +} + + + + +int +dk3sf_localtime_app( + dk3_tm_t *dest, + dk3_time_t *timer, + dk3_app_t *app +) +{ + int back = 0; + struct tm res; + if((dest) && (timer)) { + if(0 == _localtime64_s(&res, timer)) { + back = 1; + dest->Y = 1900 + res.tm_year; + dest->M = 1 + res.tm_mon; + dest->D = res.tm_mday; + dest->h = res.tm_hour; + dest->m = res.tm_min; + dest->s = res.tm_sec; + } else { + if(app) { + /* ERROR: _localtime64_s failed! */ + dk3app_log_i1(app, DK3_LL_ERROR, 268); + } + } + } + return back; +} + + + +int +dk3sf_c8_time_convert_app( + char *dest, size_t sz, dk3_time_t const *timer, dk3_app_t *app +) +{ + int back = 0; + char buffer[64]; /* Buffer for sprintf() result. */ + struct tm res; /* Result from localtime(). */ + if((dest) && (sz) && (timer)) { + if(0 == _localtime64_s(&res, timer)) { + sprintf( + buffer, + "%04d-%02d-%02d %02d:%02d:%02d", + (1900 + res.tm_year), + (1 + res.tm_mon), + res.tm_mday, + res.tm_hour, + res.tm_min, + res.tm_sec + ); + if(sz > dk3str_c8_len(buffer)) { + dk3str_c8_cpy_not_overlapped(dest, buffer); + back = 1; + } else { + if(app) { + /* Buffer too small! */ + dk3app_log_i1(app, DK3_LL_ERROR, 38); + } + } + } else { + if(app) { + /* _localtime64_s failed! */ + dk3app_log_i1(app, DK3_LL_ERROR, 80); + } + } + } + return back; +} + + + +int +dk3sf_c8_getcwd_app(char *dest, size_t sz, dk3_app_t *app) +{ + int back = 0; + if((dest) && (sz)) { + if(_getcwd(dest, (int)sz)) { + back = 1; + } else { + if(app) { + switch(errno) { + case ERANGE: { + /* Buffer too small! */ + dk3app_log_i1(app, DK3_LL_ERROR, 38); + } break; + default: { + dk3app_log_i1(app, DK3_LL_ERROR, 53); + } break; + } + } + } + } + return back; +} + + + +int +dk3sf_c8_find_exec_app( + char *d, size_t s, char const *w, char const *c, dk3_app_t *app +) +{ + int back = 0; + if((d) && (s)) { + if(GetModuleFileNameA(GetModuleHandle(NULL),d,(DWORD)s)) { + back = 1; + } else { + if(app) { + /* Failed to find name of executable! */ + dk3app_log_i1(app, DK3_LL_ERROR, 40); + } + } + } + return back; +} + + + +static +int +dk3sf_c8_is_drive(char const *p) +{ + int back = 0; + $? "+ dk3sf_c8_is_drive \"%!8s\"", TR_8STR(p) + if(dk3str_c8_len(p) == 2) { + if((*p >= 'a') && (*p <= 'z')) { + back = 1; + } + if((*p >= 'A') && (*p <= 'Z')) { + back = 1; + } + if(back) { + back = 0; + if(p[1] == ':') { back = 1; } + } + } $? "- dk3sf_c8_is_drive %d", back + return back; +} + + +int +dk3sf_c8_mkdir_app(char const *p, int mo, dk3_app_t *app) +{ + int back = 0; + char buffer[DK3_MAX_PATH]; /* Path name for parent directories. */ + char *ptr = NULL; /* Slash/backslash position. */ + int cc = 1; /* Flag: Can continue. */ + int m = 0; /* File permissions. */ + dk3_stat_t stb; + $? "+ dk3sf_c8_mkdir_app \"%!8s\"", TR_8STR(p) + if(p) { + m = dk3sf_convert_back_file_permissions(mo); + if(dk3str_c8_len(p) < sizeof(buffer)) { $? ". length ok" + dk3str_c8_cpy_not_overlapped(buffer, p); + ptr = buffer; cc = 1; + while((cc) && (ptr)) { $? ". loop ptr=\"%!8s\"", TR_8STR(ptr) + ptr = dk3str_c8_chr(ptr, '\\'); + if(ptr) { + *ptr = '\0'; $? ". directory=\"%!8s\"", buffer + if((dk3str_c8_len(buffer) > 0) && (!dk3sf_c8_is_drive(buffer))) { + if(dk3sf_c8_stat_app(&stb, buffer, NULL)) { $? ". path exists" + if(((stb.ft) & (~(DK3_FT_SYMLINK))) != DK3_FT_DIRECTORY) { + cc = 0; $? ". path \"%!8s\" no directory", buffer + if(app) { + /* Not a directory! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 83); +#endif + } + } + } else { $? ". must create directory \"%!8s\"", buffer + if(_mkdir(buffer) != 0) { $? "! failed to create \"%!8s\"", buffer + cc = 0; + if(app) { + /* Failed to create directory! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 86); +#endif + } + } + } + } + *ptr = '\\'; + ptr++; + } + } + if(cc) { $? ". all parents ok" + if(dk3sf_c8_stat_app(&stb, buffer, NULL)) { $? ". \"%!8s\" exists", buffer + if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) { + back = 1; $? ". is directory" + } else { $? ". \"%!8s\" is not a directory", buffer + if(app) { + /* Not a directory! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 83); +#endif + } + } + } else { $? ". must create \"%!8s\"", buffer + if(_mkdir(buffer) == 0) { + back = 1; + } else { $? "! failed to create \"%!8s\"", buffer +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 86); +#endif + } + } + } + } else { $? "! directory name too long" + if(app) { + /* Path too long! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, p); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 87); +#endif + } + } + } $? "- dk3sf_c8_mkdir_app %d", back + return back; +} + + + +int +dk3sf_c16_stat_app(dk3_stat_t *st, dk3_c16_t const *fn, dk3_app_t *app) +{ + WIN32_FIND_DATAW wfd; + DWORD dwFileAttributes; + HANDLE hFFF; + int ec = 0; + int back = 0; + struct __stat64 stb; /* Result from _wstat64(). */ + $? "+ dk3sf_c16_stat_app \"%ls\"", fn + if((st) && (fn)) { + dk3mem_res((void *)st, sizeof(dk3_stat_t)); + st->cReparse = 0x00; + st->dwReparse = (DWORD)0; + if(_wstat64(fn, &stb) == 0) { + back = 1; + st->u = (dk3_um_t)(stb.st_uid); + st->g = (dk3_um_t)(stb.st_gid); + st->device = (dk3_um_t)(stb.st_dev); + st->rdev = (dk3_um_t)(stb.st_rdev); + st->inode = (dk3_um_t)(stb.st_ino); + st->nlink = (dk3_um_t)(stb.st_nlink); + st->cre = (dk3_time_t)(stb.st_ctime); + st->mod = (dk3_time_t)(stb.st_mtime); + st->acc = (dk3_time_t)(stb.st_atime); + st->ft = dk3sf_convert_file_type(stb.st_mode); + st->perm = dk3sf_convert_file_permissions(stb.st_mode); + st->sz = (dk3_um_t)(stb.st_size); + st->lsz = st->sz; + st->ai = 0x00; + dk3mem_cpy((void *)(&(st->lcre)), (void *)(&(st->cre)), sizeof(dk3_time_t)); + dk3mem_cpy((void *)(&(st->lmod)), (void *)(&(st->mod)), sizeof(dk3_time_t)); + dk3mem_cpy((void *)(&(st->lacc)), (void *)(&(st->acc)), sizeof(dk3_time_t)); + st->lu = st->u; + st->lg = st->g; + st->ldevice = st->device; + st->lrdev = st->rdev; + st->linode = st->inode; + st->lnlink = st->nlink; + st->lft = st->ft; + st->lperm = st->perm; + st->lsz = st->sz; +#if VERSION_BEFORE_2012_04_14 + if(DK3_FT_DIRECTORY == st->ft) { + WIN32_FIND_DATAW wfdFileDetails; + HANDLE hFileSearch; + $? ". directory special check" + hFileSearch = FindFirstFileW(fn, &wfdFileDetails); + if(INVALID_HANDLE_VALUE != hFileSearch) { $? ". handle ok" + if(FILE_ATTRIBUTE_REPARSE_POINT & (wfdFileDetails.dwFileAttributes)) { + $? ". reparse point" + if(IO_REPARSE_TAG_MOUNT_POINT == wfdFileDetails.dwReserved0) { + $? ". mount point" + /* ##### st->ft = DK3_FT_WINDOWS_MOUNT_POINT; */ + } else { + if(IO_REPARSE_TAG_SYMLINK == wfdFileDetails.dwReserved0) { + $? ". symbolic link" + /* Symbolic link */ + st->lsz = dk3ma_um_add_ok( + dk3ma_um_mul_ok( + (dk3_um_t)(wfdFileDetails.nFileSizeHigh), + dk3ma_um_add_ok( + (dk3_um_t)(MAXDWORD), + DK3_UM_1, + &ec + ), + &ec + ), + (dk3_um_t)(wfdFileDetails.nFileSizeLow), + &ec + ); + dk3sf_convert_filetime(&(st->lcre), &(wfdFileDetails.ftCreationTime)); + dk3sf_convert_filetime(&(st->lmod), &(wfdFileDetails.ftLastWriteTime)); + dk3sf_convert_filetime(&(st->lacc), &(wfdFileDetails.ftLastAccessTime)); + st->ft |= DK3_FT_SYMLINK; + } else { + } + } + } + FindClose(hFileSearch); + } + } +#else + dwFileAttributes = GetFileAttributesW(fn); + if(INVALID_FILE_ATTRIBUTES != dwFileAttributes) { + if(dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + st->cReparse = 'r'; + hFFF = FindFirstFileW(fn, &wfd); + if(INVALID_HANDLE_VALUE != hFFF) { + if((wfd.dwFileAttributes) & FILE_ATTRIBUTE_REPARSE_POINT) { + st->dwReparse = wfd.dwReserved0; + switch(wfd.dwReserved0) { + case IO_REPARSE_TAG_MOUNT_POINT: { + st->cReparse = 'm'; + } break; + case IO_REPARSE_TAG_SYMLINK: { + st->cReparse = 'l'; + } break; + } + } + FindClose(hFFF); + } + } + } +#endif + } else { + if(app) { + /* _wstat64() failed! */ +#if DK3_CHAR_SIZE == 2 + dk3app_log_i3(app, DK3_LL_ERROR, 61, 163, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 73); +#endif + } + } + } $? "- dk3sf_c16_stat_app %d", back + return back; +} + + + +static +int +dk3sf_c16_check_open_file(dk3_c16_t const *fn, int want_to_write, dk3_app_t *app) +{ + int back = 1; + dk3_stat_t stb; /* Check for existing file. */ + if(dk3sf_c16_stat_app(&stb, fn, NULL)) { + if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) { + if(app) { + back = 0; + /* Name refers a directory! */ +#if DK3_CHAR_SIZE == 2 + dk3app_log_i3(app, DK3_LL_ERROR, 74, 75, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 76); +#endif + } + } + if(want_to_write) { + /* Place for additional checks to write files here. */ + } + } + return back; +} + + + +FILE * +dk3sf_c16_fopen_app(dk3_c16_t const *fn, dk3_c16_t const *mo, dk3_app_t *app) +{ + FILE *back = NULL; + dk3_c16_t const *moptr = NULL; /* Traverse mode string. */ + int want_to_write = 0; /* Flag: Write access wanted. */ + if((fn) && (mo)) { + moptr = mo; + while(*moptr) { + switch(*moptr) { + case L'w': case L'a': case L'+': { want_to_write = 1; } break; + } + moptr++; + } + if(dk3sf_c16_check_open_file(fn, want_to_write, app)) { + back = _wfopen(fn, mo); + if(!(back)) { + if(app) { + /* Failed to open file for writing! */ + if(want_to_write) { +#if DK3_CHAR_SIZE == 2 + dk3app_log_i3(app, DK3_LL_ERROR, 77, 78, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 79); +#endif + } else { +#if DK3_CHAR_SIZE == 2 + dk3app_log_i3(app, DK3_LL_ERROR, 143, 144, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 145); +#endif + } + } + } + } + } + return back; +} + + + +int +dk3sf_c16_time_convert_app( + dk3_c16_t *dest, size_t sz, dk3_time_t const *timer, dk3_app_t *app +) +{ + int back = 0; + char buffer[64]; + if(dk3sf_c8_time_convert_app(buffer, sizeof(buffer), timer, app)) { + back = dk3str_cnv_c8p_to_c16_app(dest, sz, buffer, app); + } + return back; +} + + + +int +dk3sf_c16_getcwd_app(dk3_c16_t *dest, size_t sz, dk3_app_t *app) +{ + int back = 0; + if((dest) && (sz)) { + if(_wgetcwd(dest, (int)sz)) { + back = 1; + } else { + if(app) { + switch(errno) { +#ifdef ERANGE + case ERANGE: { + /* Buffer too small! */ + dk3app_log_i1(app, DK3_LL_ERROR, 38); + } break; +#endif + default: { + /* Failed to find current working directory! */ + dk3app_log_i1(app, DK3_LL_ERROR, 53); + } break; + } + } + } + } + return back; +} + + + +int +dk3sf_c16_find_exec_app( + dk3_c16_t *d, size_t s, dk3_c16_t const *w, dk3_c16_t const *c, dk3_app_t *app +) +{ + int back = 0; + if((d) && (s)) { + if(GetModuleFileNameW(GetModuleHandle(NULL),d,(DWORD)s)) { + back = 1; + } else { + if(app) { + /* Failed to find name of executable! */ + dk3app_log_i1(app, DK3_LL_ERROR, 40); + } + } + } + return back; +} + + + +static +int +dk3sf_c16_is_drive(dk3_c16_t const *p) +{ + int back = 0; + if(dk3str_c16_len(p) == 2) { + if((*p >= L'A') && (*p <= L'Z')) { + back = 1; + } + if((*p >= L'a') && (*p <= L'z')) { + back = 1; + } + if(back) { + back = 0; + if(p[1] == L':') { back = 1; } + } + } + return back; +} + + + +int +dk3sf_c16_mkdir_app(dk3_c16_t const *p, int mo, dk3_app_t *app) +{ + int back = 0; + dk3_c16_t buffer[DK3_MAX_PATH]; /* File names of parent directories. */ + dk3_c16_t *ptr = NULL; /* Current slash/backslash position. */ + int cc = 1; /* Flag: Can continue. */ + int m = 0; /* Permissions. */ + dk3_stat_t stb; /* Test whether file/dir exists. */ + if(p) { + m = dk3sf_convert_back_file_permissions(mo); + if(dk3str_c16_len(p) < sizeof(buffer)) { + dk3str_c16_cpy(buffer, p); + ptr = buffer; cc = 1; + while((cc) && (ptr)) { + ptr = dk3str_c16_chr(ptr, 0x005CU); + if(ptr) { + *ptr = 0U; + if((dk3str_c16_len(buffer) > 0) && (!dk3sf_c16_is_drive(buffer))) { + if(dk3sf_c16_stat_app(&stb, buffer, NULL)) { + if(((stb.ft) & (~(DK3_FT_SYMLINK))) != DK3_FT_DIRECTORY) { + cc = 0; + if(app) { + /* Not a directory! */ +#if DK3_CHAR_SIZE == 2 + dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 83); +#endif + } + } + } else { + if(_wmkdir(buffer) != 0) { + cc = 0; + if(app) { + /* Failed to create directory! */ +#if DK3_CHAR_SIZE == 2 + dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 86); +#endif + } + } + } + } + *ptr = 0x005CU; + ptr++; + } + } + if(cc) { + if(dk3sf_c16_stat_app(&stb, buffer, NULL)) { + if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) { + back = 1; + } else { + if(app) { + /* Not a directory! */ +#if DK3_CHAR_SIZE == 2 + dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 83); +#endif + } + } + } else { + if(_wmkdir(buffer) == 0) { + back = 1; + } else { +#if DK3_CHAR_SIZE == 2 + dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 86); +#endif + } + } + } + } else { + if(app) { + /* Path too long! */ +#if DK3_CHAR_SIZE == 2 + dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, p); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 87); +#endif + } + } + } + return back; +} + + + +int +dk3sf_c16_get_hostname_app(dk3_c16_t *db, size_t sz, dk3_app_t *app) +{ + int back = 0; + DWORD s = 0; /* Buffer size / result length. */ + if((db) && (sz)) { + s = (DWORD)sz; + if(GetComputerNameExW(ComputerNameNetBIOS, db, &s)) { + if((size_t)s < sz) { + db[(size_t)s] = L'\0'; + } else { + db[sz - 1] = L'\0'; + } + back = 1; + } else { + if(app) { + /* ERROR: Failed to find NetBIOS name! */ + dk3app_log_i1(app, DK3_LL_ERROR, 131); + } + } + } + return back; +} + + + +int +dk3sf_c8_get_hostname_app(char *db, size_t sz, dk3_app_t *app) +{ + int back = 0; + DWORD s = 0; /* Buffer size / result length. */ + if((db) && (sz)) { + s = (DWORD)sz; + if(GetComputerNameExA(ComputerNameNetBIOS, db, &s)) { + if((size_t)s < sz) { + db[(size_t)s] = '\0'; + } else { + db[sz - 1] = '\0'; + } + back = 1; + } else { + if(app) { + /* ERROR: Failed to find NetBIOS name! */ + dk3app_log_i1(app, DK3_LL_ERROR, 131); + } + } + } + return back; +} + + + +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "dkChar must be 8 or 16 bit!" +#else +/* +++ Windows, dkChar 16 bit +++ */ + + + +int +dk3sf_fgets_fn_app( + dkChar *db, size_t sz, FILE *fi, dkChar const *fn, dk3_app_t *app +) +{ + int back = 0; + $? "+ dk3sf_fgets" + if((db) && (sz) && (fi)) { + if(fgetws(db, (int)sz, fi)) { + if(db[0] == DK3_CHAR_BOM) { $? ". BOM at start of line" + dk3str_c16_cpy(db, &(db[1])); + } + back = 1; + } else { + if(!feof(fi)) { + if(app) { + if(fn) { + dk3app_log_i3(app, DK3_LL_ERROR, 346, 347, fn); + } else { + dk3app_log_i1(app, DK3_LL_ERROR, 345); + } + } + } + } + } $? "- dk3sf_fgets %d", back + return back; +} + + + +int +dk3sf_fputc_fn_app(dkChar ch, FILE *fi, dkChar const *fn, dk3_app_t *app) +{ + int back = 0; + if(fi) { + if(fputwc(ch, fi) != WEOF) { + back = 1; + } else { + if(app) { + if(fn) { + dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn); + } else { + dk3app_log_i1(app, DK3_LL_ERROR, 120); + } + } + } + } + return back; +} + + + +int +dk3sf_fputs_fn_app(dkChar const *st,FILE *fi,dkChar const *fn,dk3_app_t *app) +{ + int back = 0; + if((st) && (fi)) { + if(fputws(st, fi) != WEOF) { + back = 1; + } else { + if(app) { + if(fn) { + dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn); + } else { + dk3app_log_i1(app, DK3_LL_ERROR, 120); + } + } + } + } + return back; +} + + + +void +dk3sf_initialize_stdout(void) +{ + static int not_bom_written_to_stdout = 1; + if(not_bom_written_to_stdout) { + not_bom_written_to_stdout = 0; + (void)_setmode(_fileno(stdout), _O_U16TEXT); + if(!_isatty(_fileno(stdout))) { + fputwc(0xFEFF, stdout); + } + } +} + + + +void +dk3sf_initialize_stdout_no_bom(void) +{ + static int not_bom_written_to_stdout = 1; + if(not_bom_written_to_stdout) { + not_bom_written_to_stdout = 0; + (void)_setmode(_fileno(stdout), _O_U16TEXT); + } +} + + + +void +dk3sf_initialize_stderr(void) +{ + static int not_bom_written_to_stderr = 1; + if(not_bom_written_to_stderr) { + not_bom_written_to_stderr = 0; + (void)_setmode(_fileno(stderr), _O_U16TEXT); + if(!_isatty(_fileno(stderr))) { + fputwc(0xFEFF, stderr); + } + } +} + + + +void +dk3sf_initialize_file(FILE *fipo) +{ + (void)_setmode(_fileno(fipo), _O_U16TEXT); + fputwc(0xFEFF, fipo); +} + + + +/* --- Windows, dkChar 16 bit --- */ +#endif +#else +/* +++ Windows, dkChar 8 bit +++ */ + + + +int +dk3sf_fgets_fn_app( + dkChar *db, size_t sz, FILE *fi, dkChar const *fn, dk3_app_t *app +) +{ + int back = 0; + if((db) && (sz) && (fi)) { + if(fgets(db, sz, fi)) { + back = 1; + } else { + if(!feof(fi)) { + if(app) { + if(fn) { + dk3app_log_i3(app, DK3_LL_ERROR, 346, 347, fn); + } else { + dk3app_log_i1(app, DK3_LL_ERROR, 345); + } + } + } + } + } + return back; +} + + +int +dk3sf_fputs_fn_app(dkChar const *st,FILE *fi,dkChar const *fn,dk3_app_t *app) +{ + int back = 0; + if((st) && (fi)) { + if(fputs(st, fi) != EOF) { + back = 1; + } else { + if(app) { + if(fn) { + dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn); + } else { + dk3app_log_i1(app, DK3_LL_ERROR, 120); + } + } + } + } + return back; +} + + + +int +dk3sf_fputc_fn_app(dkChar ch, FILE *fi, dkChar const *fn, dk3_app_t *app) +{ + int back = 0; + if(fi) { + if(fputc(ch, fi) != EOF) { + back = 1; + } else { + if(app) { + if(fn) { + dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn); + } else { + dk3app_log_i1(app, DK3_LL_ERROR, 120); + } + } + } + } + return back; +} + + + +void +dk3sf_initialize_stdout(void) +{ +} + + + +void +dk3sf_initialize_stderr(void) +{ +} + + +void +dk3sf_initialize_file(FILE *fipo) +{ +} + + +/* --- Windows, dkChar 8 bit --- */ +#endif + +/* --- Windows --- */ +#else +/* +++ non-Windows +++ */ + + + +/** 8-bit character keywords for use on non-Windows systems. +*/ +static char const * const kw_c8_no_win[] = { +/* 0 */ "/", +/* 1 */ "PATH", +NULL +}; + + + +dk3_um_t +dk3sf_getpid(void) +{ + dk3_um_t back = DK3_UM_0; +#if DK3_HAVE_GETPID + back = (dk3_um_t)getpid(); +#else +#if DK3_HAVE__GETPID + back = (dk3_um_t)_getpid(); +#else +#error "No getpid() function!" +#endif +#endif + return back; +} + + + +dk3_c8_t * +dk3sf_c8_getenv(char const *name) +{ + char *back = NULL; + if(name) { + back = getenv(name); + } + return back; +} + + + +int +dk3sf_c8_remove_dir_app(char const *n, dk3_app_t *app) +{ + int back = 0; + if(n) { +#if DK3_HAVE_RMDIR + if(rmdir(n) == 0) { + back = 1; + } else { + if(app) { + /* Failed to remove directory! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 69, 70, n); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 68); +#endif + dk3sf_report_errno(app, errno, dk3sf_function_names[2]); + } + } +#else +#error "No rmdir() function!" +#endif + } + return back; +} + + +int +dk3sf_c8_remove_file_app(char const *n, dk3_app_t *app) +{ + int back = 0; + if(n) { +#if DK3_HAVE_UNLINK + if(unlink(n) == 0) { + back = 1; + } else { + if(app) { + /* ERROR: Failed to unlink file */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 88, 89, n); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 90); +#endif + dk3sf_report_errno(app, errno, dk3sf_function_names[3]); + } + } +#else +#error "No support for unlink" +#endif + } + return back; +} + + +/** Copy logname of user record to buffer. + @param d Destination buffer. + @param s Size of \a d. + @param p User record. + @param app Application structure for diagnostics, may be NULL. + @return 1 on success, 0 on error. +*/ +static +int +dk3sf_c8_copy_logname(char *d, size_t s, struct passwd *p, dk3_app_t *app) +{ + int back = 0; + $? "+ dk3sf_c8_copy_logname" + if(p) { $? ". p ok" + if(p->pw_name) { $? ". name ok" + if(dk3str_c8_len(p->pw_name) < s) { $? ". name length ok" + dk3str_c8_cpy_not_overlapped(d, p->pw_name); + back = 1; + } else { $? "! name too long" + if(app) { + /* Destination buffer too small! */ + dk3app_log_i1(app, DK3_LL_ERROR, 38); + } + } + } else { + if(app) { + /* No name entry in record! */ + dk3app_log_i1(app, DK3_LL_ERROR, 91); + } + } + } $? "- dk3sf_c8_copy_logname %d", back + return back; +} + + + +int +dk3sf_c8_get_logname_app(char *d, size_t s, dk3_app_t *app) +{ + int back = 0; + uid_t u = 0; /* Current user ID. */ + struct passwd *p = NULL; /* Current user to process. */ + char uidbuffer[128]; /* Text buffer to store UID. */ + $? "+ dk3sf_c8_get_logname_app" + if((d) && (s)) { + u = getuid(); +#if DK3_HAVE_GETPWUID + p = getpwuid(u); $? ". getpwuid()" + if(p) { $? ". entry found" + back = dk3sf_c8_copy_logname(d, s, p, app); + } else { $? "! entry not found" + if(app) { + /* No passwd record for UID! */ +#if DK3_CHAR_SIZE == 1 + dk3ma_um_to_c8_string(uidbuffer, sizeof(uidbuffer), (dk3_um_t)u); + dk3app_log_i3(app, DK3_LL_ERROR, 92, 93, uidbuffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 94); +#endif + dk3sf_report_errno(app, errno, dk3sf_function_names[4]); + } + } +#else +#if DK3_HAVE_SETPWENT + setpwent(); +#endif + { + int cc; + int found; $? ". getpwent()" + cc = 1; found = 0; + while(cc) { + p = getpwent(); + if(p) { + if(p->pw_uid == u) { + cc = 0; + found = 1; $? ". entry found" + back = dk3sf_c8_copy_logname(d, s, p, app); + } + } else { cc = 0; } + } + if(!found) { $? "! entry not found" + if(app) { + /* No passwd record for UID! */ +#if DK3_CHAR_SIZE == 1 + dk3ma_um_to_c8_string(uidbuffer, sizeof(uidbuffer), (dk3_um_t)u); + dk3app_log_i3(app, DK3_LL_ERROR, 92, 93, uidbuffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 94); +#endif + } + } + } +#if DK3_HAVE_SETPWENT + endpwent(); +#endif +#endif + } $? "- dk3sf_c8_get_logname_app %d", back + return back; +} + + + +int +dk3sf_c8_get_home_app(char *d, size_t s, dk3_app_t *app) +{ + int back = 0; + uid_t u = 0; /* Current user ID to process. */ + struct passwd *p = NULL; /* Current user to process. */ + char uidbuffer[128]; /* Text buffer to store UID. */ + if((d) && (s)) { + u = getuid(); +#if DK3_HAVE_GETPWUID + p = getpwuid(u); + if(p) { + if(p->pw_dir) { + if(dk3str_c8_len(p->pw_dir) < s) { + dk3str_c8_cpy_not_overlapped(d, p->pw_dir); + back = 1; + } else { + if(app) { + /* Destination buffer too small! */ + dk3app_log_i1(app, DK3_LL_ERROR, 38); + } + } + } else { + if(app) { + /* Home directory entry empty! */ + dk3app_log_i1(app, DK3_LL_ERROR, 95); + } + } + } else { + if(app) { + /* No passwd record for uid! */ +#if DK3_CHAR_SIZE == 1 + dk3ma_um_to_c8_string(uidbuffer, sizeof(uidbuffer), (dk3_um_t)u); + dk3app_log_i3(app, DK3_LL_ERROR, 92, 93, uidbuffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 94); +#endif + dk3sf_report_errno(app, errno, dk3sf_function_names[4]); + } + } +#else + { + int cc; + int found; + cc = 1; found = 0; +#if DK3_HAVE_SETPWENT + setpwent(); +#endif + while(cc) { + p = getpwent(); + if(p) { + if(p->pw_uid == u) { + cc = 0; found = 1; + if(p->pw_dir) { + if(dk3str_c8_len(p->pw_dir) < s) { + dk3str_c8_cpy_not_overlapped(d, p->pw_dir); + back = 1; + } else { + if(app) { + /* Destination buffer too small! */ + dk3app_log_i1(app, DK3_LL_ERROR, 38); + } + } + } else { + if(app) { + /* Home directory entry empty! */ + dk3app_log_i1(app, DK3_LL_ERROR, 95); + } + } + } + } else { cc = 0; } + } +#if DK3_HAVE_SETPWENT + endpwent(); +#endif + if(!found) { + if(app) { + /* No entry for uid! */ +#if DK3_CHAR_SIZE == 1 + dk3ma_um_to_c8_string(uidbuffer, sizeof(uidbuffer), (dk3_um_t)u); + dk3app_log_i3(app, DK3_LL_ERROR, 92, 93, uidbuffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 94); +#endif + } + } + } +#endif + } + return back; +} + + +int +dk3sf_time(dk3_time_t *timer) +{ + int back = 1; + time(timer); + return back; +} + + + +/** Convert file type from system representation to DK3_FT_xxx. + @param m File type as found by stat(). + @return DK3_FT_xxx. +*/ +static +int +dk3sf_convert_file_type(mode_t m) +{ + int back = 0; + switch(m & S_IFMT) { + case S_IFIFO: back = DK3_FT_FIFO; break; + case S_IFCHR: back = DK3_FT_SPECIAL_CHAR; break; + case S_IFDIR: back = DK3_FT_DIRECTORY; break; + case S_IFBLK: back = DK3_FT_SPECIAL_BLOCK; break; + case S_IFREG: back = DK3_FT_REGULAR; break; + case S_IFSOCK: back = DK3_FT_SOCKET; break; +#ifdef S_IFMPC + case S_IFMPC: back = DK3_FT_MUX_CHAR; break; +#endif +#ifdef S_IFNAM + case S_IFNAM: back = DK3_FT_XENIX_SPECIAL; break; +#endif +#ifdef S_INSEM + case S_INSEM: back = DK3_FT_XENIX_SEMAPHORE; break; +#endif +#ifdef S_INSHD + case S_INSHD: back = DK3_FT_XENIX_SHARED_DATA; break; +#endif +#ifdef S_IFMPB + case S_IFMPB: back = DK3_FT_MUX_BLOCK; break; +#endif +#ifdef S_IFCMP + case S_IFCMP: back = DK3_FT_VXFS_COMPRESSED; break; +#endif +#ifdef S_IFNWK + case S_IFNWK: back = DK3_FT_NETWORK_SPECIAL; break; +#endif +#ifdef S_IFSHAD + case S_IFSHAD: back = DK3_FT_ACL_SHADOW; break; +#endif +#ifdef S_IFDOOR + case S_IFDOOR: back = DK3_FT_DOOR; break; +#endif +#ifdef S_IFWHT + case S_IFWHT: back = DK3_FT_WHITEOUT; break; +#endif + } + return back; +} + + + +/** Convert file permissions from system representation to + DK3_PERM_xxx + @param m File mode as obtained from stat(). + @return DK3_PERM_xxx value or combination. +*/ +static +int +dk3sf_convert_file_permissions(mode_t m) +{ + int back = 0; + DK3SF_ADDIF(S_IRUSR,DK3_FPERM_U_READ) + DK3SF_ADDIF(S_IWUSR,DK3_FPERM_U_WRITE) + DK3SF_ADDIF(S_IXUSR,DK3_FPERM_U_EXEC) + DK3SF_ADDIF(S_IRGRP,DK3_FPERM_G_READ) + DK3SF_ADDIF(S_IWGRP,DK3_FPERM_G_WRITE) + DK3SF_ADDIF(S_IXGRP,DK3_FPERM_G_EXEC) + DK3SF_ADDIF(S_IROTH,DK3_FPERM_O_READ) + DK3SF_ADDIF(S_IWOTH,DK3_FPERM_O_WRITE) + DK3SF_ADDIF(S_IXOTH,DK3_FPERM_O_EXEC) + DK3SF_ADDIF(S_ISUID,DK3_FPERM_SUID) + DK3SF_ADDIF(S_ISGID,DK3_FPERM_SGID) + DK3SF_ADDIF(S_ISVTX,DK3_FPERM_VTX) + return back; +} + + + +/** Convert file permissions back from dktools to system values. + @param m File permissions in dktools notation. + @return File permissions in system notation. +*/ +static +mode_t +dk3sf_convert_back_file_permissions(int m) +{ + mode_t back = 0; + DK3SF_ADDIF(DK3_FPERM_U_READ,S_IRUSR) + DK3SF_ADDIF(DK3_FPERM_U_WRITE,S_IWUSR) + DK3SF_ADDIF(DK3_FPERM_U_EXEC,S_IXUSR) + DK3SF_ADDIF(DK3_FPERM_G_READ,S_IRGRP) + DK3SF_ADDIF(DK3_FPERM_G_WRITE,S_IWGRP) + DK3SF_ADDIF(DK3_FPERM_G_EXEC,S_IXGRP) + DK3SF_ADDIF(DK3_FPERM_O_READ,S_IROTH) + DK3SF_ADDIF(DK3_FPERM_O_WRITE,S_IWOTH) + DK3SF_ADDIF(DK3_FPERM_O_EXEC,S_IXOTH) + DK3SF_ADDIF(DK3_FPERM_SUID,S_ISUID) + DK3SF_ADDIF(DK3_FPERM_SGID,S_ISGID) + DK3SF_ADDIF(DK3_FPERM_VTX,S_ISVTX) + return back; +} + + +int +dk3sf_c8_stat_app(dk3_stat_t *st, char const *fn, dk3_app_t *app) +{ + int back = 0; + $? "+ dk3sf_c8_stat_app \"%!8s\"", fn + if((st) && (fn)) { +#if DK3_HAVE_LARGEFILE64_SOURCE && DK3_HAVE_STAT64 + struct stat64 stb; /* Result from stat64(). */ +#if DK3_HAVE_LSTAT64 + struct stat64 lstb; /* Result from lstat64(). */ +#endif + $? ". use stat64() / lstat64()" + if(stat64(fn, &stb) == 0) { $? ". stat64 ok" + st->u = (dk3_um_t)(stb.st_uid); + st->g = (dk3_um_t)(stb.st_gid); + st->device = (dk3_um_t)(stb.st_dev); + st->rdev = (dk3_um_t)(stb.st_rdev); + st->inode = (dk3_um_t)(stb.st_ino); + st->nlink = (dk3_um_t)(stb.st_nlink); + st->cre = (dk3_time_t)(stb.st_ctime); + st->mod = (dk3_time_t)(stb.st_mtime); + st->acc = (dk3_time_t)(stb.st_atime); + st->ft = dk3sf_convert_file_type(stb.st_mode); + st->perm = dk3sf_convert_file_permissions(stb.st_mode); + st->sz = (dk3_um_t)(stb.st_size); + st->lsz = st->sz; + st->ai = 0x00; +#if DK3_HAVE_LSTAT64 + if(lstat64(fn, &lstb) == 0) { + back = 1; + if(((lstb.st_mode) & S_IFMT) == S_IFLNK) { + st->ft |= DK3_FT_SYMLINK; + st->lu = (dk3_um_t)(lstb.st_uid); + st->lg = (dk3_um_t)(lstb.st_gid); + st->ldevice = (dk3_um_t)(lstb.st_dev); + st->lrdev = (dk3_um_t)(lstb.st_rdev); + st->linode = (dk3_um_t)(lstb.st_ino); + st->lnlink = (dk3_um_t)(lstb.st_nlink); + st->lcre = (dk3_time_t)(lstb.st_ctime); + st->lmod = (dk3_time_t)(lstb.st_mtime); + st->lacc = (dk3_time_t)(lstb.st_atime); + st->lft = dk3sf_convert_file_type(lstb.st_mode); + st->lperm = dk3sf_convert_file_permissions(lstb.st_mode); + st->lsz = (dk3_um_t)(lstb.st_size); + if(lstb.st_uid != stb.st_uid) { + st->ai |= DK3_STAT_AI_USER_DIFFERS; + } + if(lstb.st_gid != stb.st_gid) { + st->ai |= DK3_STAT_AI_GROUP_DIFFERS; + } + if(lstb.st_dev != stb.st_dev) { + st->ai |= DK3_STAT_AI_FAR_LINK; + } + } $? ". ft = %d", st->ft + } else { $? "! lstat64() failed" + if(app) { + /* lstat() failed! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 96, 97, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 98); +#endif + } + } +#else + back = 1; +#endif + } else { $? "! stat64() failed for \"%!8s\"", fn +#if DK3_HAVE_LSTAT64 + if(lstat64(fn, &lstb) == 0) { + back = 1; + st->u = DK3_UM_0; + st->g = DK3_UM_0; + st->device = DK3_UM_0; + st->rdev = DK3_UM_0; + st->inode = DK3_UM_0; + st->nlink = DK3_UM_0; + st->cre = (dk3_time_t)0UL; + st->mod = (dk3_time_t)0UL; + st->acc = (dk3_time_t)0UL; + st->ft = DK3_FT_SYMLINK | DK3_FT_BAD_SYMLINK; + st->perm = 0; + st->sz = DK3_UM_0; + st->ai = 0x00; + st->lu = (dk3_um_t)(lstb.st_uid); + st->lg = (dk3_um_t)(lstb.st_gid); + st->ldevice = (dk3_um_t)(lstb.st_dev); + st->lrdev = (dk3_um_t)(lstb.st_rdev); + st->linode = (dk3_um_t)(lstb.st_ino); + st->lnlink = (dk3_um_t)(lstb.st_nlink); + st->lcre = (dk3_time_t)(lstb.st_ctime); + st->lmod = (dk3_time_t)(lstb.st_mtime); + st->lacc = (dk3_time_t)(lstb.st_atime); + st->lft = dk3sf_convert_file_type(lstb.st_mode); + st->lperm = dk3sf_convert_file_permissions(lstb.st_mode); + st->lsz = (dk3_um_t)(lstb.st_size); + } else { + if(app) { + /* stat failed */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 61, 62, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 99); +#endif + dk3sf_report_errno(app, errno, dk3sf_function_names[5]); + } + } +#else + if(app) { + /* stat failed */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 61, 62, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 99); +#endif + dk3sf_report_errno(app, errno, dk3sf_function_names[6]); + } +#endif + } +#else +#if DK3_HAVE_STAT + struct stat stb; +#if DK3_HAVE_LSTAT + struct stat lstb; +#endif + $? ". used stat() / lstat()" + if(stat(fn, &stb) == 0) { $? ". stat() ok" + st->u = (dk3_um_t)(stb.st_uid); + st->g = (dk3_um_t)(stb.st_gid); + st->device = (dk3_um_t)(stb.st_dev); + st->rdev = (dk3_um_t)(stb.st_rdev); + st->inode = (dk3_um_t)(stb.st_ino); + st->nlink = (dk3_um_t)(stb.st_nlink); + st->cre = (dk3_time_t)(stb.st_ctime); + st->mod = (dk3_time_t)(stb.st_mtime); + st->acc = (dk3_time_t)(stb.st_atime); + st->ft = dk3sf_convert_file_type(stb.st_mode); + st->perm = dk3sf_convert_file_permissions(stb.st_mode); + st->sz = (dk3_um_t)(stb.st_size); + sz->lsz = st->sz; + st->ai = 0x00; +#if DK3_HAVE_LSTAT + if(lstat(fn, &lstb) == 0) { + back = 1; + if(((lstb.st_mode) & S_IFMT) == S_IFLNK) { + st->ft |= DK3_FT_SYMLINK; + st->lu = (dk3_um_t)(lstb.st_uid); + st->lg = (dk3_um_t)(lstb.st_gid); + st->ldevice = (dk3_um_t)(lstb.st_dev); + st->lrdev = (dk3_um_t)(lstb.st_rdev); + st->linode = (dk3_um_t)(lstb.st_ino); + st->lnlink = (dk3_um_t)(lstb.st_nlink); + st->lcre = (dk3_time_t)(lstb.st_ctime); + st->lmod = (dk3_time_t)(lstb.st_mtime); + st->lacc = (dk3_time_t)(lstb.st_atime); + st->lft = dk3sf_convert_file_type(lstb.st_mode); + st->lperm = dk3sf_convert_file_permissions(lstb.st_mode); + sz->lsz = (dk3_um_t)(lstb.st_size); + if(lstb.st_uid != stb.st_uid) { + st->ai |= DK3_STAT_AI_USER_DIFFERS; + } + if(lstb.st_gid != stb.st_gid) { + st->ai |= DK3_STAT_AI_GROUP_DIFFERS; + } + if(lstb.st_dev != stb.st_dev) { + st->ai |= DK3_STAT_AI_FAR_LINK; + } + } $? ". ft = %d", st->ft + } else { $? "! lstat() failed" + if(app) { + /* lstat() failed! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 96, 97, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 98); +#endif + } + } +#else + back = 1; +#endif + } else { $? "! stat() failed" +#if DK3_HAVE_LSTAT + if(lstat(fn,&lstb) == 0) { + back = 1; + st->u = DK3_UM_0; + st->g = DK3_UM_0; + st->device = DK3_UM_0; + st->rdev = DK3_UM_0; + st->inode = DK3_UM_0; + st->nlink = DK3_UM_0; + st->cre = (dk3_time_t)0UL; + st->mod = (dk3_time_t)0UL; + st->acc = (dk3_time_t)0UL; + st->ft = DK3_FT_SYMLINK | DK3_FT_BAD_SYMLINK; + st->perm = 0; + st->sz = DK3_UM_0; + st->ai = 0x00; + st->lu = (dk3_um_t)(lstb.st_uid); + st->lg = (dk3_um_t)(lstb.st_gid); + st->ldevice = (dk3_um_t)(lstb.st_dev); + st->lrdev = (dk3_um_t)(lstb.st_rdev); + st->linode = (dk3_um_t)(lstb.st_ino); + st->lnlink = (dk3_um_t)(lstb.st_nlink); + st->lcre = (dk3_time_t)(lstb.st_ctime); + st->lmod = (dk3_time_t)(lstb.st_mtime); + st->lacc = (dk3_time_t)(lstb.st_atime); + st->lft = dk3sf_convert_file_type(lstb.st_mode); + st->lperm = dk3sf_convert_file_permissions(lstb.st_mode); + st->lsz = (dk3_um_t)(lstb.st_size); + } else { + if(app) { + /* stat() failed! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 61, 62, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 99); +#endif + dk3sf_report_errno(app, errno, dk3sf_function_names[8]); + } + } +#else + if(app) { + /* stat() failed! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 61, 62, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 99); +#endif + dk3sf_report_errno(app, errno, dk3sf_function_names[7]); + } +#endif + } +#else +#error "Not stat() function available!" +#endif +#endif + } $? "- dk3sf_c8_stat_app %d", back + return back; +} + + + +/** Check whether opening a file is allowed. + @param fn File name. + @param want_to_write Flag: Write access is wanted. + @param app Application structure for diagnostics, may be NULL. + @return 1 for write allowed, 0 for write denied. +*/ +static +int +dk3sf_c8_check_open_file(char const *fn, int want_to_write, dk3_app_t *app) +{ + int back = 1; + dk3_stat_t stb; /* Check for existing file. */ + if(dk3sf_c8_stat_app(&stb, fn, NULL)) { + if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) { + if(app) { + back = 0; + /* Name refers a directory! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 74, 75, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 76); +#endif + } + } + if(want_to_write) { + if((stb.ft) & DK3_FT_SYMLINK) { + if((stb.ai) & DK3_STAT_AI_USER_DIFFERS) { + back = 0; + /* Symlink owner is not file owner! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 100, 101, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 102); +#endif + } + } + } + } + return back; +} + + + +FILE * +dk3sf_c8_fopen_app(char const *fn, char const *mo, dk3_app_t *app) +{ + FILE *back = NULL; + char const *moptr = NULL; /* Traverse mode string. */ + int want_to_write = 0; /* Flag: Write access wanted. */ + $? "+ dk3sf_c8_fopen_app \"%!8s\" \"%!8s\"", TR_8STR(fn), TR_8STR(mo) + if((fn) && (mo)) { + moptr = mo; + while(*moptr) { + switch(*moptr) { + case 'w': case 'a': case '+': { want_to_write = 1; } break; + } + moptr++; + } + if(dk3sf_c8_check_open_file(fn, want_to_write, app)) { +#if DK3_HAVE_LARGEFILE64_SOURCE && DK3_HAVE_FOPEN64 + back = fopen64(fn, mo); $? ". attempt fopen64" +#else + back = fopen(fn, mo); $? ". attempt fopen" +#endif + if(!(back)) { + if(app) { + /* Failed to open file for writing! */ + if(want_to_write) { +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 77, 78, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 79); +#endif + } else { +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 143, 144, fn); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 145); +#endif + } + dk3sf_report_errno(app, errno, dk3sf_function_names[9]); + } + } + } + } $? "- dk3sf_c8_fopen_app %!8s", TR_8PTR(back) + return back; +} + + +#if DK3_HAVE_LOCALTIME_R +int +dk3sf_localtime_app( + dk3_tm_t *dest, + dk3_time_t *timer, + dk3_app_t *app +) +{ + int back = 0; + struct tm res, *rp; + if((dest) && (timer)) { + if((rp = localtime_r(timer, &res)) != NULL) { + back = 1; + dest->Y = 1900 + rp->tm_year; + dest->M = 1 + rp->tm_mon; + dest->D = rp->tm_mday; + dest->h = rp->tm_hour; + dest->m = rp->tm_min; + dest->s = rp->tm_sec; + } else { + if(app) { + /* ERROR: localtime_r failed! */ + dk3app_log_i1(app, DK3_LL_ERROR, 268); + dk3sf_report_errno(app, errno, dk3sf_function_names[10]); + } + } + } + return back; +} + +int +dk3sf_c8_time_convert_app( + dkChar *dest, size_t sz, dk3_time_t const *timer, dk3_app_t *app +) +{ + int back = 0; + char buffer[64]; /* Buffer. */ + struct tm res, *rp; /* Conversion result. */ + if((dest) && (sz) && (timer)) { + rp = localtime_r(timer, &res); + if(rp) { + sprintf( + buffer, + "%04d-%02d-%02d %02d:%02d:%02d", + (1900 + rp->tm_year), + (1 + rp->tm_mon), + rp->tm_mday, + rp->tm_hour, + rp->tm_min, + rp->tm_sec + ); + if(sz > dk3str_c8_len(buffer)) { + dk3str_c8_cpy_not_overlapped(dest, buffer); + back = 1; + } else { + if(app) { + /* Buffer too small! */ + dk3app_log_i1(app, DK3_LL_ERROR, 38); + } + } + } else { + if(app) { + /* localtime_r failed! */ + dk3app_log_i1(app, DK3_LL_ERROR, 80); + dk3sf_report_errno(app, errno, dk3sf_function_names[10]); + } + } + } + return back; +} +#else +#error "Function localtime_r() not available!" +#endif + + + +#if DK3_HAVE_GETCWD || DK3_HAVE__GETCWD +int +dk3sf_c8_getcwd_app(char *dest, size_t sz, dk3_app_t *app) +{ + int back = 0; + if((dest) && (sz)) { +#if DK3_HAVE_GETCWD + if(getcwd(dest, sz)) +#else + if(_getcwd(dest, sz)) +#endif + { + back = 1; + } else { + if(app) { + switch(errno) { +#ifdef ERANGE + case ERANGE: { + /* Buffer too small! */ + dk3app_log_i1(app, DK3_LL_ERROR, 38); + } break; +#endif + default: { + dk3app_log_i1(app, DK3_LL_ERROR, 53); + dk3sf_report_errno(app, errno, dk3sf_function_names[11]); + } break; + } + } + } + } + return back; +} +#else +#error "Neither getcwd() or _getcwd() available!" +#endif + + + +/** Check whether or not a file is executable. + @param f File name. + @return 1 for exectuable, 0 for not executable. +*/ +static +int +dk3sf_c8_check_exec(char const *f) +{ + int back = 0; + int testperm; /* Permissions of file. */ + dk3_stat_t stb; /* stat() result to check for file. */ + $? "+ dk3sf_c8_check_exec \"%!8s\"", f + if(dk3sf_c8_stat_app(&stb, f, NULL)) { $? ". file name ok" + if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_REGULAR) { $? ". type ok" + testperm = (DK3_FPERM_U_EXEC | DK3_FPERM_G_EXEC | DK3_FPERM_O_EXEC); + if((stb.perm) & testperm) { $? ". permissions ok" + back = 1; + } else { $? "! wrong permissions" + } + } else { $? "! wrong file type" + } + } else { $? "! file does not exist" + } $? "- dk3sf_c8_check_exec %d", back + return back; +} + + + +int +dk3sf_c8_find_exec_app( + char *d, size_t s, char const *w, char const *c, dk3_app_t *app +) +{ + int back = 0; + int cc = 0; /* Flag: Can continue. */ + char *pathcopy = NULL; /* Copy of parent directory. */ + char *p = NULL; + char *pn = NULL; + size_t tsl = 0; /* Needed buffer length. */ + $? "+ dk3sf_c8_find_exec_app" + if((d) && (s) && (w) && (c)) { $? ". args ok" + if(dk3str_c8_chr(c, DK3_C8_SEP)) { $? ". combine w and c" + if(dk3str_c8_is_abs_path(c)) { $? ". c is absolute path" + if(dk3str_c8_len(c) < s) { $? ". buffer length ok" + dk3str_c8_cpy_not_overlapped(d, c); + back = 1; $? ". result \"%!8s\"", d + } else { $? "! buffer too short" + if(app) { + /* c too long! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 103, 104, c); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 105); +#endif + } + } + } else { $? ". c is relative path" + if(dk3str_c8_len(w) < s) { + dk3str_c8_cpy_not_overlapped(d, w); + back = dk3str_c8_append_path_app(d, s, c, app); + if(back) { $? ". result \"%!8s\"", d + } + } else { $? "! buffer too short" + if(app) { + /* w too long! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, w); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 87); +#endif + } + } + } + } else { $? ". search PATH" + p = getenv(kw_c8_no_win[1]); + if(p) { $? ". PATH ok" + pathcopy = dk3str_dup_app(p, app); + if(pathcopy) { $? ". copy ok" + p = pathcopy; cc = 1; + while((p) && (cc) && (back == 0)) { + pn = dk3str_c8_chr(p, ':'); + if(pn) { *(pn++) = '\0'; } + if(dk3str_c8_len(p)) { $? ". one directory" + tsl = dk3str_c8_len(p); + tsl += dk3str_c8_len(kw_c8_no_win[0]); + tsl += dk3str_c8_len(c); + if(tsl < s) { $? ". buffer length ok" + dk3str_c8_cpy_not_overlapped(d, p); + dk3str_c8_cat(d, kw_c8_no_win[0]); + dk3str_c8_cat(d, c); + back = dk3sf_c8_check_exec(d); + } else { $? "! buffer too short" + cc = 0; + if(app) { + /* Destination buffer too small! */ + dk3app_log_i1(app, DK3_LL_ERROR, 38); + } + } + } else { $? ". current directory" + tsl = dk3str_c8_len(w); + tsl += dk3str_c8_len(kw_c8_no_win[0]); + tsl += dk3str_c8_len(c); + if(tsl < s) { $? ". buffer length ok" + dk3str_c8_cpy_not_overlapped(d, w); + dk3str_c8_cat(d, kw_c8_no_win[0]); + dk3str_c8_cat(d, c); + back = dk3sf_c8_check_exec(d); + } else { $? "! buffer too short" + cc = 0; + if(app) { + /* Destination buffer too small! */ + dk3app_log_i1(app, DK3_LL_ERROR, 38); + } + } + } + p = pn; + } + dk3_delete(pathcopy); + } else { $? "! memory" + } + } else { $? "! No PATH" + if(app) { + /* PATH environment variable not defined. */ + dk3app_log_i1(app, DK3_LL_ERROR, 106); + } + } + } + } $? "- dk3sf_c8_find_exec_app %d", back + return back; +} + + + +int +dk3sf_c8_mkdir_app(char const *p, int mo, dk3_app_t *app) +{ + int back = 0; + char buffer[DK3_MAX_PATH]; /* File names of parent directories. */ + char *ptr = NULL; /* Current path separator. */ + int cc = 0; /* Flag: Can continue. */ + mode_t m = 0; /* File creation mode. */ + dk3_stat_t stb; /* Check for existance of file or directory. */ + $? "+ dk3sf_c8_mkdir_app \"%!8s\"", TR_8STR(p) + if(p) { $? ". name ok" + m = dk3sf_convert_back_file_permissions(mo); + if(dk3str_c8_len(p) < sizeof(buffer)) { $? ". length ok" + dk3str_c8_cpy_not_overlapped(buffer, p); + ptr = buffer; cc = 1; + while((cc) && (ptr)) { $? ". loop \"%!8s\"", ptr + ptr = dk3str_c8_chr(ptr, DK3_C8_SEP); + if(ptr) { + *ptr = '\0'; $? ". directory \"%!8s\"", buffer + if(dk3str_c8_len(buffer) > 0) { + if(dk3sf_c8_stat_app(&stb, buffer, NULL)) { $? ". path exists" + if(((stb.ft) & (~(DK3_FT_SYMLINK))) != DK3_FT_DIRECTORY) { + cc = 0; $? "! path is not a directory" + if(app) { + /* Not a directory! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 83); +#endif + } + } + } else { $? ". must create dir \"%!8s\"", buffer +#if DK3_HAVE_MKDIR +#if DK3_HAVE_MKDIR2 + if(mkdir(buffer, m) == 0) +#else + if(mkdir(buffer) == 0) +#endif + { +#if DK3_HAVE_CHMOD + (void)chmod(buffer, m); $? ". mode %o", m +#endif + } else { + cc = 0; $? "! failed to create directory" + if(app) { + /* Failed to create directory! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 86); +#endif + dk3sf_report_errno(app, errno, dk3sf_function_names[12]); + } + } +#else + cc = 0; + if(app) { $? "! no mkdir) function" + /* No mkdir() function available! */ + dk3app_log_i1(app, DK3_LL_ERROR, 107); + } +#endif + } + } + *ptr = DK3_C8_SEP; + ptr++; + } + } + if(cc) { $? ". all parents ok path now \"%!8s\"", buffer + if(dk3sf_c8_stat_app(&stb, buffer, NULL)) { $? ". path exists" + if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) { + back = 1; $? ". path is a directory" + } else { $? "! path is not a directory" + if(app) { + /* Not a directory! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 83); +#endif + } + } + } else { $? ". must create \"%!8s\"", buffer +#if DK3_HAVE_MKDIR +#if DK3_HAVE_MKDIR2 + if(mkdir(buffer, m) == 0) +#else + if(mkdir(buffer) == 0) +#endif + { + back = 1; $? ". \"%!8s\" created successfully", buffer +#if DK3_HAVE_CHMOD + (void)chmod(buffer, m); $? ". mode %o", m +#endif + } else { $? "! failed to create \"%!8s\"", buffer +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 86); +#endif + dk3sf_report_errno(app, errno, dk3sf_function_names[12]); + } +#else + if(app) { $? "! no mkdir() function" + /* No mkdir() function available! */ + dk3app_log_i1(app, DK3_LL_ERROR, 107); + } +#endif + } + } + } else { $? "! directory name too long" + if(app) { + /* Path too long! */ +#if DK3_CHAR_SIZE == 1 + dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, p); +#else + dk3app_log_i1(app, DK3_LL_ERROR, 87); +#endif + } + } + } $? "- dk3sf_c8_mkdir_app %d", back + return back; +} + + +int +dk3sf_c8_get_hostname_app(char *db, size_t sz, dk3_app_t *app) +{ + int back = 0; + char *ptr = NULL; /* Begin of DNS domain name. */ + if((db) && (sz)) { + if(gethostname(db, sz) == 0) { + back = 1; + ptr = dk3str_c8_chr(db, '.'); + if(ptr) { + *ptr = '\0'; + } + } else { + if(app) { + /* ERROR: Failed to find host name! */ + dk3app_log_i1(app, DK3_LL_ERROR, 131); + dk3sf_report_errno(app, errno, dk3sf_function_names[13]); + } + } + } + return back; +} + + + +#if DK3_CHAR_SIZE > 1 +#error "dkChar must be 8 bit on non-Windows systems!" +#else +/* +++ non-Windows, dkChar 8 bit +++ */ + + + +int +dk3sf_fgets_fn_app( + dkChar *db, size_t sz, FILE *fi, dkChar const *fn, dk3_app_t *app +) +{ + int back = 0; + if((db) && (sz) && (fi)) { + if(fgets(db, sz, fi)) { + back = 1; + } else { + if(!feof(fi)) { + if(app) { + if(fn) { + dk3app_log_i3(app, DK3_LL_ERROR, 346, 347, fn); + } else { + dk3app_log_i1(app, DK3_LL_ERROR, 345); + } + dk3sf_report_errno(app, errno, dk3sf_function_names[25]); + } + } + } + } + return back; +} + + + +int +dk3sf_fputs_fn_app(dkChar const *st,FILE *fi,dkChar const *fn,dk3_app_t *app) +{ + int back = 0; + if((st) && (fi)) { + if(fputs(st, fi) >= 0) { + back = 1; + } else { + if(app) { + if(fn) { + dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn); + } else { + dk3app_log_i1(app, DK3_LL_ERROR, 120); + } + dk3sf_report_errno(app, errno, dk3sf_function_names[23]); + } + } + } + return back; +} + + + +int +dk3sf_fputc_fn_app(dkChar ch, FILE *fi, dkChar const *fn, dk3_app_t *app) +{ + int back = 0; + if(fi) { + if(fputc(ch, fi) != EOF) { + back = 1; + } else { + if(app) { + if(fn) { + dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn); + } else { + dk3app_log_i1(app, DK3_LL_ERROR, 120); + } + dk3sf_report_errno(app, errno, dk3sf_function_names[24]); + } + } + } + return back; +} + + + +void +dk3sf_initialize_stdout(void) +{ +} + + + +void +dk3sf_initialize_stderr(void) +{ +} + + + +void +dk3sf_initialize_file(FILE *fipo) +{ +} + + + +/* --- non-Windows, dkChar 8 bit --- */ +#endif + +/* --- non-Windows --- */ +#endif + + + +int +dk3sf_must_expand(dkChar const *fn) +{ + int back = 0; + $? "+ dk3sf_must_expand" + if(fn) { +#if DK3_ON_WINDOWS + dkChar const *ptr; + ptr = fn; + while((*ptr) && (back == 0)) { + switch(*ptr) { + case dkT('?'): + case dkT('*'): + { + back = 1; + } + break; + } + ptr++; + } +#endif + } $? "- dk3sf_must_expand %d", back + return back; +} + + + +int +dk3sf_c8_fputc(char c, FILE *f) +{ + int back = 0; + if(f) { +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 + if(fputwc((((wchar_t)c) & 0x000000FFUL), f) != WEOF) { + back = 1; + } +#else + if(fputwc((((wchar_t)c) & 0x00FFU), f) != WEOF) { + back = 1; + } +#endif +#else + if(fputc(c, f) != EOF) { + back = 1; + } +#endif + } + return back; +} + + + +int +dk3sf_c8_fputs(char const *s, FILE *f) +{ + int back = 0; + char const *ptr = NULL; + if((s) && (f)) { + back = 1; + ptr = s; + while(*ptr) { + if(!dk3sf_c8_fputc(*(ptr++), f)) { + back = 0; + } + } + } + return back; +} + + + +size_t +dk3sf_read_app(int fd, void *buf, size_t s, dk3_app_t *app) +{ + size_t back = 0; + $? "+ dk3sf_read_app buf=%!8s s=%u", TR_8PTR(buf), (unsigned)s + if((buf) && (s)) { +#if DK3_ON_WINDOWS + int rb; + $? ". Windows +" + rb = _read(fd, buf, (unsigned int)s); + if(rb >= 0) { + back = (size_t)rb; + } else { + /* ERROR: Read failed! */ + dk3app_log_i1(app, DK3_LL_ERROR, 124); + } + $? ". Windows -" +#else + $? ". non-Windows +" +#if DK3_HAVE_READ + ssize_t rb = 0; /* Number of bytes read. */ + $? ". read() +" + rb = read(fd, buf, s); + if(rb >= (ssize_t)0) { + back = (size_t)rb; + } else { + if(app) { + /* ERROR: Read failed! */ + dk3app_log_i1(app, DK3_LL_ERROR, 124); + dk3sf_report_errno(app, errno, dk3sf_function_names[14]); + } + } $? ". read() -" +#else +#if DK3_HAVE__READ + ssize_t rb = 0; /* Number of bytes read. */ + $? ". _read() +" + rb = _read(fd, buf, s); + if(rb >= (ssize_t)0) { + back = (size_t)rb; + } else { + if(app) { + /* ERROR: Read failed! */ + dk3app_log_i1(app, DK3_LL_ERROR, 124); + dk3sf_report_errno(app, errno, dk3sf_function_names[15]); + } + } $? ". _read() -" +#else +#error "No read() function available!" +#endif +#endif + $? ". non-Windows -" +#endif + } $? "- dk3sf_read_app %u", (unsigned)back + return back; +} + + + +int +dk3sf_write_app(int fd, char const *buf, size_t s, dk3_app_t *app) +{ + int back = 0; + if((buf) && (s)) { +#if DK3_ON_WINDOWS + int wb; + wb = _write(fd, buf, (unsigned int)s); + if(wb >= 0) { + if((size_t)wb == s) { + back = 1; + } else { + if(app) { + /* ERROR: Not all bytes written! */ + dk3app_log_write_error(app, DK3_LL_ERROR, s, wb); + } + } + } else { + if(app) { + /* ERROR: Write failed! */ + dk3app_log_i1( app, DK3_LL_ERROR, 173); + } + } +#else +#if DK3_HAVE_WRITE + ssize_t wb; + wb = write(fd, buf, s); + if(wb >= 0) { + if((size_t)wb == s) { + back = 1; + } else { + if(app) { + /* ERROR: Not all bytes written! */ + dk3app_log_write_error(app, DK3_LL_ERROR, s, wb); + } + } + } else { + if(app) { + /* ERROR: Write failed! */ + dk3app_log_i1(app, DK3_LL_ERROR, 173); + dk3sf_report_errno(app, errno, dk3sf_function_names[16]); + } + } +#else +#if DK3_HAVE__WRITE + ssize_t wb; + wb = _write(fd, buf, s); + if(wb >= 0) { + if((size_t)wb == s) { + back = 1; + } else { + if(app) { + /* ERROR: Not all bytes written! */ + dk3app_log_write_error(app, DK3_LL_ERROR, s, wb); + } + } + } else { + if(app) { + /* ERROR: Write failed! */ + dk3app_log_i1(app, DK3_LL_ERROR, 173); + dk3sf_report_errno(app, errno, dk3sf_function_names[17]); + } + } +#else +#error "No write() function available!" +#endif +#endif +#endif + } + return back; +} + + +size_t +dk3sf_fread_app(void *db, size_t sz, size_t ne, FILE *fi, dk3_app_t *app) +{ + size_t back = 0; + if((db) && (sz) && (ne) && (fi)) { +#if DK3_ON_WINDOWS + back = fread(db, sz, ne, fi); + if(back < ne) { + if(ferror(fi)) { + if(app) { + dk3app_log_i1(app, DK3_LL_ERROR, 124); + } + } + clearerr(fi); + } +#else +#if DK3_HAVE_FREAD + back = fread(db, sz, ne, fi); + if(back < ne) { + if(ferror(fi)) { + if(app) { + dk3app_log_i1(app, DK3_LL_ERROR, 124); + dk3sf_report_errno(app, errno, dk3sf_function_names[18]); + } + } clearerr(fi); + } +#else +#if DK3_HAVE__FREAD + back = _fread(db, sz, ne, fi); + if(back < ne) { + if(ferror(fi)) { + if(app) { + dk3app_log_i1(app, DK3_LL_ERROR, 124); + dk3sf_report_errno(app, errno, dk3sf_function_names[19]); + } + } clearerr(fi); + } +#else +#error "No fread() function available!" +#endif +#endif +#endif + } + return back; +} + + + +int +dk3sf_fwrite_app(void const *sb, size_t sz, size_t ne, FILE *fi, dk3_app_t *app) +{ + int back = 0; + if((sb) && (sz) && (ne) && (fi)) { +#if DK3_ON_WINDOWS + size_t wb; + wb = fwrite(sb, sz, ne, fi); + if(wb == ne) { + back = 1; + } else { + if(app) { + dk3app_log_fwrite_error(app, DK3_LL_ERROR, ne, wb); + } + } +#else +#if DK3_HAVE_FWRITE + size_t wb; + wb = fwrite(sb, sz, ne, fi); + if(wb == ne) { + back = 1; + } else { + if(app) { + dk3app_log_fwrite_error(app, DK3_LL_ERROR, ne, wb); + dk3sf_report_errno(app, errno, dk3sf_function_names[20]); + } + } +#else +#if DK3_HAVE__FWRITE + size_t wb; + wb = _fwrite(sb, sz, ne, fi); + if(wb == ne) { + back = 1; + } else { + if(app) { + dk3app_log_fwrite_error(app, DK3_LL_ERROR, ne, wb); + dk3sf_report_errno(app, errno, dk3sf_function_names[21]); + } + } +#else +#error "No fwrite() function available!" +#endif +#endif +#endif + } + return back; +} + + + +int +dk3sf_inspect_bom_skip_app( + dkChar const *fn, + int dv, + size_t *skb, + dk3_app_t *app +) +{ + int back = -1; + int found = 0; /* Flag: Any form of BOM found .*/ + FILE *fipo = NULL; /* Input file. */ + unsigned char bb[4]; /* Buffer for BOM. */ + size_t rb = 0; /* Number of bytes read. */ + $? "+ dk3sf_inspect_bom_app %d", dv + if(skb) { *skb = 0; } + back = dv; + if(fn) { + fipo = dk3sf_fopen_app(fn, dk3app_not_localized(36), app); + if(fipo) { + rb = dk3sf_fread_app(bb, 1, 4, fipo, app); + /* Check UTF-8 */ + if(rb >= 3) { + if((bb[0] == 0xEF) && (bb[1] == 0xBB) && (bb[2] == 0xBF)) { + found = 1; back = DK3_FILE_ENCODING_UTF8; $? ". UTF-8" + if(skb) { *skb = 3; } + } + } + if(!found) { + if(rb >= 2) { + if((bb[0] == 0xFE) && (bb[1] == 0xFF)) { + found = 1; back = DK3_FILE_ENCODING_UTF16_MSB_FIRST; $? ". U16 M" + if(skb) { *skb = 2; } + } else { + if((bb[0] == 0xFF) && (bb[1] == 0xFE)) { + found = 1; back = DK3_FILE_ENCODING_UTF16_LSB_FIRST; $? ". U16 L" + if(skb) { *skb = 2; } + if(rb >= 4) { + if((bb[2] == 0x00) && (bb[3] == 0x00)) { + back = DK3_FILE_ENCODING_UNICODE_LSB_FIRST; $? ". U32 L" + if(skb) { *skb = 4; } + } + } + } + } + } + } + if(!found) { + if(rb >= 4) { + if((bb[0] == 0x00) && (bb[1] == 0x00) + && (bb[2] == 0xFE) && (bb[3] == 0xFF) + ) + { + found = 1; back = DK3_FILE_ENCODING_UNICODE_MSB_FIRST; $? ". U32 M" + if(skb) { *skb = 4; } + } + } + } + if(!found) { + /* No BOM found */ + back = dv; + } + fclose(fipo); + } + } $? "- dk3sf_inspect_bom_app %d", back + return back; +} + + + +int +dk3sf_inspect_bom_app(dkChar const *fn, int dv, dk3_app_t *app) +{ + int back; + back = dk3sf_inspect_bom_skip_app(fn, dv, NULL, app); + return back; +} + + + +int +dk3sf_apply_bom_to_file_app(FILE *fipo, int enc, dk3_app_t *app) +{ + int back = 0; + $? "+ dk3sf_apply_bom_to_file_app" +#if DK3_ON_WINDOWS + if(fipo) { + switch(enc) { + case DK3_FILE_ENCODING_ASCII: { + back = 1; $? ". keep default" + } break; + case DK3_FILE_ENCODING_UTF8: { + back = 1; + _setmode(_fileno(fipo), _O_U8TEXT); $? ". 8" + } break; + case DK3_FILE_ENCODING_UTF16_LSB_FIRST: { + _setmode(_fileno(fipo), _O_U16TEXT); $? ". 16 L" + } break; + default: { + /* ERROR: Encoding can not be handled directly by file! */ + dk3app_log_i1(app, DK3_LL_ERROR, 204); + } break; + } + } +#else + if(fipo) { + switch(enc) { + case DK3_FILE_ENCODING_ASCII: case DK3_FILE_ENCODING_UTF8: { + back = 1; $? ". 8-bit, ok" + } break; + default: { + /* ERROR: Encoding can not be handled direcly by file! */ + dk3app_log_i1(app, DK3_LL_ERROR, 204); + } break; + } + } +#endif + $? "- dk3sf_apply_bom_to_file_app %d", back + return back; +} + + + +int +dk3sf_is_dir_app(dkChar const *n, dk3_app_t *app) +{ + int back = 0; + dk3_stat_t stb; + if(dk3sf_stat_app(&stb, n, app)) { + if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) { + back = 1; + } else { + if(app) { + /* ERROR: n is not a directory! */ + dk3app_log_i3(app, DK3_LL_ERROR, 202, 203, n); + } + } + } + return back; +} + + + +int +dk3sf_chdir_app(dkChar const *dn, dk3_app_t *app) +{ + int back = 0; + if(dn) { +#if DK3_CHAR_SIZE > 1 +#if DK3_ON_WINDOWS + if(_wchdir(dn) == 0) { + back = 1; + } else { + if(app) { + dk3app_log_i3(app, DK3_LL_ERROR, 242, 243, dn); + } + } +#else +#error "No chdir() function (16-bit) on non-Windows systems!" +#endif +#else +#if DK3_ON_WINDOWS + if(chdir(dn) == 0) { + back = 1; + } else { + if(app) { + dk3app_log_i3(app, DK3_LL_ERROR, 242, 243, dn); + } + } +#else +#if DK3_HAVE_CHDIR + if(chdir(dn) == 0) { + back = 1; + } else { + if(app) { + dk3app_log_i3(app, DK3_LL_ERROR, 242, 243, dn); + dk3sf_report_errno(app, errno, dk3sf_function_names[22]); + } + } +#else +#error "No chdir() function available!" +#endif +#endif +#endif + } + return back; +} + + + +int +dk3sf_must_rebuild(dkChar const *dn, dkChar const *sn) +{ + int back = 1; + dk3_stat_t stbs; + dk3_stat_t stbd; + if((dn) && (sn)) { + if(dk3sf_stat_app(&stbd, dn, NULL)) { + if(dk3sf_stat_app(&stbs, sn, NULL)) { + if(stbd.mod > stbs.mod) { + back = 0; + } + } + } + } + return back; +} + + + +int +dk3sf_filename_to_c8( + char *fnb, size_t szfnb, dkChar const *src, dk3_app_t *app +) +{ + int back = 0; + if((fnb) && (szfnb) && (src)) { +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "Only 1- or 2-byte character support available!" +#else +#if DK3_ON_WINDOWS + back = dk3str_cnv_c16_to_c8p_app(fnb, szfnb, src, app); +#else +#error "2-byte character support is available on Windows platforms only!" +#endif +#endif +#else + if(dk3str_len(src) < szfnb) { + dk3str_cpy_not_overlapped(fnb, src); + back = 1; + } else { + /* ERROR: File name too long! */ + if(app) { + dk3app_log_i3(app, DK3_LL_ERROR, 65, 66, src); + } + } +#endif + } + return back; +} + + + +int +dk3sf_scan_double_app(dkChar const *txt, double *v, dk3_app_t *app) +{ + int back = 0; + $? "+ dk3sf_scan_double" + if((txt) && (v)) { $? ". args ok" +#if DK3_HAVE_SETLOCALE + char oldlocale[64]; + char *lcptr; + + lcptr = setlocale(LC_NUMERIC, NULL); $? ". have setlocale" + if(lcptr) { $? ". setlocale (1) ok" + if(dk3str_c8_len(lcptr) < sizeof(oldlocale)) { $? ". length ok" + dk3str_c8_cpy_not_overlapped(oldlocale, lcptr); + setlocale(LC_NUMERIC, "C"); +#if VERSION_BEFORE_20140716 + back = dk3sf_sscanf3(txt,dkT("%lf"),v); +#else + back = dk3ma_d_from_string(v, txt, NULL); +#endif + setlocale(LC_NUMERIC, oldlocale); + } else { $? "! too long" +#if VERSION_BEFORE_20140716 + dk3sf_sscanf3(txt,dkT("%lf"),v); +#else + back = dk3ma_d_from_string(v, txt, NULL); +#endif + if(app) { + /* ERROR: Failed to save current locale! */ + dk3app_log_i1(app, DK3_LL_ERROR, 254); + } + } + } else { $? "! setlocale (1)" +#if VERSION_BEFORE_20140716 + dk3sf_sscanf3(txt,dkT("%lf"),v); +#else + back = dk3ma_d_from_string(v, txt, NULL); +#endif + if(app) { + /* ERROR: Failed to obtain current locale! */ + dk3app_log_i1(app, DK3_LL_ERROR, 253); + } + } +#else +#if VERSION_BEFORE_20140716 + back = dk3sf_sscanf3(txt,dkT("%lf"),v); $? ". no setlocale" +#else + back = dk3ma_d_from_string(v, txt, NULL); +#endif +#endif + } $? "- dk3sf_scan_double %d", back + return back; +} + + + +int +dk3sf_get_max_files(void) +{ + int back = 1024; +#if DK3_HAVE_SYS_RESOURCE_H +#if DK3_HAVE_GETRLIMIT + struct rlimit rl; + if(getrlimit(RLIMIT_NOFILE, &rl) >= 0) { + if(rl.rlim_max != RLIM_INFINITY) { + back = rl.rlim_max; + } + } +#endif +#endif + return back; +} + + + + +int +dk3sf_fclose_fn_app(FILE *fipo, dkChar const *fn, dk3_app_t *app) +{ + int back = 0; + int res; + if(fipo) { + res = fclose(fipo); + if(0 == res) { + back = 1; + } else { + if(fn) { + dk3app_log_i3(app, DK3_LL_ERROR, 341, 342, fn); + } else { + dk3app_log_i1(app, DK3_LL_ERROR, 340); + } + dk3sf_report_errno(app, errno, dk3sf_function_names[1]); + } + } + return back; +} + + + +int +dk3sf_fclose_app(FILE *fipo, dk3_app_t *app) +{ + int back = 0; + back = dk3sf_fclose_fn_app(fipo, NULL, app); + return back; +} + + + +int +dk3sf_fgets(dkChar *db, size_t sz, FILE *fi) +{ + int back; + back = dk3sf_fgets_fn_app(db, sz, fi, NULL, NULL); + return back; +} + + + +int +dk3sf_fputs(dkChar const *st, FILE *fi) +{ + int back; + back = dk3sf_fputs_fn_app(st, fi, NULL, NULL); + return back; +} + + + +int +dk3sf_fputt(dkChar const * const *txt, FILE *fi) +{ + dkChar const * const *ptr; + int back = 0; + if((txt) && (fi)) { + back = 1; + ptr = txt; + while(*ptr) { + if(!(dk3sf_fputs(*(ptr++), fi))) { + back = 0; + } + dk3sf_fputc(dkT('\n'), fi); + } + } + return back; +} + + +int +dk3sf_fputc(dkChar c, FILE *fi) +{ + int back; + back = dk3sf_fputc_fn_app(c, fi, NULL, NULL); + return back; +} + + + +int +dk3sf_stat_app(dk3_stat_t *st, dkChar const *fn, dk3_app_t *app) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_stat_app(st, fn, app)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_stat_app(st, fn, app)); +#endif +} + + + +FILE * +dk3sf_fopen_app(dkChar const *fn, dkChar const *mo, dk3_app_t *app) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_fopen_app(fn, mo, app)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_fopen_app(fn, mo, app)); +#endif +} + + + +int +dk3sf_time_convert_app( + dkChar *dest, + size_t sz, + dk3_time_t const *timer, + dk3_app_t *app +) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_time_convert_app(dest, sz, timer, app)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_time_convert_app(dest, sz, timer, app)); +#endif +} + + + +int +dk3sf_getcwd_app(dkChar *dest, size_t sz, dk3_app_t *app) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_getcwd_app(dest, sz, app)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_getcwd_app(dest, sz, app)); +#endif +} + + + +int +dk3sf_find_exec_app( + dkChar *d, + size_t s, + dkChar const *w, + dkChar const *c, + dk3_app_t *app +) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_find_exec_app(d, s, w, c, app)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_find_exec_app(d, s, w, c, app)); +#endif +} + + + +int +dk3sf_get_logname_app(dkChar *d, size_t s, dk3_app_t *app) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_get_logname_app(d, s, app)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_get_logname_app(d, s, app)); +#endif +} + + + +int +dk3sf_get_home_app(dkChar *d, size_t s, dk3_app_t *app) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_get_home_app(d, s, app)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_get_home_app(d, s, app)); +#endif +} + + + +int +dk3sf_mkdir_app(dkChar const *p, int mo, dk3_app_t *app) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_mkdir_app(p, mo, app)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_mkdir_app(p, mo, app)); +#endif +} + + + +int +dk3sf_remove_file_app(dkChar const *n, dk3_app_t *app) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_remove_file_app(n, app)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_remove_file_app(n, app)); +#endif +} + + + +int +dk3sf_remove_dir_app(dkChar const *n, dk3_app_t *app) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_remove_dir_app(n, app)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_remove_dir_app(n, app)); +#endif +} + + + +int +dk3sf_get_hostname_app(dkChar *db, size_t sz, dk3_app_t *app) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_get_hostname_app(db, sz, app)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_get_hostname_app(db, sz, app)); +#endif +} + + + +dkChar * +dk3sf_getenv(dkChar const *name) +{ +#if DK3_CHAR_SIZE > 1 +#if DK3_CHAR_SIZE > 2 +#error "System function for b-byte character strings not available!" +#else +#if DK3_ON_WINDOWS + return(dk3sf_c16_getenv(name)); +#else +#error "Wide character functions not defined on non-Windows systems!" +#endif +#endif +#else + return(dk3sf_c8_getenv(name)); +#endif +} + + + + +/* vim: set ai sw=2 : */ + |