1 /*
2 Copyright (C) 2011-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5 
6 /*
7 	WARNING: This file was generated by the dkct program (see
8 	http://dktools.sourceforge.net/ for details).
9 	Changes you make here will be lost if dkct is run again!
10 	You should modify the original source and run dkct on it.
11 	Original source: dk3sf.ctr
12 */
13 
14 /**	@file dk3sf.c The dk3sf module.
15 */
16 
17 
18 #include <libdk3c/dk3all.h>
19 #include <libdk3c/dk3unused.h>
20 
21 
22 
23 
24 
25 
26 
27 
28 #if DK3_ON_WINDOWS || DK3_HAVE_BACKSLASH
29 
30 /**	File path component separator.
31 */
32 #define	DK3_C8_SEP	'\\'
33 
34 /**	Not a file path component separator.
35 */
36 #define	DK3_C8_NOSEP	'/'
37 
38 #else
39 
40 /**	File path component separator.
41 */
42 #define	DK3_C8_SEP	'/'
43 
44 /**	Not a file path component separator.
45 */
46 #define	DK3_C8_NOSEP	'\\'
47 
48 #endif
49 
50 
51 
52 /**	Add bit to set after testing another bit.
53 */
54 #define DK3SF_ADDIF(a,b) if(m & a) { back |= b; }
55 
56 
57 
58 /**	Function names used in error messages.
59 */
60 dkChar const * const	dk3sf_function_names[] = {
61 /* 0 */
62 dkT(""),
63 
64 /* 1 */
65 dkT("fclose: "),
66 
67 /* 2 */
68 dkT("rmdir: "),
69 
70 /* 3 */
71 dkT("unlink: "),
72 
73 /* 4 */
74 dkT("getpwuid: "),
75 
76 /* 5 */
77 dkT("lstat64: "),
78 
79 /* 6 */
80 dkT("stat64: "),
81 
82 /* 7 */
83 dkT("stat: "),
84 
85 /* 8 */
86 dkT("lstat: "),
87 
88 /* 9 */
89 dkT("fopen: "),
90 
91 /* 10 */
92 dkT("localtime_r: "),
93 
94 /* 11 */
95 dkT("getcwd: "),
96 
97 /* 12 */
98 dkT("mkdir: "),
99 
100 /* 13 */
101 dkT("gethostname: "),
102 
103 /* 14 */
104 dkT("read: "),
105 
106 /* 15 */
107 dkT("_read: "),
108 
109 /* 16 */
110 dkT("write: "),
111 
112 /* 17 */
113 dkT("_write: "),
114 
115 /* 18 */
116 dkT("fread: "),
117 
118 /* 19 */
119 dkT("_fread: "),
120 
121 /* 20 */
122 dkT("fwrite: "),
123 
124 /* 21 */
125 dkT("_fwrite: "),
126 
127 /* 22 */
128 dkT("chdir: "),
129 
130 /* 23 */
131 dkT("fputs: "),
132 
133 /* 24 */
134 dkT("fputc: "),
135 
136 /* 25 */
137 dkT("fgets: "),
138 
139 NULL
140 
141 };
142 
143 
144 
145 void
146 #if (DK3_CHAR_SIZE == 1) && DK3_HAVE_STRERROR && (!DK3_ON_WINDOWS)
dk3sf_report_errno(dk3_app_t * app,int err,dkChar const * fctn)147 dk3sf_report_errno(dk3_app_t *app, int err, dkChar const *fctn)
148 #else
149 dk3sf_report_errno(
150 	dk3_app_t * DK3_ARG_UNUSED(app),
151 	int DK3_ARG_UNUSED(err),
152 	dkChar const * DK3_ARG_UNUSED(fctn)
153 )
154 #endif
155 {
156 #if (DK3_CHAR_SIZE == 1) && DK3_HAVE_STRERROR && (!DK3_ON_WINDOWS)
157   dkChar const	*msgarray[2];
158 #if DK3_HAVE_GETENV && DK3_HAVE_SETLOCALE
159   char const	*oldlocale = NULL;
160   char const	*langptr = NULL;
161 #endif
162   if((app) && (fctn)) {
163     msgarray[0] = fctn;
164     errno = 0;
165 #if DK3_HAVE_GETENV && DK3_HAVE_SETLOCALE
166     langptr = getenv("LANG");
167     if(langptr) {
168       oldlocale = setlocale(LC_MESSAGES, langptr);
169     }
170 #endif
171     msgarray[1] = strerror(err);
172     if(0 == errno) {
173       dk3app_log_3(app, DK3_LL_ERROR, msgarray, 0, 1, dk3sf_function_names[0]);
174     }
175 #if DK3_HAVE_GETENV && DK3_HAVE_SETLOCALE
176     if(langptr) {
177       if(oldlocale) { setlocale(LC_MESSAGES, oldlocale); }
178     }
179 #endif
180   }
181 #else
182   DK3_UNUSED_ARG(app)
183   DK3_UNUSED_ARG(err)
184   DK3_UNUSED_ARG(fctn)
185 #endif
186 }
187 
188 
189 
190 
191 #if DK3_ON_WINDOWS
192 /* +++ Windows +++ */
193 
194 
195 
196 /**	Unlocalized 8-bit character keywords used by module.
197 */
198 static char const * const dk3sf_kw_win_c8[] = {
199 /*  0 */ "HOMEDRIVE",
200 /*  1 */ "HOMEPATH",
201 /*  2 */ "USERPROFILE",
202 /*  3 */ "LOCALAPPDATA",
203 /*  4 */ "\\AppData\\Local",
204 /*  5 */ "APPDATA",
205 /*  6 */ "\\AppData\\Roaming",
206 /*  7 */ "TEMP",
207 /*  8 */ "TMP",
208 /*  9 */ "\\AppData\\Local\\Temp",
209 NULL
210 };
211 
212 
213 
214 /**	Unlocalized 16-bit character keywords used by module.
215 */
216 static wchar_t const * const dk3sf_kw_win_c16[] = {
217 /*  0 */ L"HOMEDRIVE",
218 /*  1 */ L"HOMEPATH",
219 /*  2 */ L"USERPROFILE",
220 /*  3 */ L"LOCALAPPDATA",
221 /*  4 */ L"\\AppData\\Local",
222 /*  5 */ L"APPDATA",
223 /*  6 */ L"\\AppData\\Roaming",
224 /*  7 */ L"TEMP",
225 /*  8 */ L"TMP",
226 /*  9 */ L"\\AppData\\Local\\Temp",
227 NULL
228 };
229 
230 
231 
232 dk3_um_t
dk3sf_getpid(void)233 dk3sf_getpid(void)
234 {
235   dk3_um_t back;
236   back = (dk3_um_t)_getpid();
237   return back;
238 }
239 
240 
241 
242 dk3_c16_t *
dk3sf_c16_getenv(dk3_c16_t const * name)243 dk3sf_c16_getenv(dk3_c16_t const *name)
244 {
245   dk3_c16_t *back = NULL;
246   if(name) {
247     back = _wgetenv(name);
248   }
249   return back;
250 }
251 
252 
253 dk3_c8_t *
dk3sf_c8_getenv(char const * name)254 dk3sf_c8_getenv(char const *name)
255 {
256   char *back = NULL;
257   if(name) {
258     back = getenv(name);
259   }
260   return back;
261 }
262 
263 
264 int
dk3sf_c16_remove_dir_app(dk3_c16_t const * n,dk3_app_t * app)265 dk3sf_c16_remove_dir_app(dk3_c16_t const *n, dk3_app_t *app)
266 {
267   int back = 0;
268   if(n) {
269     if(_wrmdir(n) == 0) {
270       back = 1;
271     } else {
272       if(app) {
273         /* Failed to remove directory! */
274 #if DK3_CHAR_SIZE == 2
275 	dk3app_log_i3(app, DK3_LL_ERROR, 69, 70, n);
276 #else
277 	dk3app_log_i1(app, DK3_LL_ERROR, 68);
278 #endif
279       }
280     }
281   }
282   return back;
283 }
284 
285 
286 
287 int
dk3sf_c8_remove_dir_app(char const * n,dk3_app_t * app)288 dk3sf_c8_remove_dir_app(char const *n, dk3_app_t *app)
289 {
290   int back = 0;
291   if(n) {
292     if(_rmdir(n) == 0) {
293       back = 1;
294     } else {
295       if(app) {
296         /* Failed to remove directory! */
297 #if DK3_CHAR_SIZE == 1
298 	dk3app_log_i3(app, DK3_LL_ERROR, 69, 70, n);
299 #else
300 	dk3app_log_i1(app, DK3_LL_ERROR, 68);
301 #endif
302       }
303     }
304   }
305   return back;
306 }
307 
308 
309 int
dk3sf_c16_remove_file_app(dk3_c16_t const * n,dk3_app_t * app)310 dk3sf_c16_remove_file_app(dk3_c16_t const *n, dk3_app_t *app)
311 {
312   int back = 0;
313   if(n) {
314     if(_wunlink(n) == 0) {
315       back = 1;
316     } else {
317       if(app) {
318         /* Failed to remove file! */
319 #if DK3_CHAR_SIZE == 2
320 	dk3app_log_i3(app, DK3_LL_ERROR, 88, 89, n);
321 #else
322 	dk3app_log_i1(app, DK3_LL_ERROR, 90);
323 #endif
324       }
325     }
326   }
327   return back;
328 }
329 
330 
331 int
dk3sf_c8_remove_file_app(char const * n,dk3_app_t * app)332 dk3sf_c8_remove_file_app(char const *n, dk3_app_t *app)
333 {
334   int back = 0;
335   if(n) {
336     if(_unlink(n) == 0) {
337       back = 1;
338     } else {
339       if(app) {
340         /* ERROR: Failed to remove file! */
341 #if	DK3_CHAR_SIZE	== 1
342 	dk3app_log_i3(app, DK3_LL_ERROR, 88, 89, n);
343 #else
344 	dk3app_log_i1(app, DK3_LL_ERROR, 90);
345 #endif
346       }
347     }
348   }
349   return back;
350 }
351 
352 
353 /**	Attempt to retrieve home directory name.
354 	@param	d	Destination buffer.
355 	@param	sz	Size of \a d (number of characters).
356 	@param	n1	Name of first environment variable to check.
357 	@param	n2	Name of second environment variable to check.
358 	@param	n3	Trailing string to remove if found.
359 	@return	1 on success, 0 on error.
360 */
361 static
362 int
dk3sf_c8_attempt_home(char * d,size_t sz,char const * n1,char const * n2,char const * n3)363 dk3sf_c8_attempt_home(
364   char *d, size_t sz, char const *n1, char const *n2, char const *n3
365 )
366 {
367   int back = 0;
368   char *p1 = NULL;	/* Value of first environment variable. */
369   char *p2 = NULL;	/* Value of second environment variable. */
370   size_t s = 0;		/* Buffer size needed. */
371   size_t s2 = 0;	/* Size of trailing part to remove. */
372   p2 = NULL;
373 
374   p1 = getenv(n1);
375   if(p1) {
376     if(n2) { p2 = getenv(n2); }
377     if((p2) || (!(n2))) {
378       s = dk3str_c8_len(p1);
379       if(p2) { s += dk3str_c8_len(p2); }
380       if(s < sz) {
381         dk3str_c8_cpy_not_overlapped(d, p1);
382 	if(p2) { dk3str_c8_cat(d, p2); }
383 	if(n3) {
384 	  s2 = dk3str_c8_len(n3);
385 	  if(s2 < 2) {
386 	    if(dk3str_c8_casecmp(&(d[s - s2]), n3) == 0) {
387 	      d[s - s2] = '\0';
388 	      back = 1;
389 	    }
390 	  }
391 	} else {
392 	  back = 1;
393 	}
394       }
395     }
396 
397 
398 
399   }
400   return back;
401 }
402 
403 
404 int
dk3sf_c8_get_home_app(char * d,size_t s,dk3_app_t * DK3_ARG_UNUSED (app))405 dk3sf_c8_get_home_app(char *d, size_t s, dk3_app_t * DK3_ARG_UNUSED(app))
406 {
407   int back = 0;
408   DK3_UNUSED_ARG(app)
409   if((d) && (s)) {
410     back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[0], dk3sf_kw_win_c8[1], NULL);
411     if(!back) {
412       back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[2], NULL, NULL);
413     }
414     if(!back) {
415       back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[3], NULL, dk3sf_kw_win_c8[4]);
416     }
417     if(!back) {
418       back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[5], NULL, dk3sf_kw_win_c8[6]);
419     }
420     if(!back) {
421       back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[7], NULL, dk3sf_kw_win_c8[9]);
422     }
423     if(!back) {
424       back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[8], NULL, dk3sf_kw_win_c8[9]);
425     }
426     if(!back) {
427       back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[3], NULL, NULL);
428     }
429     if(!back) {
430       back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[5], NULL, NULL);
431     }
432     if(!back) {
433       back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[7], NULL, NULL);
434     }
435     if(!back) {
436       back = dk3sf_c8_attempt_home(d, s, dk3sf_kw_win_c8[8], NULL, NULL);
437     }
438 
439 
440 
441   }
442   return back;
443 }
444 
445 
446 
447 /**	Attempt to retrieve home directory name.
448 	@param	d	Destination buffer.
449 	@param	sz	Size of \a d (number of characters).
450 	@param	n1	Name of first environment variable to check.
451 	@param	n2	Name of second environment variable to check.
452 	@param	n3	Trailing string to remove if found.
453 	@return	1 on success, 0 on error.
454 */
455 static
456 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)457 dk3sf_c16_attempt_home(
458   dk3_c16_t *d, size_t sz,
459   dk3_c16_t const *n1, dk3_c16_t const *n2, dk3_c16_t const *n3
460 )
461 {
462   int back = 0;
463   dk3_c16_t *p1 = NULL;	/* Value of first environment variable. */
464   dk3_c16_t *p2 = NULL;	/* Value of second environment variable. */
465   size_t s = 0;		/* Buffer size needed. */
466   size_t s2 = 0;	/* Size of trailing text to remove. */
467   p2 = NULL;
468 
469   p1 = _wgetenv(n1);
470   if(p1) {
471     if(n2) { p2 = _wgetenv(n2); }
472     if((p2) || (!(n2))) {
473       s = dk3str_c16_len(p1);
474       if(p2) { s += dk3str_c16_len(p2); }
475       if(s < sz) {
476         dk3str_c16_cpy(d, p1);
477 	if(p2) { dk3str_c16_cat(d, p2); }
478 	if(n3) {
479 	  s2 = dk3str_c16_len(n3);
480 	  if(s2 < 2) {
481 	    if(dk3str_c16_casecmp(&(d[s - s2]), n3) == 0) {
482 	      d[s - s2] = 0x0000U;
483 	      back = 1;
484 	    }
485 	  }
486 	} else {
487 	  back = 1;
488 	}
489       }
490     }
491 
492 
493 
494   }
495   return back;
496 }
497 
498 
499 
500 int
dk3sf_c16_get_home_app(dk3_c16_t * d,size_t s,dk3_app_t * DK3_ARG_UNUSED (app))501 dk3sf_c16_get_home_app(dk3_c16_t *d, size_t s, dk3_app_t * DK3_ARG_UNUSED(app))
502 {
503   int back = 0;
504   DK3_UNUSED_ARG(app)
505   if((d) && (s)) {
506     back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[0], dk3sf_kw_win_c16[1], NULL);
507     if(!back) {
508       back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[2], NULL, NULL);
509     }
510     if(!back) {
511       back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[3], NULL, dk3sf_kw_win_c16[4]);
512     }
513     if(!back) {
514       back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[5], NULL, dk3sf_kw_win_c16[6]);
515     }
516     if(!back) {
517       back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[7], NULL, dk3sf_kw_win_c16[9]);
518     }
519     if(!back) {
520       back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[8], NULL, dk3sf_kw_win_c16[9]);
521     }
522     if(!back) {
523       back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[3], NULL, NULL);
524     }
525     if(!back) {
526       back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[5], NULL, NULL);
527     }
528     if(!back) {
529       back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[7], NULL, NULL);
530     }
531     if(!back) {
532       back = dk3sf_c16_attempt_home(d, s, dk3sf_kw_win_c16[8], NULL, NULL);
533     }
534 
535 
536 
537   }
538   return back;
539 }
540 
541 
542 int
dk3sf_c8_get_logname_app(char * d,size_t s,dk3_app_t * app)543 dk3sf_c8_get_logname_app(char *d, size_t s, dk3_app_t *app)
544 {
545   int		back = 0;
546   DWORD		sz = 0;		/* Buffer size / Result length. */
547   sz = (DWORD)s;
548   if((d) && (s)) {
549     if(GetUserNameA(d, &sz)) {
550       if(sz) {
551 	d[((size_t)sz < s) ? ((size_t)sz) : (s - 1)] = '\0';
552 	back = 1;
553       }
554     } else {
555       if(app) {
556         /* Failed to find current user name */
557 	dk3app_log_i1(app, DK3_LL_ERROR, 43);
558       }
559     }
560   }
561   return back;
562 }
563 
564 
565 
566 int
dk3sf_c16_get_logname_app(dk3_c16_t * d,size_t s,dk3_app_t * app)567 dk3sf_c16_get_logname_app(dk3_c16_t *d, size_t s, dk3_app_t *app)
568 {
569   int		back = 0;
570   DWORD		sz = 0;		/* Buffer size / result length. */
571   if((d) && (s)) {
572     sz = (DWORD)s;
573     if(GetUserNameW(d, &sz)) {
574       if(sz) {
575         d[((size_t)sz < s) ? ((size_t)sz) : (s - 1)] = 0U;
576         back = 1;
577       }
578     } else {
579       if(app) {
580         /* Failed to find current user name */
581 	dk3app_log_i1(app, DK3_LL_ERROR, 43);
582       }
583     }
584   }
585   return back;
586 }
587 
588 
589 int
dk3sf_time(dk3_time_t * timer)590 dk3sf_time(dk3_time_t *timer)
591 {
592   int back = 1;
593   _time64(timer);
594   return back;
595 }
596 
597 
598 
599 static
600 int
dk3sf_convert_file_type(int m)601 dk3sf_convert_file_type(int m)
602 {
603   int back = 0;
604   switch(m & _S_IFMT) {
605 #ifdef _S_IFIFO
606     case _S_IFIFO: back = DK3_FT_FIFO; break;
607 #endif
608 #ifdef _S_IFCHR
609     case _S_IFCHR: back = DK3_FT_SPECIAL_CHAR; break;
610 #endif
611 #ifdef _S_IFDIR
612     case _S_IFDIR: back = DK3_FT_DIRECTORY; break;
613 #endif
614 #ifdef _S_IFBLK
615     case _S_IFBLK: back = DK3_FT_SPECIAL_BLOCK; break;
616 #endif
617 #ifdef _S_IFREG
618     case _S_IFREG: back = DK3_FT_REGULAR; break;
619 #endif
620   }
621   return back;
622 }
623 
624 
625 
626 static
627 int
dk3sf_convert_file_permissions(int m)628 dk3sf_convert_file_permissions(int m)
629 {
630   int back = 0;
631   DK3SF_ADDIF(_S_IREAD,DK3_FPERM_U_READ)
632   DK3SF_ADDIF(_S_IWRITE,DK3_FPERM_U_WRITE)
633   DK3SF_ADDIF(_S_IEXEC,DK3_FPERM_U_EXEC)
634   return back;
635 }
636 
637 
638 #if (1 == DK3_CHAR_SIZE) || (VERSION_BEFORE_2019_10_20)
639 
640 /**	Convert file permissions back from dktools to system values.
641 	@param	m	File permissions in dktools notation.
642 	@return	File permissions in system notation.
643 */
644 static
645 int
dk3sf_convert_back_file_permissions(int m)646 dk3sf_convert_back_file_permissions(int m)
647 {
648   int back  = 0;
649   DK3SF_ADDIF(DK3_FPERM_U_READ,S_IREAD)
650   DK3SF_ADDIF(DK3_FPERM_U_WRITE,S_IWRITE)
651   DK3SF_ADDIF(DK3_FPERM_U_EXEC,S_IEXEC)
652   return back;
653 }
654 
655 #endif
656 
657 
658 #if	VERSION_BEFORE_2012_04_14
659 
660 static
661 void
dk3sf_convert_filetime(dk3_time_t * pd,FILETIME * ps)662 dk3sf_convert_filetime(dk3_time_t *pd, FILETIME *ps)
663 {
664   __int64	i1;
665   __int64	i2;
666   i1 = (__int64)(ps->dwHighDateTime);
667   i2 = (__int64)(ps->dwLowDateTime);
668   i1 = ((i1 << 32) & 0xFFFFFFFF00000000UL) | (i2 & 0x00000000FFFFFFFFUL);
669   *pd = (dk3_time_t)i1;
670 }
671 
672 #endif
673 
674 
675 int
dk3sf_c8_stat_app(dk3_stat_t * st,char const * fn,dk3_app_t * app)676 dk3sf_c8_stat_app(dk3_stat_t *st, char const *fn, dk3_app_t *app)
677 {
678   WIN32_FIND_DATAA	wfd;
679   DWORD			dwFileAttributes;
680   HANDLE		hFFF;
681 #if	VERSION_BEFORE_2012_04_14
682   int			ec   = 0;
683 #endif
684   int			back = 0;
685   struct __stat64 stb;	/* Internal buffer for _stat64(). */
686 
687   if((st) && (fn)) {
688     dk3mem_res((void *)st, sizeof(dk3_stat_t));
689     st->cReparse = 0x00;
690     st->dwReparse = (DWORD)0;
691     if(_stat64(fn, &stb) == 0) {
692       back = 1;
693       st->u = (dk3_um_t)(stb.st_uid);
694       st->g = (dk3_um_t)(stb.st_gid);
695       st->device = (dk3_um_t)(stb.st_dev);
696       st->rdev = (dk3_um_t)(stb.st_rdev);
697       st->inode = (dk3_um_t)(stb.st_ino);
698       st->nlink = (dk3_um_t)(stb.st_nlink);
699       st->cre = (dk3_time_t)(stb.st_ctime);
700       st->mod = (dk3_time_t)(stb.st_mtime);
701       st->acc = (dk3_time_t)(stb.st_atime);
702       st->ft = dk3sf_convert_file_type(stb.st_mode);
703       st->perm = dk3sf_convert_file_permissions(stb.st_mode);
704       st->sz = (dk3_um_t)(stb.st_size);
705       st->lsz = st->sz;
706       st->ai = 0x00;
707       dk3mem_cpy((void *)(&(st->lcre)),  (void *)(&(st->cre)), sizeof(dk3_time_t));
708       dk3mem_cpy((void *)(&(st->lmod)),  (void *)(&(st->mod)), sizeof(dk3_time_t));
709       dk3mem_cpy((void *)(&(st->lacc)),  (void *)(&(st->acc)), sizeof(dk3_time_t));
710       st->lu = st->u;
711       st->lg = st->g;
712       st->ldevice = st->device;
713       st->lrdev = st->rdev;
714       st->linode = st->inode;
715       st->lnlink = st->nlink;
716       st->lft = st->ft;
717       st->lperm = st->perm;
718       st->lsz = st->sz;
719 #if VERSION_BEFORE_2012_04_14
720       if(DK3_FT_DIRECTORY == st->ft) {
721         WIN32_FIND_DATAA	wfdFileDetails;
722 	HANDLE			hFileSearch;
723 
724         hFileSearch = FindFirstFileA(fn, &wfdFileDetails);
725 	if(INVALID_HANDLE_VALUE != hFileSearch) {
726 	  if(FILE_ATTRIBUTE_REPARSE_POINT & (wfdFileDetails.dwFileAttributes)) {
727 	    if(IO_REPARSE_TAG_MOUNT_POINT == wfdFileDetails.dwReserved0) {
728 	      /* ##### st->ft = DK3_FT_WINDOWS_MOUNT_POINT; */
729 	    } else {
730 	      if(IO_REPARSE_TAG_SYMLINK == wfdFileDetails.dwReserved0) {
731 	        /* Symbolic link */
732 		st->lsz = dk3ma_um_add_ok(
733 		  dk3ma_um_mul_ok(
734 		    (dk3_um_t)(wfdFileDetails.nFileSizeHigh),
735 		    dk3ma_um_add_ok(
736 		      (dk3_um_t)(MAXDWORD),
737 		      DK3_UM_1,
738 		      &ec
739 		    ),
740 		    &ec
741 		  ),
742 		  (dk3_um_t)(wfdFileDetails.nFileSizeLow),
743 		  &ec
744 		);
745 		dk3sf_convert_filetime(&(st->lcre), &(wfdFileDetails.ftCreationTime));
746 		dk3sf_convert_filetime(&(st->lmod), &(wfdFileDetails.ftLastWriteTime));
747 		dk3sf_convert_filetime(&(st->lacc), &(wfdFileDetails.ftLastAccessTime));
748 		st->ft |= DK3_FT_SYMLINK;
749 	      } else {
750 	      }
751 	    }
752 	  }
753 	  FindClose(hFileSearch);
754 	}
755       }
756 #else
757       dwFileAttributes = GetFileAttributesA(fn);
758       if(INVALID_FILE_ATTRIBUTES != dwFileAttributes) {
759         if(dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
760 	  st->cReparse = 'r';
761 	  hFFF = FindFirstFileA(fn, &wfd);
762 	  if(INVALID_HANDLE_VALUE != hFFF) {
763 	    if((wfd.dwFileAttributes) & FILE_ATTRIBUTE_REPARSE_POINT) {
764 	      st->dwReparse = wfd.dwReserved0;
765 	      switch(wfd.dwReserved0) {
766 	        case IO_REPARSE_TAG_MOUNT_POINT: {
767 		  st->cReparse = 'm';
768 		} break;
769 		case IO_REPARSE_TAG_SYMLINK: {
770 		  st->cReparse = 'l';
771 		} break;
772 	      }
773 	    }
774 	    FindClose(hFFF);
775 	  }
776 	}
777       }
778 #endif
779     } else {
780       if(app) {
781         /* stat() failed! */
782 #if DK3_CHAR_SIZE == 1
783 	dk3app_log_i3(app, DK3_LL_ERROR, 61, 62, fn);
784 #else
785 	dk3app_log_i1(app, DK3_LL_ERROR, 73);
786 #endif
787       }
788     }
789   }
790   return back;
791 }
792 
793 
794 
795 /**	Check whether opening a file is allowed.
796 	@param	fn	File name.
797 	@param	want_to_write	Flag: Write access is wanted.
798 	@param	app	Application structure for diagnostics, may be NULL.
799 	@return	1 for write allowed, 0 for write denied.
800 */
801 static
802 int
dk3sf_c8_check_open_file(char const * fn,int want_to_write,dk3_app_t * app)803 dk3sf_c8_check_open_file(char const *fn, int want_to_write, dk3_app_t *app)
804 {
805   int		back = 1;
806   dk3_stat_t	stb;		/* Internal buffer for checks. */
807   if(dk3sf_c8_stat_app(&stb, fn, NULL)) {
808     if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) {
809       if(app) {
810         back = 0;
811         /* ERROR: Name refers a directory! */
812 #if DK3_CHAR_SIZE == 1
813 	dk3app_log_i3(app, DK3_LL_ERROR, 74, 75, fn);
814 #else
815 	dk3app_log_i1(app, DK3_LL_ERROR, 76);
816 #endif
817       }
818     }
819     if(want_to_write) {
820       /* Place for additional checks to write files here. */
821     }
822   }
823   return back;
824 }
825 
826 
827 
828 FILE *
dk3sf_c8_fopen_app(char const * fn,char const * mo,dk3_app_t * app)829 dk3sf_c8_fopen_app(char const *fn, char const *mo, dk3_app_t *app)
830 {
831   FILE		*back = NULL;
832   char const	*moptr = NULL;		/* Check mode string. */
833   int		want_to_write = 0;	/* Flag: Write access wanted. */
834 
835   if((fn) && (mo)) {
836     moptr = mo;
837     while(*moptr) {
838       switch(*moptr) {
839         case 'w': case 'a': case '+': { want_to_write = 1; } break;
840       }
841       moptr++;
842     }
843     if(dk3sf_c8_check_open_file(fn, want_to_write, app)) {
844       back = fopen(fn, mo);
845       if(!(back)) {
846         if(app) {
847 	  /* Failed to open file for writing! */
848 	  if(want_to_write) {
849 #if DK3_CHAR_SIZE == 1
850 	    dk3app_log_i3(app, DK3_LL_ERROR, 77, 78, fn);
851 #else
852 	    dk3app_log_i1(app, DK3_LL_ERROR, 79);
853 #endif
854           } else {
855 #if DK3_CHAR_SIZE == 1
856 	    dk3app_log_i3(app, DK3_LL_ERROR, 143, 144, fn);
857 #else
858 	    dk3app_log_i1(app, DK3_LL_ERROR, 145);
859 #endif
860 	  }
861 	}
862       }
863     }
864   }
865   return back;
866 }
867 
868 
869 
870 
871 int
dk3sf_localtime_app(dk3_tm_t * dest,dk3_time_t * timer,dk3_app_t * app)872 dk3sf_localtime_app(
873   dk3_tm_t	*dest,
874   dk3_time_t	*timer,
875   dk3_app_t	*app
876 )
877 {
878   int			 back = 0;
879   struct tm		 res;
880   if((dest) && (timer)) {
881     if(0 == _localtime64_s(&res, timer)) {
882       back = 1;
883       dest->Y = 1900 + res.tm_year;
884       dest->M = 1 + res.tm_mon;
885       dest->D = res.tm_mday;
886       dest->h = res.tm_hour;
887       dest->m = res.tm_min;
888       dest->s = res.tm_sec;
889     } else {
890       if(app) {
891         /* ERROR: _localtime64_s failed! */
892 	dk3app_log_i1(app, DK3_LL_ERROR, 268);
893       }
894     }
895   }
896   return back;
897 }
898 
899 
900 
901 int
dk3sf_c8_time_convert_app(char * dest,size_t sz,dk3_time_t const * timer,dk3_app_t * app)902 dk3sf_c8_time_convert_app(
903   char *dest, size_t sz, dk3_time_t const *timer, dk3_app_t *app
904 )
905 {
906   int back = 0;
907   char buffer[64];	/* Buffer for sprintf() result. */
908   struct tm res;	/* Result from localtime(). */
909   if((dest) && (sz) && (timer)) {
910     if(0 == _localtime64_s(&res, timer)) {
911       sprintf(
912         buffer,
913 	"%04d-%02d-%02d %02d:%02d:%02d",
914 	(1900 + res.tm_year),
915 	(1 + res.tm_mon),
916 	res.tm_mday,
917 	res.tm_hour,
918 	res.tm_min,
919 	res.tm_sec
920       );
921       if(sz > dk3str_c8_len(buffer)) {
922         dk3str_c8_cpy_not_overlapped(dest, buffer);
923 	back = 1;
924       } else {
925         if(app) {
926 	  /* Buffer too small! */
927 	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
928 	}
929       }
930     } else {
931       if(app) {
932         /* _localtime64_s failed! */
933 	dk3app_log_i1(app, DK3_LL_ERROR, 80);
934       }
935     }
936   }
937   return back;
938 }
939 
940 
941 
942 int
dk3sf_c8_getcwd_app(char * dest,size_t sz,dk3_app_t * app)943 dk3sf_c8_getcwd_app(char *dest, size_t sz, dk3_app_t *app)
944 {
945   int back = 0;
946   if((dest) && (sz)) {
947     if(_getcwd(dest, (int)sz)) {
948       back = 1;
949     } else {
950       if(app) {
951         switch(errno) {
952 	  case ERANGE: {
953 	    /* Buffer too small! */
954 	    dk3app_log_i1(app, DK3_LL_ERROR, 38);
955 	  } break;
956 	  default: {
957 	    dk3app_log_i1(app, DK3_LL_ERROR, 53);
958 	  } break;
959 	}
960       }
961     }
962   }
963   return back;
964 }
965 
966 
967 
968 int
dk3sf_c8_find_exec_app(char * d,size_t s,char const * DK3_ARG_UNUSED (w),char const * DK3_ARG_UNUSED (c),dk3_app_t * app)969 dk3sf_c8_find_exec_app(
970   char *d,
971   size_t s,
972   char const * DK3_ARG_UNUSED(w),
973   char const * DK3_ARG_UNUSED(c),
974   dk3_app_t *app
975 )
976 {
977   int back = 0;
978   DK3_UNUSED_ARG(w)
979   DK3_UNUSED_ARG(c)
980   if((d) && (s)) {
981     if(GetModuleFileNameA(GetModuleHandle(NULL),d,(DWORD)s)) {
982       back = 1;
983     } else {
984       if(app) {
985         /* Failed to find name of executable! */
986 	dk3app_log_i1(app, DK3_LL_ERROR, 40);
987       }
988     }
989   }
990   return back;
991 }
992 
993 
994 
995 static
996 int
dk3sf_c8_is_drive(char const * p)997 dk3sf_c8_is_drive(char const *p)
998 {
999   int back = 0;
1000 
1001   if(dk3str_c8_len(p) == 2) {
1002     if((*p >= 'a') && (*p <= 'z')) {
1003       back = 1;
1004     }
1005     if((*p >= 'A') && (*p <= 'Z')) {
1006       back = 1;
1007     }
1008     if(back) {
1009       back = 0;
1010       if(p[1] == ':') { back = 1; }
1011     }
1012   }
1013   return back;
1014 }
1015 
1016 
1017 int
dk3sf_c8_mkdir_app(char const * p,int mo,dk3_app_t * app)1018 dk3sf_c8_mkdir_app(
1019 	char const *p,
1020 #if VERSION_BEFORE_2019_10_20
1021 	int mo,
1022 #else
1023 	int DK3_ARG_UNUSED(mo),
1024 #endif
1025 	dk3_app_t *app
1026 )
1027 {
1028   int back = 0;
1029   char buffer[DK3_MAX_PATH];	/* Path name for parent directories. */
1030   char *ptr = NULL;		/* Slash/backslash position. */
1031   int cc = 1;			/* Flag: Can continue. */
1032 #if VERSION_BEFORE_2019_10_20
1033   int m = 0;			/* File permissions. */
1034 #endif
1035   dk3_stat_t stb;
1036 #if (!(VERSION_BEFORE_2019_10_20))
1037   DK3_UNUSED_ARG(mo)
1038 #endif
1039 
1040   if(p) {
1041 #if VERSION_BEFORE_2019_10_20
1042     m = dk3sf_convert_back_file_permissions(mo);
1043 #endif
1044     if(dk3str_c8_len(p) < sizeof(buffer)) {
1045       dk3str_c8_cpy_not_overlapped(buffer, p);
1046       ptr = buffer; cc = 1;
1047       while((cc) && (ptr)) {
1048         ptr = dk3str_c8_chr(ptr, '\\');
1049 	if(ptr) {
1050 	  *ptr = '\0';
1051 	  if((dk3str_c8_len(buffer) > 0) && (!dk3sf_c8_is_drive(buffer))) {
1052 	    if(dk3sf_c8_stat_app(&stb, buffer, NULL)) {
1053 	      if(((stb.ft) & (~(DK3_FT_SYMLINK))) != DK3_FT_DIRECTORY) {
1054 	        cc = 0;
1055 	        if(app) {
1056 	          /* Not a directory! */
1057 #if DK3_CHAR_SIZE == 1
1058 		  dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer);
1059 #else
1060 		  dk3app_log_i1(app, DK3_LL_ERROR, 83);
1061 #endif
1062 	        }
1063 	      }
1064 	    } else {
1065 	      if(_mkdir(buffer) != 0) {
1066 	        cc = 0;
1067 	        if(app) {
1068 	          /* Failed to create directory! */
1069 #if DK3_CHAR_SIZE == 1
1070 		  dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer);
1071 #else
1072 		  dk3app_log_i1(app, DK3_LL_ERROR, 86);
1073 #endif
1074 	        }
1075 	      }
1076 	    }
1077 	  }
1078 	  *ptr = '\\';
1079 	  ptr++;
1080 	}
1081       }
1082       if(cc) {
1083 	if(dk3sf_c8_stat_app(&stb, buffer, NULL)) {
1084 	  if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) {
1085 	    back = 1;
1086 	  } else {
1087 	    if(app) {
1088 	      /* Not a directory! */
1089 #if DK3_CHAR_SIZE == 1
1090 	      dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer);
1091 #else
1092 	      dk3app_log_i1(app, DK3_LL_ERROR, 83);
1093 #endif
1094 	    }
1095 	  }
1096 	} else {
1097 	  if(_mkdir(buffer) == 0) {
1098 	    back = 1;
1099 	  } else {
1100 #if DK3_CHAR_SIZE == 1
1101 	    dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer);
1102 #else
1103 	    dk3app_log_i1(app, DK3_LL_ERROR, 86);
1104 #endif
1105 	  }
1106 	}
1107       }
1108     } else {
1109       if(app) {
1110         /* Path too long! */
1111 #if DK3_CHAR_SIZE == 1
1112         dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, p);
1113 #else
1114         dk3app_log_i1(app, DK3_LL_ERROR, 87);
1115 #endif
1116       }
1117     }
1118   }
1119   return back;
1120 }
1121 
1122 
1123 
1124 int
dk3sf_c16_stat_app(dk3_stat_t * st,dk3_c16_t const * fn,dk3_app_t * app)1125 dk3sf_c16_stat_app(dk3_stat_t *st, dk3_c16_t const *fn, dk3_app_t *app)
1126 {
1127   WIN32_FIND_DATAW	wfd;
1128   DWORD			dwFileAttributes;
1129   HANDLE		hFFF;
1130 #if	VERSION_BEFORE_2012_04_14
1131   int			ec   = 0;
1132 #endif
1133   int			back = 0;
1134   struct __stat64 stb;	/* Result from _wstat64(). */
1135 
1136   if((st) && (fn)) {
1137     dk3mem_res((void *)st, sizeof(dk3_stat_t));
1138     st->cReparse = 0x00;
1139     st->dwReparse = (DWORD)0;
1140     if(_wstat64(fn, &stb) == 0) {
1141       back = 1;
1142       st->u = (dk3_um_t)(stb.st_uid);
1143       st->g = (dk3_um_t)(stb.st_gid);
1144       st->device = (dk3_um_t)(stb.st_dev);
1145       st->rdev = (dk3_um_t)(stb.st_rdev);
1146       st->inode = (dk3_um_t)(stb.st_ino);
1147       st->nlink = (dk3_um_t)(stb.st_nlink);
1148       st->cre = (dk3_time_t)(stb.st_ctime);
1149       st->mod = (dk3_time_t)(stb.st_mtime);
1150       st->acc = (dk3_time_t)(stb.st_atime);
1151       st->ft = dk3sf_convert_file_type(stb.st_mode);
1152       st->perm = dk3sf_convert_file_permissions(stb.st_mode);
1153       st->sz = (dk3_um_t)(stb.st_size);
1154       st->lsz = st->sz;
1155       st->ai = 0x00;
1156       dk3mem_cpy((void *)(&(st->lcre)),  (void *)(&(st->cre)), sizeof(dk3_time_t));
1157       dk3mem_cpy((void *)(&(st->lmod)),  (void *)(&(st->mod)), sizeof(dk3_time_t));
1158       dk3mem_cpy((void *)(&(st->lacc)),  (void *)(&(st->acc)), sizeof(dk3_time_t));
1159       st->lu = st->u;
1160       st->lg = st->g;
1161       st->ldevice = st->device;
1162       st->lrdev = st->rdev;
1163       st->linode = st->inode;
1164       st->lnlink = st->nlink;
1165       st->lft = st->ft;
1166       st->lperm = st->perm;
1167       st->lsz = st->sz;
1168 #if VERSION_BEFORE_2012_04_14
1169       if(DK3_FT_DIRECTORY == st->ft) {
1170         WIN32_FIND_DATAW	wfdFileDetails;
1171 	HANDLE			hFileSearch;
1172 
1173 	hFileSearch = FindFirstFileW(fn, &wfdFileDetails);
1174 	if(INVALID_HANDLE_VALUE != hFileSearch) {
1175 	  if(FILE_ATTRIBUTE_REPARSE_POINT & (wfdFileDetails.dwFileAttributes)) {
1176 
1177 	    if(IO_REPARSE_TAG_MOUNT_POINT == wfdFileDetails.dwReserved0) {
1178 
1179 	      /* ##### st->ft = DK3_FT_WINDOWS_MOUNT_POINT; */
1180 	    } else {
1181 	      if(IO_REPARSE_TAG_SYMLINK == wfdFileDetails.dwReserved0) {
1182 
1183 	        /* Symbolic link */
1184 		st->lsz = dk3ma_um_add_ok(
1185 		  dk3ma_um_mul_ok(
1186 		    (dk3_um_t)(wfdFileDetails.nFileSizeHigh),
1187 		    dk3ma_um_add_ok(
1188 		      (dk3_um_t)(MAXDWORD),
1189 		      DK3_UM_1,
1190 		      &ec
1191 		    ),
1192 		    &ec
1193 		  ),
1194 		  (dk3_um_t)(wfdFileDetails.nFileSizeLow),
1195 		  &ec
1196 		);
1197 		dk3sf_convert_filetime(&(st->lcre), &(wfdFileDetails.ftCreationTime));
1198 		dk3sf_convert_filetime(&(st->lmod), &(wfdFileDetails.ftLastWriteTime));
1199 		dk3sf_convert_filetime(&(st->lacc), &(wfdFileDetails.ftLastAccessTime));
1200 		st->ft |= DK3_FT_SYMLINK;
1201 	      } else {
1202 	      }
1203 	    }
1204 	  }
1205 	  FindClose(hFileSearch);
1206 	}
1207       }
1208 #else
1209       dwFileAttributes = GetFileAttributesW(fn);
1210       if(INVALID_FILE_ATTRIBUTES != dwFileAttributes) {
1211         if(dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1212 	  st->cReparse = 'r';
1213 	  hFFF = FindFirstFileW(fn, &wfd);
1214 	  if(INVALID_HANDLE_VALUE != hFFF) {
1215 	    if((wfd.dwFileAttributes) & FILE_ATTRIBUTE_REPARSE_POINT) {
1216 	      st->dwReparse = wfd.dwReserved0;
1217 	      switch(wfd.dwReserved0) {
1218 	        case IO_REPARSE_TAG_MOUNT_POINT: {
1219 		  st->cReparse = 'm';
1220 		} break;
1221 		case IO_REPARSE_TAG_SYMLINK: {
1222 		  st->cReparse = 'l';
1223 		} break;
1224 	      }
1225 	    }
1226 	    FindClose(hFFF);
1227 	  }
1228 	}
1229       }
1230 #endif
1231     } else {
1232       if(app) {
1233         /* _wstat64() failed! */
1234 #if DK3_CHAR_SIZE == 2
1235 	dk3app_log_i3(app, DK3_LL_ERROR, 61, 163, fn);
1236 #else
1237 	dk3app_log_i1(app, DK3_LL_ERROR, 73);
1238 #endif
1239       }
1240     }
1241   }
1242   return back;
1243 }
1244 
1245 
1246 
1247 static
1248 int
dk3sf_c16_check_open_file(dk3_c16_t const * fn,int want_to_write,dk3_app_t * app)1249 dk3sf_c16_check_open_file(dk3_c16_t const *fn, int want_to_write, dk3_app_t *app)
1250 {
1251   int		back = 1;
1252   dk3_stat_t	stb;		/* Check for existing file. */
1253   if(dk3sf_c16_stat_app(&stb, fn, NULL)) {
1254     if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) {
1255       if(app) {
1256         back = 0;
1257         /* Name refers a directory! */
1258 #if DK3_CHAR_SIZE == 2
1259 	dk3app_log_i3(app, DK3_LL_ERROR, 74, 75, fn);
1260 #else
1261 	dk3app_log_i1(app, DK3_LL_ERROR, 76);
1262 #endif
1263       }
1264     }
1265     if(want_to_write) {
1266       /* Place for additional checks to write files here. */
1267     }
1268   }
1269   return back;
1270 }
1271 
1272 
1273 
1274 FILE *
dk3sf_c16_fopen_app(dk3_c16_t const * fn,dk3_c16_t const * mo,dk3_app_t * app)1275 dk3sf_c16_fopen_app(dk3_c16_t const *fn, dk3_c16_t const *mo, dk3_app_t *app)
1276 {
1277   FILE		*back = NULL;
1278   dk3_c16_t	const	*moptr = NULL;	/* Traverse mode string. */
1279   int		want_to_write = 0;	/* Flag: Write access wanted. */
1280   if((fn) && (mo)) {
1281     moptr = mo;
1282     while(*moptr) {
1283       switch(*moptr) {
1284         case L'w': case L'a': case L'+': { want_to_write = 1; } break;
1285       }
1286       moptr++;
1287     }
1288     if(dk3sf_c16_check_open_file(fn, want_to_write, app)) {
1289       back = _wfopen(fn, mo);
1290       if(!(back)) {
1291         if(app) {
1292 	  /* Failed to open file for writing! */
1293 	  if(want_to_write) {
1294 #if DK3_CHAR_SIZE == 2
1295 	    dk3app_log_i3(app, DK3_LL_ERROR, 77, 78, fn);
1296 #else
1297 	    dk3app_log_i1(app, DK3_LL_ERROR, 79);
1298 #endif
1299           } else {
1300 #if DK3_CHAR_SIZE == 2
1301 	    dk3app_log_i3(app, DK3_LL_ERROR, 143, 144, fn);
1302 #else
1303 	    dk3app_log_i1(app, DK3_LL_ERROR, 145);
1304 #endif
1305 	  }
1306 	}
1307       }
1308     }
1309   }
1310   return back;
1311 }
1312 
1313 
1314 
1315 int
dk3sf_c16_time_convert_app(dk3_c16_t * dest,size_t sz,dk3_time_t const * timer,dk3_app_t * app)1316 dk3sf_c16_time_convert_app(
1317   dk3_c16_t *dest, size_t sz, dk3_time_t const *timer, dk3_app_t *app
1318 )
1319 {
1320   int back = 0;
1321   char buffer[64];
1322   if(dk3sf_c8_time_convert_app(buffer, sizeof(buffer), timer, app)) {
1323     back = dk3str_cnv_c8p_to_c16_app(dest, sz, buffer, app);
1324   }
1325   return back;
1326 }
1327 
1328 
1329 
1330 int
dk3sf_c16_getcwd_app(dk3_c16_t * dest,size_t sz,dk3_app_t * app)1331 dk3sf_c16_getcwd_app(dk3_c16_t *dest, size_t sz, dk3_app_t *app)
1332 {
1333   int back = 0;
1334   if((dest) && (sz)) {
1335     if(_wgetcwd(dest, (int)sz)) {
1336       back = 1;
1337     } else {
1338       if(app) {
1339         switch(errno) {
1340 #ifdef ERANGE
1341 	  case ERANGE: {
1342 	    /* Buffer too small! */
1343 	    dk3app_log_i1(app, DK3_LL_ERROR, 38);
1344 	  } break;
1345 #endif
1346 	  default: {
1347 	    /* Failed to find current working directory! */
1348 	    dk3app_log_i1(app, DK3_LL_ERROR, 53);
1349 	  } break;
1350 	}
1351       }
1352     }
1353   }
1354   return back;
1355 }
1356 
1357 
1358 
1359 int
dk3sf_c16_find_exec_app(dk3_c16_t * d,size_t s,dk3_c16_t const * DK3_ARG_UNUSED (w),dk3_c16_t const * DK3_ARG_UNUSED (c),dk3_app_t * app)1360 dk3sf_c16_find_exec_app(
1361   dk3_c16_t *d,
1362   size_t s,
1363   dk3_c16_t const * DK3_ARG_UNUSED(w),
1364   dk3_c16_t const * DK3_ARG_UNUSED(c),
1365   dk3_app_t *app
1366 )
1367 {
1368   int back = 0;
1369   DK3_UNUSED_ARG(w)
1370   DK3_UNUSED_ARG(c)
1371   if((d) && (s)) {
1372     if(GetModuleFileNameW(GetModuleHandle(NULL),d,(DWORD)s)) {
1373       back = 1;
1374     } else {
1375       if(app) {
1376         /* Failed to find name of executable! */
1377 	dk3app_log_i1(app, DK3_LL_ERROR, 40);
1378       }
1379     }
1380   }
1381   return back;
1382 }
1383 
1384 
1385 
1386 static
1387 int
dk3sf_c16_is_drive(dk3_c16_t const * p)1388 dk3sf_c16_is_drive(dk3_c16_t const *p)
1389 {
1390   int back = 0;
1391   if(dk3str_c16_len(p) == 2) {
1392     if((*p >= L'A') && (*p <= L'Z')) {
1393       back = 1;
1394     }
1395     if((*p >= L'a') && (*p <= L'z')) {
1396       back = 1;
1397     }
1398     if(back) {
1399       back = 0;
1400       if(p[1] == L':') { back = 1; }
1401     }
1402   }
1403   return back;
1404 }
1405 
1406 
1407 
1408 int
dk3sf_c16_mkdir_app(dk3_c16_t const * p,int mo,dk3_app_t * app)1409 dk3sf_c16_mkdir_app(
1410 	dk3_c16_t const *p,
1411 #if VERSION_BEFORE_2019_10_20
1412 	int mo,
1413 #else
1414 	int DK3_ARG_UNUSED(mo),
1415 #endif
1416 	dk3_app_t *app
1417 )
1418 {
1419   int back = 0;
1420   dk3_c16_t buffer[DK3_MAX_PATH];	/* File names of parent directories. */
1421   dk3_c16_t *ptr = NULL;		/* Current slash/backslash position. */
1422   int cc = 1;				/* Flag: Can continue. */
1423 #if VERSION_BEFORE_2019_10_20
1424   int m = 0;				/* Permissions. */
1425 #endif
1426   dk3_stat_t stb;			/* Test whether file/dir exists. */
1427 #if (!(VERSION_BEFORE_2019_10_20))
1428   DK3_UNUSED_ARG(mo)
1429 #endif
1430   if(p) {
1431 #if VERSION_BEFORE_2019_10_20
1432     m = dk3sf_convert_back_file_permissions(mo);
1433 #endif
1434     if(dk3str_c16_len(p) < sizeof(buffer)) {
1435       dk3str_c16_cpy(buffer, p);
1436       ptr = buffer; cc = 1;
1437       while((cc) && (ptr)) {
1438         ptr = dk3str_c16_chr(ptr, 0x005CU);
1439 	if(ptr) {
1440 	  *ptr = 0U;
1441 	  if((dk3str_c16_len(buffer) > 0) && (!dk3sf_c16_is_drive(buffer))) {
1442 	    if(dk3sf_c16_stat_app(&stb, buffer, NULL)) {
1443 	      if(((stb.ft) & (~(DK3_FT_SYMLINK))) != DK3_FT_DIRECTORY) {
1444 	        cc = 0;
1445 	        if(app) {
1446 	          /* Not a directory! */
1447 #if DK3_CHAR_SIZE == 2
1448 		  dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer);
1449 #else
1450 		  dk3app_log_i1(app, DK3_LL_ERROR, 83);
1451 #endif
1452 	        }
1453 	      }
1454 	    } else {
1455 	      if(_wmkdir(buffer) != 0) {
1456 	        cc = 0;
1457 	        if(app) {
1458 	          /* Failed to create directory! */
1459 #if DK3_CHAR_SIZE == 2
1460 		  dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer);
1461 #else
1462 		  dk3app_log_i1(app, DK3_LL_ERROR, 86);
1463 #endif
1464 	        }
1465 	      }
1466 	    }
1467 	  }
1468 	  *ptr = 0x005CU;
1469 	  ptr++;
1470 	}
1471       }
1472       if(cc) {
1473 	if(dk3sf_c16_stat_app(&stb, buffer, NULL)) {
1474 	  if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) {
1475 	    back = 1;
1476 	  } else {
1477 	    if(app) {
1478 	      /* Not a directory! */
1479 #if DK3_CHAR_SIZE == 2
1480 	      dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer);
1481 #else
1482 	      dk3app_log_i1(app, DK3_LL_ERROR, 83);
1483 #endif
1484 	    }
1485 	  }
1486 	} else {
1487 	  if(_wmkdir(buffer) == 0) {
1488 	    back = 1;
1489 	  } else {
1490 #if DK3_CHAR_SIZE == 2
1491 	    dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer);
1492 #else
1493 	    dk3app_log_i1(app, DK3_LL_ERROR, 86);
1494 #endif
1495 	  }
1496 	}
1497       }
1498     } else {
1499       if(app) {
1500         /* Path too long! */
1501 #if DK3_CHAR_SIZE == 2
1502         dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, p);
1503 #else
1504         dk3app_log_i1(app, DK3_LL_ERROR, 87);
1505 #endif
1506       }
1507     }
1508   }
1509   return back;
1510 }
1511 
1512 
1513 
1514 int
dk3sf_c16_get_hostname_app(dk3_c16_t * db,size_t sz,dk3_app_t * app)1515 dk3sf_c16_get_hostname_app(dk3_c16_t *db, size_t sz, dk3_app_t *app)
1516 {
1517   int back = 0;
1518   DWORD s = 0;		/* Buffer size / result length. */
1519   if((db) && (sz)) {
1520     s = (DWORD)sz;
1521     if(GetComputerNameExW(ComputerNameNetBIOS, db, &s)) {
1522       if((size_t)s < sz) {
1523         db[(size_t)s] = L'\0';
1524       } else {
1525         db[sz - 1] = L'\0';
1526       }
1527       back = 1;
1528     } else {
1529       if(app) {
1530         /* ERROR: Failed to find NetBIOS name! */
1531 	dk3app_log_i1(app, DK3_LL_ERROR, 131);
1532       }
1533     }
1534   }
1535   return back;
1536 }
1537 
1538 
1539 
1540 int
dk3sf_c8_get_hostname_app(char * db,size_t sz,dk3_app_t * app)1541 dk3sf_c8_get_hostname_app(char *db, size_t sz, dk3_app_t *app)
1542 {
1543   int back = 0;
1544   DWORD s = 0;		/* Buffer size / result length. */
1545   if((db) && (sz)) {
1546     s = (DWORD)sz;
1547     if(GetComputerNameExA(ComputerNameNetBIOS, db, &s)) {
1548       if((size_t)s < sz) {
1549         db[(size_t)s] = '\0';
1550       } else {
1551         db[sz - 1] = '\0';
1552       }
1553       back = 1;
1554     } else {
1555       if(app) {
1556         /* ERROR: Failed to find NetBIOS name! */
1557 	dk3app_log_i1(app, DK3_LL_ERROR, 131);
1558       }
1559     }
1560   }
1561   return back;
1562 }
1563 
1564 
1565 
1566 #if DK3_CHAR_SIZE > 1
1567 #if DK3_CHAR_SIZE > 2
1568 #error	"dkChar must be 8 or 16 bit!"
1569 #else
1570 /* +++ Windows, dkChar 16 bit +++ */
1571 
1572 
1573 
1574 int
dk3sf_fgets_fn_app(dkChar * db,size_t sz,FILE * fi,dkChar const * fn,dk3_app_t * app)1575 dk3sf_fgets_fn_app(
1576   dkChar *db, size_t sz, FILE *fi, dkChar const *fn, dk3_app_t *app
1577 )
1578 {
1579   int back = 0;
1580 
1581   if((db) && (sz) && (fi)) {
1582     if(fgetws(db, (int)sz, fi)) {
1583       if(db[0] == DK3_CHAR_BOM) {
1584         dk3str_c16_cpy(db, &(db[1]));
1585       }
1586       back = 1;
1587     } else {
1588       if(!feof(fi)) {
1589         if(app) {
1590 	  if(fn) {
1591 	    dk3app_log_i3(app, DK3_LL_ERROR, 346, 347, fn);
1592 	  } else {
1593 	    dk3app_log_i1(app, DK3_LL_ERROR, 345);
1594 	  }
1595 	}
1596       }
1597     }
1598   }
1599   return back;
1600 }
1601 
1602 
1603 
1604 int
dk3sf_fputc_fn_app(dkChar ch,FILE * fi,dkChar const * fn,dk3_app_t * app)1605 dk3sf_fputc_fn_app(dkChar ch, FILE *fi, dkChar const *fn, dk3_app_t *app)
1606 {
1607   int back = 0;
1608   if(fi) {
1609     if(fputwc(ch, fi) != WEOF) {
1610       back = 1;
1611     } else {
1612       if(app) {
1613         if(fn) {
1614 	  dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn);
1615 	} else {
1616 	  dk3app_log_i1(app, DK3_LL_ERROR, 120);
1617 	}
1618       }
1619     }
1620   }
1621   return back;
1622 }
1623 
1624 
1625 
1626 int
dk3sf_fputs_fn_app(dkChar const * st,FILE * fi,dkChar const * fn,dk3_app_t * app)1627 dk3sf_fputs_fn_app(dkChar const *st,FILE *fi,dkChar const *fn,dk3_app_t *app)
1628 {
1629   int back = 0;
1630   if((st) && (fi)) {
1631     if(fputws(st, fi) != WEOF) {
1632       back = 1;
1633     } else {
1634       if(app) {
1635         if(fn) {
1636 	  dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn);
1637 	} else {
1638 	  dk3app_log_i1(app, DK3_LL_ERROR, 120);
1639 	}
1640       }
1641     }
1642   }
1643   return back;
1644 }
1645 
1646 
1647 
1648 void
dk3sf_initialize_stdout(void)1649 dk3sf_initialize_stdout(void)
1650 {
1651   static int not_bom_written_to_stdout = 1;
1652   if(not_bom_written_to_stdout) {
1653     not_bom_written_to_stdout = 0;
1654 #if defined(_MSC_VER)
1655     (void)_setmode(_fileno(stdout), _O_U16TEXT);
1656 #endif
1657     if(!_isatty(_fileno(stdout))) {
1658       fputwc(0xFEFF, stdout);
1659     }
1660   }
1661 }
1662 
1663 
1664 
1665 void
dk3sf_initialize_stdout_no_bom(void)1666 dk3sf_initialize_stdout_no_bom(void)
1667 {
1668   static int not_bom_written_to_stdout = 1;
1669   if(not_bom_written_to_stdout) {
1670     not_bom_written_to_stdout = 0;
1671 #if defined(_MSC_VER)
1672     (void)_setmode(_fileno(stdout), _O_U16TEXT);
1673 #endif
1674   }
1675 }
1676 
1677 
1678 
1679 void
dk3sf_initialize_stderr(void)1680 dk3sf_initialize_stderr(void)
1681 {
1682   static int not_bom_written_to_stderr = 1;
1683   if(not_bom_written_to_stderr) {
1684     not_bom_written_to_stderr = 0;
1685 #if defined(_MSC_VER)
1686     (void)_setmode(_fileno(stderr), _O_U16TEXT);
1687 #endif
1688     if(!_isatty(_fileno(stderr))) {
1689       fputwc(0xFEFF, stderr);
1690     }
1691   }
1692 }
1693 
1694 
1695 
1696 void
dk3sf_initialize_file(FILE * fipo)1697 dk3sf_initialize_file(FILE *fipo)
1698 {
1699 #if defined(_MSC_VER)
1700   (void)_setmode(_fileno(fipo), _O_U16TEXT);
1701 #endif
1702   fputwc(0xFEFF, fipo);
1703 }
1704 
1705 
1706 
1707 /* --- Windows, dkChar 16 bit --- */
1708 #endif
1709 #else
1710 /* +++ Windows, dkChar 8 bit +++ */
1711 
1712 
1713 
1714 int
dk3sf_fgets_fn_app(dkChar * db,size_t sz,FILE * fi,dkChar const * fn,dk3_app_t * app)1715 dk3sf_fgets_fn_app(
1716   dkChar *db, size_t sz, FILE *fi, dkChar const *fn, dk3_app_t *app
1717 )
1718 {
1719   int back = 0;
1720   if((db) && (sz) && (fi)) {
1721     if(fgets(db, sz, fi)) {
1722       back = 1;
1723     } else {
1724       if(!feof(fi)) {
1725         if(app) {
1726 	  if(fn) {
1727 	    dk3app_log_i3(app, DK3_LL_ERROR, 346, 347, fn);
1728 	  } else {
1729 	    dk3app_log_i1(app, DK3_LL_ERROR, 345);
1730 	  }
1731 	}
1732       }
1733     }
1734   }
1735   return back;
1736 }
1737 
1738 
1739 int
dk3sf_fputs_fn_app(dkChar const * st,FILE * fi,dkChar const * fn,dk3_app_t * app)1740 dk3sf_fputs_fn_app(dkChar const *st,FILE *fi,dkChar const *fn,dk3_app_t *app)
1741 {
1742   int back = 0;
1743   if((st) && (fi)) {
1744     if(fputs(st, fi) != EOF) {
1745       back = 1;
1746     } else {
1747       if(app) {
1748         if(fn) {
1749 	  dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn);
1750 	} else {
1751 	  dk3app_log_i1(app, DK3_LL_ERROR, 120);
1752 	}
1753       }
1754     }
1755   }
1756   return back;
1757 }
1758 
1759 
1760 
1761 int
dk3sf_fputc_fn_app(dkChar ch,FILE * fi,dkChar const * fn,dk3_app_t * app)1762 dk3sf_fputc_fn_app(dkChar ch, FILE *fi, dkChar const *fn, dk3_app_t *app)
1763 {
1764   int back = 0;
1765   if(fi) {
1766     if(fputc(ch, fi) != EOF) {
1767       back = 1;
1768     } else {
1769       if(app) {
1770         if(fn) {
1771 	  dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn);
1772 	} else {
1773 	  dk3app_log_i1(app, DK3_LL_ERROR, 120);
1774 	}
1775       }
1776     }
1777   }
1778   return back;
1779 }
1780 
1781 
1782 
1783 void
dk3sf_initialize_stdout(void)1784 dk3sf_initialize_stdout(void)
1785 {
1786 }
1787 
1788 
1789 
1790 void
dk3sf_initialize_stderr(void)1791 dk3sf_initialize_stderr(void)
1792 {
1793 }
1794 
1795 
1796 void
dk3sf_initialize_file(FILE * fipo)1797 dk3sf_initialize_file(FILE *fipo)
1798 {
1799 }
1800 
1801 
1802 /* --- Windows, dkChar 8 bit --- */
1803 #endif
1804 
1805 /* --- Windows --- */
1806 #else
1807 /* +++ non-Windows +++ */
1808 
1809 
1810 
1811 /**	8-bit character keywords for use on non-Windows systems.
1812 */
1813 static char const * const kw_c8_no_win[] = {
1814 /*  0 */	"/",
1815 /*  1 */	"PATH",
1816 NULL
1817 };
1818 
1819 
1820 
1821 dk3_um_t
dk3sf_getpid(void)1822 dk3sf_getpid(void)
1823 {
1824   dk3_um_t back = DK3_UM_0;
1825 #if DK3_HAVE_GETPID
1826   back = (dk3_um_t)getpid();
1827 #else
1828 #if DK3_HAVE__GETPID
1829   back = (dk3_um_t)_getpid();
1830 #else
1831 #error	"No getpid() function!"
1832 #endif
1833 #endif
1834   return back;
1835 }
1836 
1837 
1838 
1839 dk3_c8_t *
dk3sf_c8_getenv(char const * name)1840 dk3sf_c8_getenv(char const *name)
1841 {
1842   char *back = NULL;
1843   if(name) {
1844     back = getenv(name);
1845   }
1846   return back;
1847 }
1848 
1849 
1850 
1851 int
dk3sf_c8_remove_dir_app(char const * n,dk3_app_t * app)1852 dk3sf_c8_remove_dir_app(char const *n, dk3_app_t *app)
1853 {
1854   int back = 0;
1855   if(n) {
1856 #if DK3_HAVE_RMDIR
1857     if(rmdir(n) == 0) {
1858       back = 1;
1859     } else {
1860       if(app) {
1861         /* Failed to remove directory! */
1862 #if DK3_CHAR_SIZE == 1
1863 	dk3app_log_i3(app, DK3_LL_ERROR, 69, 70, n);
1864 #else
1865 	dk3app_log_i1(app, DK3_LL_ERROR, 68);
1866 #endif
1867 	dk3sf_report_errno(app, errno, dk3sf_function_names[2]);
1868       }
1869     }
1870 #else
1871 #error	"No rmdir() function!"
1872 #endif
1873   }
1874   return back;
1875 }
1876 
1877 
1878 int
dk3sf_c8_remove_file_app(char const * n,dk3_app_t * app)1879 dk3sf_c8_remove_file_app(char const *n, dk3_app_t *app)
1880 {
1881   int back = 0;
1882   if(n) {
1883 #if DK3_HAVE_UNLINK
1884     if(unlink(n) == 0) {
1885       back = 1;
1886     } else {
1887       if(app) {
1888         /* ERROR: Failed to unlink file */
1889 #if DK3_CHAR_SIZE == 1
1890 	dk3app_log_i3(app, DK3_LL_ERROR, 88, 89, n);
1891 #else
1892 	dk3app_log_i1(app, DK3_LL_ERROR, 90);
1893 #endif
1894 	dk3sf_report_errno(app, errno, dk3sf_function_names[3]);
1895       }
1896     }
1897 #else
1898 #error	"No support for unlink"
1899 #endif
1900   }
1901   return back;
1902 }
1903 
1904 
1905 /**	Copy logname of user record to buffer.
1906 	@param	d	Destination buffer.
1907 	@param	s	Size of \a d.
1908 	@param	p	User record.
1909 	@param	app	Application structure for diagnostics, may be NULL.
1910 	@return	1 on success, 0 on error.
1911 */
1912 static
1913 int
dk3sf_c8_copy_logname(char * d,size_t s,struct passwd * p,dk3_app_t * app)1914 dk3sf_c8_copy_logname(char *d, size_t s, struct passwd *p, dk3_app_t *app)
1915 {
1916   int back = 0;
1917 
1918   if(p) {
1919     if(p->pw_name) {
1920       if(dk3str_c8_len(p->pw_name) < s) {
1921         dk3str_c8_cpy_not_overlapped(d, p->pw_name);
1922 	back = 1;
1923       } else {
1924         if(app) {
1925 	  /* Destination buffer too small! */
1926 	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
1927 	}
1928       }
1929     } else {
1930       if(app) {
1931         /* No name entry in record! */
1932 	dk3app_log_i1(app, DK3_LL_ERROR, 91);
1933       }
1934     }
1935   }
1936   return back;
1937 }
1938 
1939 
1940 
1941 int
dk3sf_c8_get_logname_app(char * d,size_t s,dk3_app_t * app)1942 dk3sf_c8_get_logname_app(char *d, size_t s, dk3_app_t *app)
1943 {
1944   int		back = 0;
1945   uid_t		u = 0;		/* Current user ID. */
1946   struct passwd	*p = NULL;	/* Current user to process. */
1947   char		uidbuffer[128];	/* Text buffer to store UID. */
1948 
1949   if((d) && (s)) {
1950     u = getuid();
1951 #if DK3_HAVE_GETPWUID
1952     p = getpwuid(u);
1953     if(p) {
1954       back = dk3sf_c8_copy_logname(d, s, p, app);
1955     } else {
1956       if(app) {
1957         /* No passwd record for UID! */
1958 #if DK3_CHAR_SIZE == 1
1959 	dk3ma_um_to_c8_string(uidbuffer, sizeof(uidbuffer), (dk3_um_t)u);
1960 	dk3app_log_i3(app, DK3_LL_ERROR, 92, 93, uidbuffer);
1961 #else
1962 	dk3app_log_i1(app, DK3_LL_ERROR, 94);
1963 #endif
1964 	dk3sf_report_errno(app, errno, dk3sf_function_names[4]);
1965       }
1966     }
1967 #else
1968 #if DK3_HAVE_SETPWENT
1969     setpwent();
1970 #endif
1971     {
1972       int cc;
1973       int found;
1974       cc = 1; found = 0;
1975       while(cc) {
1976         p = getpwent();
1977 	if(p) {
1978 	  if(p->pw_uid == u) {
1979 	    cc = 0;
1980 	    found = 1;
1981 	    back = dk3sf_c8_copy_logname(d, s, p, app);
1982 	  }
1983 	} else { cc = 0; }
1984       }
1985       if(!found) {
1986         if(app) {
1987           /* No passwd record for UID! */
1988 #if DK3_CHAR_SIZE == 1
1989 	  dk3ma_um_to_c8_string(uidbuffer, sizeof(uidbuffer), (dk3_um_t)u);
1990 	  dk3app_log_i3(app, DK3_LL_ERROR, 92, 93, uidbuffer);
1991 #else
1992 	  dk3app_log_i1(app, DK3_LL_ERROR, 94);
1993 #endif
1994 	}
1995       }
1996     }
1997 #if DK3_HAVE_SETPWENT
1998     endpwent();
1999 #endif
2000 #endif
2001   }
2002   return back;
2003 }
2004 
2005 
2006 
2007 int
dk3sf_c8_get_home_app(char * d,size_t s,dk3_app_t * app)2008 dk3sf_c8_get_home_app(char *d, size_t s, dk3_app_t *app)
2009 {
2010   int		back = 0;
2011   uid_t		u = 0;		/* Current user ID to process. */
2012   struct passwd	*p = NULL;	/* Current user to process. */
2013   char		uidbuffer[128];	/* Text buffer to store UID. */
2014   if((d) && (s)) {
2015     u = getuid();
2016 #if DK3_HAVE_GETPWUID
2017     p = getpwuid(u);
2018     if(p) {
2019       if(p->pw_dir) {
2020         if(dk3str_c8_len(p->pw_dir) < s) {
2021 	  dk3str_c8_cpy_not_overlapped(d, p->pw_dir);
2022 	  back = 1;
2023 	} else {
2024 	  if(app) {
2025 	    /* Destination buffer too small! */
2026 	    dk3app_log_i1(app, DK3_LL_ERROR, 38);
2027 	  }
2028 	}
2029       } else {
2030         if(app) {
2031 	  /* Home directory entry empty! */
2032 	  dk3app_log_i1(app, DK3_LL_ERROR, 95);
2033 	}
2034       }
2035     } else {
2036       if(app) {
2037         /* No passwd record for uid! */
2038 #if DK3_CHAR_SIZE == 1
2039 	dk3ma_um_to_c8_string(uidbuffer, sizeof(uidbuffer), (dk3_um_t)u);
2040 	dk3app_log_i3(app, DK3_LL_ERROR, 92, 93, uidbuffer);
2041 #else
2042 	dk3app_log_i1(app, DK3_LL_ERROR, 94);
2043 #endif
2044 	dk3sf_report_errno(app, errno, dk3sf_function_names[4]);
2045       }
2046     }
2047 #else
2048     {
2049       int cc;
2050       int found;
2051       cc = 1; found = 0;
2052 #if DK3_HAVE_SETPWENT
2053       setpwent();
2054 #endif
2055       while(cc) {
2056         p = getpwent();
2057 	if(p) {
2058 	  if(p->pw_uid == u) {
2059 	    cc = 0; found = 1;
2060 	    if(p->pw_dir) {
2061 	      if(dk3str_c8_len(p->pw_dir) < s) {
2062 	        dk3str_c8_cpy_not_overlapped(d, p->pw_dir);
2063 		back = 1;
2064 	      } else {
2065 	        if(app) {
2066 		  /* Destination buffer too small! */
2067 		  dk3app_log_i1(app, DK3_LL_ERROR, 38);
2068 		}
2069 	      }
2070 	    } else {
2071 	      if(app) {
2072 	        /* Home directory entry empty! */
2073 		dk3app_log_i1(app, DK3_LL_ERROR, 95);
2074 	      }
2075 	    }
2076 	  }
2077 	} else { cc = 0; }
2078       }
2079 #if DK3_HAVE_SETPWENT
2080       endpwent();
2081 #endif
2082       if(!found) {
2083         if(app) {
2084 	  /* No entry for uid! */
2085 #if DK3_CHAR_SIZE == 1
2086 	  dk3ma_um_to_c8_string(uidbuffer, sizeof(uidbuffer), (dk3_um_t)u);
2087 	  dk3app_log_i3(app, DK3_LL_ERROR, 92, 93, uidbuffer);
2088 #else
2089 	  dk3app_log_i1(app, DK3_LL_ERROR, 94);
2090 #endif
2091 	}
2092       }
2093     }
2094 #endif
2095   }
2096   return back;
2097 }
2098 
2099 
2100 int
dk3sf_time(dk3_time_t * timer)2101 dk3sf_time(dk3_time_t *timer)
2102 {
2103   int back = 1;
2104   time(timer);
2105   return back;
2106 }
2107 
2108 
2109 
2110 /**	Convert file type from system representation to DK3_FT_xxx.
2111 	@param	m	File type as found by stat().
2112 	@return	DK3_FT_xxx.
2113 */
2114 static
2115 int
dk3sf_convert_file_type(mode_t m)2116 dk3sf_convert_file_type(mode_t m)
2117 {
2118   int back = 0;
2119   switch(m & S_IFMT) {
2120     case S_IFIFO: back = DK3_FT_FIFO; break;
2121     case S_IFCHR: back = DK3_FT_SPECIAL_CHAR; break;
2122     case S_IFDIR: back = DK3_FT_DIRECTORY; break;
2123     case S_IFBLK: back = DK3_FT_SPECIAL_BLOCK; break;
2124     case S_IFREG: back = DK3_FT_REGULAR; break;
2125     case S_IFSOCK: back = DK3_FT_SOCKET; break;
2126 #ifdef S_IFMPC
2127     case S_IFMPC: back = DK3_FT_MUX_CHAR; break;
2128 #endif
2129 #ifdef S_IFNAM
2130     case S_IFNAM: back = DK3_FT_XENIX_SPECIAL; break;
2131 #endif
2132 #ifdef S_INSEM
2133     case S_INSEM: back = DK3_FT_XENIX_SEMAPHORE; break;
2134 #endif
2135 #ifdef S_INSHD
2136     case S_INSHD: back = DK3_FT_XENIX_SHARED_DATA; break;
2137 #endif
2138 #ifdef S_IFMPB
2139     case S_IFMPB: back = DK3_FT_MUX_BLOCK; break;
2140 #endif
2141 #ifdef S_IFCMP
2142     case S_IFCMP: back = DK3_FT_VXFS_COMPRESSED; break;
2143 #endif
2144 #ifdef S_IFNWK
2145     case S_IFNWK: back = DK3_FT_NETWORK_SPECIAL; break;
2146 #endif
2147 #ifdef S_IFSHAD
2148     case S_IFSHAD: back = DK3_FT_ACL_SHADOW; break;
2149 #endif
2150 #ifdef S_IFDOOR
2151     case S_IFDOOR: back = DK3_FT_DOOR; break;
2152 #endif
2153 #ifdef S_IFWHT
2154     case S_IFWHT: back = DK3_FT_WHITEOUT; break;
2155 #endif
2156   }
2157   return back;
2158 }
2159 
2160 
2161 
2162 /**	Convert file permissions from system representation to
2163 	DK3_PERM_xxx
2164 	@param	m	File mode as obtained from stat().
2165 	@return	DK3_PERM_xxx value or combination.
2166 */
2167 static
2168 int
dk3sf_convert_file_permissions(mode_t m)2169 dk3sf_convert_file_permissions(mode_t m)
2170 {
2171   int back = 0;
2172   DK3SF_ADDIF(S_IRUSR,DK3_FPERM_U_READ)
2173   DK3SF_ADDIF(S_IWUSR,DK3_FPERM_U_WRITE)
2174   DK3SF_ADDIF(S_IXUSR,DK3_FPERM_U_EXEC)
2175   DK3SF_ADDIF(S_IRGRP,DK3_FPERM_G_READ)
2176   DK3SF_ADDIF(S_IWGRP,DK3_FPERM_G_WRITE)
2177   DK3SF_ADDIF(S_IXGRP,DK3_FPERM_G_EXEC)
2178   DK3SF_ADDIF(S_IROTH,DK3_FPERM_O_READ)
2179   DK3SF_ADDIF(S_IWOTH,DK3_FPERM_O_WRITE)
2180   DK3SF_ADDIF(S_IXOTH,DK3_FPERM_O_EXEC)
2181   DK3SF_ADDIF(S_ISUID,DK3_FPERM_SUID)
2182   DK3SF_ADDIF(S_ISGID,DK3_FPERM_SGID)
2183   DK3SF_ADDIF(S_ISVTX,DK3_FPERM_VTX)
2184   return back;
2185 }
2186 
2187 
2188 
2189 #if (1 == DK3_CHAR_SIZE) || (VERSION_BEFORE_2019_10_20)
2190 
2191 /**	Convert file permissions back from dktools to system values.
2192 	@param	m	File permissions in dktools notation.
2193 	@return	File permissions in system notation.
2194 */
2195 static
2196 mode_t
dk3sf_convert_back_file_permissions(int m)2197 dk3sf_convert_back_file_permissions(int m)
2198 {
2199   mode_t back  = 0;
2200   DK3SF_ADDIF(DK3_FPERM_U_READ,S_IRUSR)
2201   DK3SF_ADDIF(DK3_FPERM_U_WRITE,S_IWUSR)
2202   DK3SF_ADDIF(DK3_FPERM_U_EXEC,S_IXUSR)
2203   DK3SF_ADDIF(DK3_FPERM_G_READ,S_IRGRP)
2204   DK3SF_ADDIF(DK3_FPERM_G_WRITE,S_IWGRP)
2205   DK3SF_ADDIF(DK3_FPERM_G_EXEC,S_IXGRP)
2206   DK3SF_ADDIF(DK3_FPERM_O_READ,S_IROTH)
2207   DK3SF_ADDIF(DK3_FPERM_O_WRITE,S_IWOTH)
2208   DK3SF_ADDIF(DK3_FPERM_O_EXEC,S_IXOTH)
2209   DK3SF_ADDIF(DK3_FPERM_SUID,S_ISUID)
2210   DK3SF_ADDIF(DK3_FPERM_SGID,S_ISGID)
2211   DK3SF_ADDIF(DK3_FPERM_VTX,S_ISVTX)
2212   return back;
2213 }
2214 
2215 #endif
2216 
2217 
2218 int
dk3sf_c8_stat_app(dk3_stat_t * st,char const * fn,dk3_app_t * app)2219 dk3sf_c8_stat_app(dk3_stat_t *st, char const *fn, dk3_app_t *app)
2220 {
2221   int back = 0;
2222 
2223   if((st) && (fn)) {
2224 #if DK3_HAVE_LARGEFILE64_SOURCE && DK3_HAVE_STAT64
2225     struct stat64 stb;		/* Result from stat64(). */
2226 #if DK3_HAVE_LSTAT64
2227     struct stat64 lstb;		/* Result from lstat64(). */
2228 #endif
2229 
2230     if(stat64(fn, &stb) == 0) {
2231       st->u = (dk3_um_t)(stb.st_uid);
2232       st->g = (dk3_um_t)(stb.st_gid);
2233       st->device = (dk3_um_t)(stb.st_dev);
2234       st->rdev = (dk3_um_t)(stb.st_rdev);
2235       st->inode = (dk3_um_t)(stb.st_ino);
2236       st->nlink = (dk3_um_t)(stb.st_nlink);
2237       st->cre = (dk3_time_t)(stb.st_ctime);
2238       st->mod = (dk3_time_t)(stb.st_mtime);
2239       st->acc = (dk3_time_t)(stb.st_atime);
2240       st->ft = dk3sf_convert_file_type(stb.st_mode);
2241       st->perm = dk3sf_convert_file_permissions(stb.st_mode);
2242       st->sz = (dk3_um_t)(stb.st_size);
2243       st->lsz = st->sz;
2244       st->ai = 0x00;
2245 #if DK3_HAVE_LSTAT64
2246       if(lstat64(fn, &lstb) == 0) {
2247         back = 1;
2248 	if(((lstb.st_mode) & S_IFMT) == S_IFLNK) {
2249 	  st->ft |= DK3_FT_SYMLINK;
2250 	  st->lu = (dk3_um_t)(lstb.st_uid);
2251 	  st->lg = (dk3_um_t)(lstb.st_gid);
2252 	  st->ldevice = (dk3_um_t)(lstb.st_dev);
2253 	  st->lrdev = (dk3_um_t)(lstb.st_rdev);
2254 	  st->linode = (dk3_um_t)(lstb.st_ino);
2255 	  st->lnlink = (dk3_um_t)(lstb.st_nlink);
2256 	  st->lcre = (dk3_time_t)(lstb.st_ctime);
2257 	  st->lmod = (dk3_time_t)(lstb.st_mtime);
2258 	  st->lacc = (dk3_time_t)(lstb.st_atime);
2259 	  st->lft = dk3sf_convert_file_type(lstb.st_mode);
2260 	  st->lperm = dk3sf_convert_file_permissions(lstb.st_mode);
2261 	  st->lsz = (dk3_um_t)(lstb.st_size);
2262 	  if(lstb.st_uid != stb.st_uid) {
2263 	    st->ai |= DK3_STAT_AI_USER_DIFFERS;
2264 	  }
2265 	  if(lstb.st_gid != stb.st_gid) {
2266 	    st->ai |= DK3_STAT_AI_GROUP_DIFFERS;
2267 	  }
2268 	  if(lstb.st_dev != stb.st_dev) {
2269 	    st->ai |= DK3_STAT_AI_FAR_LINK;
2270 	  }
2271 	}
2272       } else {
2273         if(app) {
2274 	  /* lstat() failed! */
2275 #if DK3_CHAR_SIZE == 1
2276 	dk3app_log_i3(app, DK3_LL_ERROR, 96, 97, fn);
2277 #else
2278 	dk3app_log_i1(app, DK3_LL_ERROR, 98);
2279 #endif
2280 	}
2281       }
2282 #else
2283       back = 1;
2284 #endif
2285     } else {
2286 #if DK3_HAVE_LSTAT64
2287       if(lstat64(fn, &lstb) == 0) {
2288         back = 1;
2289         st->u = DK3_UM_0;
2290         st->g = DK3_UM_0;
2291         st->device = DK3_UM_0;
2292         st->rdev = DK3_UM_0;
2293         st->inode = DK3_UM_0;
2294         st->nlink = DK3_UM_0;
2295         st->cre = (dk3_time_t)0UL;
2296         st->mod = (dk3_time_t)0UL;
2297         st->acc = (dk3_time_t)0UL;
2298         st->ft = DK3_FT_SYMLINK | DK3_FT_BAD_SYMLINK;
2299         st->perm = 0;
2300         st->sz = DK3_UM_0;
2301         st->ai = 0x00;
2302 	st->lu = (dk3_um_t)(lstb.st_uid);
2303 	st->lg = (dk3_um_t)(lstb.st_gid);
2304 	st->ldevice = (dk3_um_t)(lstb.st_dev);
2305 	st->lrdev = (dk3_um_t)(lstb.st_rdev);
2306 	st->linode = (dk3_um_t)(lstb.st_ino);
2307 	st->lnlink = (dk3_um_t)(lstb.st_nlink);
2308 	st->lcre = (dk3_time_t)(lstb.st_ctime);
2309 	st->lmod = (dk3_time_t)(lstb.st_mtime);
2310 	st->lacc = (dk3_time_t)(lstb.st_atime);
2311 	st->lft = dk3sf_convert_file_type(lstb.st_mode);
2312 	st->lperm = dk3sf_convert_file_permissions(lstb.st_mode);
2313 	st->lsz = (dk3_um_t)(lstb.st_size);
2314       } else {
2315         if(app) {
2316           /* stat failed */
2317 #if DK3_CHAR_SIZE == 1
2318 	  dk3app_log_i3(app, DK3_LL_ERROR, 61, 62, fn);
2319 #else
2320 	  dk3app_log_i1(app, DK3_LL_ERROR, 99);
2321 #endif
2322 	  dk3sf_report_errno(app, errno, dk3sf_function_names[5]);
2323         }
2324       }
2325 #else
2326       if(app) {
2327         /* stat failed */
2328 #if DK3_CHAR_SIZE == 1
2329 	dk3app_log_i3(app, DK3_LL_ERROR, 61, 62, fn);
2330 #else
2331 	dk3app_log_i1(app, DK3_LL_ERROR, 99);
2332 #endif
2333 	dk3sf_report_errno(app, errno, dk3sf_function_names[6]);
2334       }
2335 #endif
2336     }
2337 #else
2338 #if DK3_HAVE_STAT
2339     struct stat stb;
2340 #if DK3_HAVE_LSTAT
2341     struct stat lstb;
2342 #endif
2343 
2344     if(stat(fn, &stb) == 0) {
2345       st->u = (dk3_um_t)(stb.st_uid);
2346       st->g = (dk3_um_t)(stb.st_gid);
2347       st->device = (dk3_um_t)(stb.st_dev);
2348       st->rdev = (dk3_um_t)(stb.st_rdev);
2349       st->inode = (dk3_um_t)(stb.st_ino);
2350       st->nlink = (dk3_um_t)(stb.st_nlink);
2351       st->cre = (dk3_time_t)(stb.st_ctime);
2352       st->mod = (dk3_time_t)(stb.st_mtime);
2353       st->acc = (dk3_time_t)(stb.st_atime);
2354       st->ft = dk3sf_convert_file_type(stb.st_mode);
2355       st->perm = dk3sf_convert_file_permissions(stb.st_mode);
2356       st->sz = (dk3_um_t)(stb.st_size);
2357       st->lsz = st->sz;
2358       st->ai = 0x00;
2359 #if DK3_HAVE_LSTAT
2360       if(lstat(fn, &lstb) == 0) {
2361         back = 1;
2362 	if(((lstb.st_mode) & S_IFMT) == S_IFLNK) {
2363 	  st->ft |= DK3_FT_SYMLINK;
2364           st->lu = (dk3_um_t)(lstb.st_uid);
2365           st->lg = (dk3_um_t)(lstb.st_gid);
2366           st->ldevice = (dk3_um_t)(lstb.st_dev);
2367           st->lrdev = (dk3_um_t)(lstb.st_rdev);
2368           st->linode = (dk3_um_t)(lstb.st_ino);
2369 	  st->lnlink = (dk3_um_t)(lstb.st_nlink);
2370           st->lcre = (dk3_time_t)(lstb.st_ctime);
2371           st->lmod = (dk3_time_t)(lstb.st_mtime);
2372           st->lacc = (dk3_time_t)(lstb.st_atime);
2373           st->lft = dk3sf_convert_file_type(lstb.st_mode);
2374           st->lperm = dk3sf_convert_file_permissions(lstb.st_mode);
2375 	  st->lsz = (dk3_um_t)(lstb.st_size);
2376 	  if(lstb.st_uid != stb.st_uid) {
2377 	    st->ai |= DK3_STAT_AI_USER_DIFFERS;
2378 	  }
2379 	  if(lstb.st_gid != stb.st_gid) {
2380 	    st->ai |= DK3_STAT_AI_GROUP_DIFFERS;
2381 	  }
2382 	  if(lstb.st_dev != stb.st_dev) {
2383 	    st->ai |= DK3_STAT_AI_FAR_LINK;
2384 	  }
2385 	}
2386       } else {
2387         if(app) {
2388 	  /* lstat() failed! */
2389 #if DK3_CHAR_SIZE == 1
2390 	  dk3app_log_i3(app, DK3_LL_ERROR, 96, 97, fn);
2391 #else
2392 	  dk3app_log_i1(app, DK3_LL_ERROR, 98);
2393 #endif
2394 	}
2395       }
2396 #else
2397       back = 1;
2398 #endif
2399     } else {
2400 #if DK3_HAVE_LSTAT
2401       if(lstat(fn,&lstb) == 0) {
2402         back = 1;
2403         st->u = DK3_UM_0;
2404         st->g = DK3_UM_0;
2405         st->device = DK3_UM_0;
2406         st->rdev = DK3_UM_0;
2407         st->inode = DK3_UM_0;
2408         st->nlink = DK3_UM_0;
2409         st->cre = (dk3_time_t)0UL;
2410         st->mod = (dk3_time_t)0UL;
2411         st->acc = (dk3_time_t)0UL;
2412         st->ft = DK3_FT_SYMLINK | DK3_FT_BAD_SYMLINK;
2413         st->perm = 0;
2414         st->sz = DK3_UM_0;
2415         st->ai = 0x00;
2416 	st->lu = (dk3_um_t)(lstb.st_uid);
2417 	st->lg = (dk3_um_t)(lstb.st_gid);
2418 	st->ldevice = (dk3_um_t)(lstb.st_dev);
2419 	st->lrdev = (dk3_um_t)(lstb.st_rdev);
2420 	st->linode = (dk3_um_t)(lstb.st_ino);
2421 	st->lnlink = (dk3_um_t)(lstb.st_nlink);
2422 	st->lcre = (dk3_time_t)(lstb.st_ctime);
2423 	st->lmod = (dk3_time_t)(lstb.st_mtime);
2424 	st->lacc = (dk3_time_t)(lstb.st_atime);
2425 	st->lft = dk3sf_convert_file_type(lstb.st_mode);
2426 	st->lperm = dk3sf_convert_file_permissions(lstb.st_mode);
2427 	st->lsz = (dk3_um_t)(lstb.st_size);
2428       } else {
2429         if(app) {
2430           /* stat() failed! */
2431 #if DK3_CHAR_SIZE == 1
2432 	  dk3app_log_i3(app, DK3_LL_ERROR, 61, 62, fn);
2433 #else
2434 	  dk3app_log_i1(app, DK3_LL_ERROR, 99);
2435 #endif
2436 	  dk3sf_report_errno(app, errno, dk3sf_function_names[8]);
2437         }
2438       }
2439 #else
2440       if(app) {
2441         /* stat() failed! */
2442 #if DK3_CHAR_SIZE == 1
2443 	dk3app_log_i3(app, DK3_LL_ERROR, 61, 62, fn);
2444 #else
2445 	dk3app_log_i1(app, DK3_LL_ERROR, 99);
2446 #endif
2447 	dk3sf_report_errno(app, errno, dk3sf_function_names[7]);
2448       }
2449 #endif
2450     }
2451 #else
2452 #error "Not stat() function available!"
2453 #endif
2454 #endif
2455   }
2456   return back;
2457 }
2458 
2459 
2460 
2461 /**	Check whether opening a file is allowed.
2462 	@param	fn	File name.
2463 	@param	want_to_write	Flag: Write access is wanted.
2464 	@param	app	Application structure for diagnostics, may be NULL.
2465 	@return	1 for write allowed, 0 for write denied.
2466 */
2467 static
2468 int
dk3sf_c8_check_open_file(char const * fn,int want_to_write,dk3_app_t * app)2469 dk3sf_c8_check_open_file(char const *fn, int want_to_write, dk3_app_t *app)
2470 {
2471   int		back = 1;
2472   dk3_stat_t	stb;		/* Check for existing file. */
2473   if(dk3sf_c8_stat_app(&stb, fn, NULL)) {
2474     if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) {
2475       if(app) {
2476         back = 0;
2477         /* Name refers a directory! */
2478 #if DK3_CHAR_SIZE == 1
2479 	dk3app_log_i3(app, DK3_LL_ERROR, 74, 75, fn);
2480 #else
2481 	dk3app_log_i1(app, DK3_LL_ERROR, 76);
2482 #endif
2483       }
2484     }
2485     if(want_to_write) {
2486       if((stb.ft) & DK3_FT_SYMLINK) {
2487         if((stb.ai) & DK3_STAT_AI_USER_DIFFERS) {
2488 	  back = 0;
2489 	  /* Symlink owner is not file owner! */
2490 #if DK3_CHAR_SIZE == 1
2491 	dk3app_log_i3(app, DK3_LL_ERROR, 100, 101, fn);
2492 #else
2493 	dk3app_log_i1(app, DK3_LL_ERROR, 102);
2494 #endif
2495         }
2496       }
2497     }
2498   }
2499   return back;
2500 }
2501 
2502 
2503 
2504 FILE *
dk3sf_c8_fopen_app(char const * fn,char const * mo,dk3_app_t * app)2505 dk3sf_c8_fopen_app(char const *fn, char const *mo, dk3_app_t *app)
2506 {
2507   FILE		*back = NULL;
2508   char const	*moptr = NULL;		/* Traverse mode string. */
2509   int		want_to_write = 0;	/* Flag: Write access wanted. */
2510 
2511   if((fn) && (mo)) {
2512     moptr = mo;
2513     while(*moptr) {
2514       switch(*moptr) {
2515         case 'w': case 'a': case '+': { want_to_write = 1; } break;
2516       }
2517       moptr++;
2518     }
2519     if(dk3sf_c8_check_open_file(fn, want_to_write, app)) {
2520 #if DK3_HAVE_LARGEFILE64_SOURCE && DK3_HAVE_FOPEN64
2521       back = fopen64(fn, mo);
2522 #else
2523       back = fopen(fn, mo);
2524 #endif
2525       if(!(back)) {
2526         if(app) {
2527 	  /* Failed to open file for writing! */
2528 	  if(want_to_write) {
2529 #if DK3_CHAR_SIZE == 1
2530 	    dk3app_log_i3(app, DK3_LL_ERROR, 77, 78, fn);
2531 #else
2532 	    dk3app_log_i1(app, DK3_LL_ERROR, 79);
2533 #endif
2534           } else {
2535 #if DK3_CHAR_SIZE == 1
2536 	    dk3app_log_i3(app, DK3_LL_ERROR, 143, 144, fn);
2537 #else
2538 	    dk3app_log_i1(app, DK3_LL_ERROR, 145);
2539 #endif
2540 	  }
2541 	  dk3sf_report_errno(app, errno, dk3sf_function_names[9]);
2542 	}
2543       }
2544     }
2545   }
2546   return back;
2547 }
2548 
2549 
2550 #if DK3_HAVE_LOCALTIME_R
2551 int
dk3sf_localtime_app(dk3_tm_t * dest,dk3_time_t * timer,dk3_app_t * app)2552 dk3sf_localtime_app(
2553   dk3_tm_t	*dest,
2554   dk3_time_t	*timer,
2555   dk3_app_t	*app
2556 )
2557 {
2558   int			 back = 0;
2559   struct tm		 res, *rp;
2560   if((dest) && (timer)) {
2561     if((rp = localtime_r(timer, &res)) != NULL) {
2562       back = 1;
2563       dest->Y = 1900 + rp->tm_year;
2564       dest->M = 1 + rp->tm_mon;
2565       dest->D = rp->tm_mday;
2566       dest->h = rp->tm_hour;
2567       dest->m = rp->tm_min;
2568       dest->s = rp->tm_sec;
2569     } else {
2570       if(app) {
2571         /* ERROR: localtime_r failed! */
2572 	dk3app_log_i1(app, DK3_LL_ERROR, 268);
2573 	dk3sf_report_errno(app, errno, dk3sf_function_names[10]);
2574       }
2575     }
2576   }
2577   return back;
2578 }
2579 
2580 int
dk3sf_c8_time_convert_app(dkChar * dest,size_t sz,dk3_time_t const * timer,dk3_app_t * app)2581 dk3sf_c8_time_convert_app(
2582   dkChar *dest, size_t sz, dk3_time_t const *timer, dk3_app_t *app
2583 )
2584 {
2585   int back = 0;
2586   char buffer[64];	/* Buffer. */
2587   struct tm res, *rp;	/* Conversion result. */
2588   if((dest) && (sz) && (timer)) {
2589     rp = localtime_r(timer, &res);
2590     if(rp) {
2591       sprintf(
2592         buffer,
2593 	"%04d-%02d-%02d %02d:%02d:%02d",
2594 	(1900 + rp->tm_year),
2595 	(1 + rp->tm_mon),
2596 	rp->tm_mday,
2597 	rp->tm_hour,
2598 	rp->tm_min,
2599 	rp->tm_sec
2600       );
2601       if(sz > dk3str_c8_len(buffer)) {
2602         dk3str_c8_cpy_not_overlapped(dest, buffer);
2603 	back = 1;
2604       } else {
2605         if(app) {
2606 	  /* Buffer too small! */
2607 	  dk3app_log_i1(app, DK3_LL_ERROR, 38);
2608 	}
2609       }
2610     } else {
2611       if(app) {
2612         /* localtime_r failed! */
2613 	dk3app_log_i1(app, DK3_LL_ERROR, 80);
2614 	dk3sf_report_errno(app, errno, dk3sf_function_names[10]);
2615       }
2616     }
2617   }
2618   return back;
2619 }
2620 #else
2621 #error	"Function localtime_r() not available!"
2622 #endif
2623 
2624 
2625 
2626 #if DK3_HAVE_GETCWD || DK3_HAVE__GETCWD
2627 int
dk3sf_c8_getcwd_app(char * dest,size_t sz,dk3_app_t * app)2628 dk3sf_c8_getcwd_app(char *dest, size_t sz, dk3_app_t *app)
2629 {
2630   int back = 0;
2631   if((dest) && (sz)) {
2632 #if DK3_HAVE_GETCWD
2633     if(getcwd(dest, sz))
2634 #else
2635     if(_getcwd(dest, sz))
2636 #endif
2637     {
2638       back = 1;
2639     } else {
2640       if(app) {
2641         switch(errno) {
2642 #ifdef ERANGE
2643 	  case ERANGE: {
2644 	    /* Buffer too small! */
2645 	    dk3app_log_i1(app, DK3_LL_ERROR, 38);
2646 	  } break;
2647 #endif
2648 	  default: {
2649 	    dk3app_log_i1(app, DK3_LL_ERROR, 53);
2650 	    dk3sf_report_errno(app, errno, dk3sf_function_names[11]);
2651 	  } break;
2652 	}
2653       }
2654     }
2655   }
2656   return back;
2657 }
2658 #else
2659 #error	"Neither getcwd() or _getcwd() available!"
2660 #endif
2661 
2662 
2663 
2664 /**	Check whether or not a file is executable.
2665 	@param	f	File name.
2666 	@return	1 for exectuable, 0 for not executable.
2667 */
2668 static
2669 int
dk3sf_c8_check_exec(char const * f)2670 dk3sf_c8_check_exec(char const *f)
2671 {
2672   int		back = 0;
2673   int		testperm;	/* Permissions of file. */
2674   dk3_stat_t	stb;		/* stat() result to check for file. */
2675 
2676   if(dk3sf_c8_stat_app(&stb, f, NULL)) {
2677     if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_REGULAR) {
2678       testperm = (DK3_FPERM_U_EXEC | DK3_FPERM_G_EXEC | DK3_FPERM_O_EXEC);
2679       if((stb.perm) & testperm) {
2680         back = 1;
2681       } else {
2682       }
2683     } else {
2684     }
2685   } else {
2686   }
2687   return back;
2688 }
2689 
2690 
2691 
2692 int
dk3sf_c8_find_exec_app(char * d,size_t s,char const * w,char const * c,dk3_app_t * app)2693 dk3sf_c8_find_exec_app(
2694   char *d, size_t s, char const *w, char const *c, dk3_app_t *app
2695 )
2696 {
2697   int		back = 0;
2698   int		cc = 0;			/* Flag: Can continue. */
2699   char		*pathcopy = NULL;	/* Copy of parent directory. */
2700   char		*p = NULL;
2701   char		*pn = NULL;
2702   size_t	tsl = 0;		/* Needed buffer length. */
2703 
2704   if((d) && (s) && (w) && (c)) {
2705     if(dk3str_c8_chr(c, DK3_C8_SEP)) {
2706       if(dk3str_c8_is_abs_path(c)) {
2707         if(dk3str_c8_len(c) < s) {
2708 	  dk3str_c8_cpy_not_overlapped(d, c);
2709 	  back = 1;
2710 	} else {
2711 	  if(app) {
2712 	    /* c too long! */
2713 #if DK3_CHAR_SIZE == 1
2714 	  dk3app_log_i3(app, DK3_LL_ERROR, 103, 104, c);
2715 #else
2716 	  dk3app_log_i1(app, DK3_LL_ERROR, 105);
2717 #endif
2718 	  }
2719 	}
2720       } else {
2721         if(dk3str_c8_len(w) < s) {
2722 	  dk3str_c8_cpy_not_overlapped(d, w);
2723 	  back = dk3str_c8_append_path_app(d, s, c, app);
2724 	  if(back) {
2725 	  }
2726 	} else {
2727 	  if(app) {
2728 	    /* w too long! */
2729 #if DK3_CHAR_SIZE == 1
2730 	  dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, w);
2731 #else
2732 	  dk3app_log_i1(app, DK3_LL_ERROR, 87);
2733 #endif
2734 	  }
2735 	}
2736       }
2737     } else {
2738       p = getenv(kw_c8_no_win[1]);
2739       if(p) {
2740         pathcopy = dk3str_dup_app(p, app);
2741 	if(pathcopy) {
2742 	  p = pathcopy; cc = 1;
2743 	  while((p) && (cc) && (back == 0)) {
2744 	    pn = dk3str_c8_chr(p, ':');
2745 	    if(pn) { *(pn++) = '\0'; }
2746 	    if(dk3str_c8_len(p)) {
2747 	      tsl =  dk3str_c8_len(p);
2748 	      tsl += dk3str_c8_len(kw_c8_no_win[0]);
2749 	      tsl += dk3str_c8_len(c);
2750 	      if(tsl < s) {
2751 	        dk3str_c8_cpy_not_overlapped(d, p);
2752 		dk3str_c8_cat(d, kw_c8_no_win[0]);
2753 		dk3str_c8_cat(d, c);
2754 		back = dk3sf_c8_check_exec(d);
2755 	      } else {
2756 	        cc = 0;
2757 		if(app) {
2758 		  /* Destination buffer too small! */
2759 		  dk3app_log_i1(app, DK3_LL_ERROR, 38);
2760 		}
2761 	      }
2762 	    } else {
2763 	      tsl =  dk3str_c8_len(w);
2764 	      tsl += dk3str_c8_len(kw_c8_no_win[0]);
2765 	      tsl += dk3str_c8_len(c);
2766 	      if(tsl < s) {
2767 	        dk3str_c8_cpy_not_overlapped(d, w);
2768 		dk3str_c8_cat(d, kw_c8_no_win[0]);
2769 		dk3str_c8_cat(d, c);
2770 		back = dk3sf_c8_check_exec(d);
2771 	      } else {
2772 	        cc = 0;
2773 		if(app) {
2774 		  /* Destination buffer too small! */
2775 		  dk3app_log_i1(app, DK3_LL_ERROR, 38);
2776 		}
2777 	      }
2778 	    }
2779 	    p = pn;
2780 	  }
2781 	  dk3_delete(pathcopy);
2782 	} else {
2783 	}
2784       } else {
2785         if(app) {
2786 	  /* PATH environment variable not defined. */
2787 	  dk3app_log_i1(app, DK3_LL_ERROR, 106);
2788 	}
2789       }
2790     }
2791   }
2792   return back;
2793 }
2794 
2795 
2796 
2797 int
dk3sf_c8_mkdir_app(char const * p,int mo,dk3_app_t * app)2798 dk3sf_c8_mkdir_app(char const *p, int mo, dk3_app_t *app)
2799 {
2800   int back = 0;
2801   char buffer[DK3_MAX_PATH];	/* File names of parent directories. */
2802   char *ptr = NULL;		/* Current path separator. */
2803   int cc = 0;			/* Flag: Can continue. */
2804   mode_t m = 0;			/* File creation mode. */
2805   dk3_stat_t stb;		/* Check for existance of file or directory. */
2806 
2807   if(p) {
2808     m = dk3sf_convert_back_file_permissions(mo);
2809     if(dk3str_c8_len(p) < sizeof(buffer)) {
2810       dk3str_c8_cpy_not_overlapped(buffer, p);
2811       ptr = buffer; cc = 1;
2812       while((cc) && (ptr)) {
2813         ptr = dk3str_c8_chr(ptr, DK3_C8_SEP);
2814 	if(ptr) {
2815 	  *ptr = '\0';
2816 	  if(dk3str_c8_len(buffer) > 0) {
2817 	    if(dk3sf_c8_stat_app(&stb, buffer, NULL)) {
2818 	      if(((stb.ft) & (~(DK3_FT_SYMLINK))) != DK3_FT_DIRECTORY) {
2819 	        cc = 0;
2820 	        if(app) {
2821 	          /* Not a directory! */
2822 #if DK3_CHAR_SIZE == 1
2823 		  dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer);
2824 #else
2825 		  dk3app_log_i1(app, DK3_LL_ERROR, 83);
2826 #endif
2827 	        }
2828 	      }
2829 	    } else {
2830 #if DK3_HAVE_MKDIR
2831 #if DK3_HAVE_MKDIR2
2832 	      if(mkdir(buffer, m) == 0)
2833 #else
2834 	      if(mkdir(buffer) == 0)
2835 #endif
2836 	      {
2837 #if DK3_HAVE_CHMOD
2838 		(void)chmod(buffer, m);
2839 #endif
2840 	      } else {
2841 	        cc = 0;
2842 	        if(app) {
2843 	          /* Failed to create directory! */
2844 #if DK3_CHAR_SIZE == 1
2845 		  dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer);
2846 #else
2847 		  dk3app_log_i1(app, DK3_LL_ERROR, 86);
2848 #endif
2849 	          dk3sf_report_errno(app, errno, dk3sf_function_names[12]);
2850 	        }
2851 	      }
2852 #else
2853 	      cc = 0;
2854 	      if(app) {
2855 	        /* No mkdir() function available! */
2856 		dk3app_log_i1(app, DK3_LL_ERROR, 107);
2857 	      }
2858 #endif
2859 	    }
2860 	  }
2861 	  *ptr = DK3_C8_SEP;
2862 	  ptr++;
2863 	}
2864       }
2865       if(cc) {
2866 	if(dk3sf_c8_stat_app(&stb, buffer, NULL)) {
2867 	  if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) {
2868 	    back = 1;
2869 	  } else {
2870 	    if(app) {
2871 	      /* Not a directory! */
2872 #if DK3_CHAR_SIZE == 1
2873 	      dk3app_log_i3(app, DK3_LL_ERROR, 81, 82, buffer);
2874 #else
2875 	      dk3app_log_i1(app, DK3_LL_ERROR, 83);
2876 #endif
2877 	    }
2878 	  }
2879 	} else {
2880 #if DK3_HAVE_MKDIR
2881 #if DK3_HAVE_MKDIR2
2882 	  if(mkdir(buffer, m) == 0)
2883 #else
2884 	  if(mkdir(buffer) == 0)
2885 #endif
2886 	  {
2887 	    back = 1;
2888 #if DK3_HAVE_CHMOD
2889 	    (void)chmod(buffer, m);
2890 #endif
2891 	  } else {
2892 #if DK3_CHAR_SIZE == 1
2893 	    dk3app_log_i3(app, DK3_LL_ERROR, 84, 85, buffer);
2894 #else
2895 	    dk3app_log_i1(app, DK3_LL_ERROR, 86);
2896 #endif
2897 	    dk3sf_report_errno(app, errno, dk3sf_function_names[12]);
2898 	  }
2899 #else
2900 	  if(app) {
2901 	    /* No mkdir() function available! */
2902 	    dk3app_log_i1(app, DK3_LL_ERROR, 107);
2903 	  }
2904 #endif
2905 	}
2906       }
2907     } else {
2908       if(app) {
2909         /* Path too long! */
2910 #if DK3_CHAR_SIZE == 1
2911         dk3app_log_i3(app, DK3_LL_ERROR, 59, 60, p);
2912 #else
2913         dk3app_log_i1(app, DK3_LL_ERROR, 87);
2914 #endif
2915       }
2916     }
2917   }
2918   return back;
2919 }
2920 
2921 
2922 int
dk3sf_c8_get_hostname_app(char * db,size_t sz,dk3_app_t * app)2923 dk3sf_c8_get_hostname_app(char *db, size_t sz, dk3_app_t *app)
2924 {
2925   int back = 0;
2926   char *ptr = NULL;	/* Begin of DNS domain name. */
2927   if((db) && (sz)) {
2928     if(gethostname(db, sz) == 0) {
2929       back = 1;
2930       ptr = dk3str_c8_chr(db, '.');
2931       if(ptr) {
2932         *ptr = '\0';
2933       }
2934     } else {
2935       if(app) {
2936         /* ERROR: Failed to find host name! */
2937 	dk3app_log_i1(app, DK3_LL_ERROR, 131);
2938 	dk3sf_report_errno(app, errno, dk3sf_function_names[13]);
2939       }
2940     }
2941   }
2942   return back;
2943 }
2944 
2945 
2946 
2947 #if DK3_CHAR_SIZE > 1
2948 #error	"dkChar must be 8 bit on non-Windows systems!"
2949 #else
2950 /* +++ non-Windows, dkChar 8 bit +++ */
2951 
2952 
2953 
2954 int
dk3sf_fgets_fn_app(dkChar * db,size_t sz,FILE * fi,dkChar const * fn,dk3_app_t * app)2955 dk3sf_fgets_fn_app(
2956   dkChar *db, size_t sz, FILE *fi, dkChar const *fn, dk3_app_t *app
2957 )
2958 {
2959   int back = 0;
2960   if((db) && (sz) && (fi)) {
2961     if(fgets(db, (int)sz, fi)) {
2962       back = 1;
2963     } else {
2964       if(!feof(fi)) {
2965         if(app) {
2966 	  if(fn) {
2967 	    dk3app_log_i3(app, DK3_LL_ERROR, 346, 347, fn);
2968 	  } else {
2969 	    dk3app_log_i1(app, DK3_LL_ERROR, 345);
2970 	  }
2971 	  dk3sf_report_errno(app, errno, dk3sf_function_names[25]);
2972 	}
2973       }
2974     }
2975   }
2976   return back;
2977 }
2978 
2979 
2980 
2981 int
dk3sf_fputs_fn_app(dkChar const * st,FILE * fi,dkChar const * fn,dk3_app_t * app)2982 dk3sf_fputs_fn_app(dkChar const *st,FILE *fi,dkChar const *fn,dk3_app_t *app)
2983 {
2984   int back = 0;
2985   if((st) && (fi)) {
2986     if(fputs(st, fi) >= 0) {
2987       back = 1;
2988     } else {
2989       if(app) {
2990         if(fn) {
2991 	  dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn);
2992 	} else {
2993 	  dk3app_log_i1(app, DK3_LL_ERROR, 120);
2994 	}
2995 	dk3sf_report_errno(app, errno, dk3sf_function_names[23]);
2996       }
2997     }
2998   }
2999   return back;
3000 }
3001 
3002 
3003 
3004 int
dk3sf_fputc_fn_app(dkChar ch,FILE * fi,dkChar const * fn,dk3_app_t * app)3005 dk3sf_fputc_fn_app(dkChar ch, FILE *fi, dkChar const *fn, dk3_app_t *app)
3006 {
3007   int back = 0;
3008   if(fi) {
3009     if(fputc(ch, fi) != EOF) {
3010       back = 1;
3011     } else {
3012       if(app) {
3013         if(fn) {
3014 	  dk3app_log_i3(app, DK3_LL_ERROR, 343, 344, fn);
3015 	} else {
3016 	  dk3app_log_i1(app, DK3_LL_ERROR, 120);
3017 	}
3018 	dk3sf_report_errno(app, errno, dk3sf_function_names[24]);
3019       }
3020     }
3021   }
3022   return back;
3023 }
3024 
3025 
3026 
3027 void
dk3sf_initialize_stdout(void)3028 dk3sf_initialize_stdout(void)
3029 {
3030 }
3031 
3032 
3033 
3034 void
dk3sf_initialize_stderr(void)3035 dk3sf_initialize_stderr(void)
3036 {
3037 }
3038 
3039 
3040 
3041 void
dk3sf_initialize_file(FILE * DK3_ARG_UNUSED (fipo))3042 dk3sf_initialize_file(FILE * DK3_ARG_UNUSED(fipo) )
3043 {
3044   DK3_UNUSED_ARG(fipo)
3045 }
3046 
3047 
3048 
3049 /* --- non-Windows, dkChar 8 bit --- */
3050 #endif
3051 
3052 /* --- non-Windows --- */
3053 #endif
3054 
3055 
3056 
3057 int
dk3sf_must_expand(dkChar const * fn)3058 dk3sf_must_expand(dkChar const *fn)
3059 {
3060   int back = 0;
3061 
3062   if(fn) {
3063 #if DK3_ON_WINDOWS
3064     dkChar const *ptr;
3065     ptr = fn;
3066     while((*ptr) && (back == 0)) {
3067       switch(*ptr) {
3068         case dkT('?'):
3069 	case dkT('*'):
3070 	{
3071 	  back = 1;
3072 	}
3073 	break;
3074       }
3075       ptr++;
3076     }
3077 #endif
3078   }
3079   return back;
3080 }
3081 
3082 
3083 
3084 int
dk3sf_c8_fputc(char c,FILE * f)3085 dk3sf_c8_fputc(char c, FILE *f)
3086 {
3087   int back = 0;
3088   if(f) {
3089 #if DK3_CHAR_SIZE > 1
3090 #if DK3_CHAR_SIZE > 2
3091     if(fputwc((((wchar_t)c) & 0x000000FFUL), f) != WEOF) {
3092       back = 1;
3093     }
3094 #else
3095     if(fputwc((((wchar_t)c) & 0x00FFU), f) != WEOF) {
3096       back = 1;
3097     }
3098 #endif
3099 #else
3100     if(fputc(c, f) != EOF) {
3101       back = 1;
3102     }
3103 #endif
3104   }
3105   return back;
3106 }
3107 
3108 
3109 
3110 int
dk3sf_c8_fputs(char const * s,FILE * f)3111 dk3sf_c8_fputs(char const *s, FILE *f)
3112 {
3113   int back = 0;
3114   char const *ptr = NULL;
3115   if((s) && (f)) {
3116     back = 1;
3117     ptr = s;
3118     while(*ptr) {
3119       if(!dk3sf_c8_fputc(*(ptr++), f)) {
3120         back = 0;
3121       }
3122     }
3123   }
3124   return back;
3125 }
3126 
3127 
3128 
3129 size_t
dk3sf_read_app(int fd,void * buf,size_t s,dk3_app_t * app)3130 dk3sf_read_app(int fd, void *buf, size_t s, dk3_app_t *app)
3131 {
3132   size_t back = 0;
3133 
3134   if((buf) && (s)) {
3135 #if DK3_ON_WINDOWS
3136     int		rb;
3137 
3138     rb = _read(fd, buf, (unsigned int)s);
3139     if(rb >= 0) {
3140       back = (size_t)rb;
3141     } else {
3142       /* ERROR: Read failed! */
3143       dk3app_log_i1(app, DK3_LL_ERROR, 124);
3144     }
3145 
3146 #else
3147 
3148 #if DK3_HAVE_READ
3149     ssize_t	rb = 0;		/* Number of bytes read. */
3150 
3151     rb = read(fd, buf, s);
3152     if(rb >= (ssize_t)0) {
3153       back = (size_t)rb;
3154     } else {
3155       if(app) {
3156         /* ERROR: Read failed! */
3157 	dk3app_log_i1(app, DK3_LL_ERROR, 124);
3158 	dk3sf_report_errno(app, errno, dk3sf_function_names[14]);
3159       }
3160     }
3161 #else
3162 #if DK3_HAVE__READ
3163     ssize_t	rb = 0;		/* Number of bytes read. */
3164 
3165     rb = _read(fd, buf, s);
3166     if(rb >= (ssize_t)0) {
3167       back = (size_t)rb;
3168     } else {
3169       if(app) {
3170         /* ERROR: Read failed! */
3171 	dk3app_log_i1(app, DK3_LL_ERROR, 124);
3172 	dk3sf_report_errno(app, errno, dk3sf_function_names[15]);
3173       }
3174     }
3175 #else
3176 #error	"No read() function available!"
3177 #endif
3178 #endif
3179 
3180 #endif
3181   }
3182   return back;
3183 }
3184 
3185 
3186 
3187 int
dk3sf_write_app(int fd,char const * buf,size_t s,dk3_app_t * app)3188 dk3sf_write_app(int fd, char const *buf, size_t s, dk3_app_t *app)
3189 {
3190   int back = 0;
3191   if((buf) && (s)) {
3192 #if DK3_ON_WINDOWS
3193     int		wb;
3194     wb = _write(fd, buf, (unsigned int)s);
3195     if(wb >= 0) {
3196       if((size_t)wb == s) {
3197         back = 1;
3198       } else {
3199         if(app) {
3200           /* ERROR: Not all bytes written! */
3201 	  dk3app_log_write_error(app, DK3_LL_ERROR, s, wb);
3202 	}
3203       }
3204     } else {
3205       if(app) {
3206         /* ERROR: Write failed! */
3207 	dk3app_log_i1( app, DK3_LL_ERROR, 173);
3208       }
3209     }
3210 #else
3211 #if DK3_HAVE_WRITE
3212     ssize_t	wb;
3213     wb = write(fd, buf, s);
3214     if(wb >= 0) {
3215       if((size_t)wb == s) {
3216         back = 1;
3217       } else {
3218         if(app) {
3219           /* ERROR: Not all bytes written! */
3220 	  dk3app_log_write_error(app, DK3_LL_ERROR, s, (size_t)wb);
3221 	}
3222       }
3223     } else {
3224       if(app) {
3225         /* ERROR: Write failed! */
3226 	dk3app_log_i1(app, DK3_LL_ERROR, 173);
3227 	dk3sf_report_errno(app, errno, dk3sf_function_names[16]);
3228       }
3229     }
3230 #else
3231 #if DK3_HAVE__WRITE
3232     ssize_t	wb;
3233     wb = _write(fd, buf, s);
3234     if(wb >= 0) {
3235       if((size_t)wb == s) {
3236         back = 1;
3237       } else {
3238         if(app) {
3239           /* ERROR: Not all bytes written! */
3240 	  dk3app_log_write_error(app, DK3_LL_ERROR, s, wb);
3241 	}
3242       }
3243     } else {
3244       if(app) {
3245         /* ERROR: Write failed! */
3246 	dk3app_log_i1(app, DK3_LL_ERROR, 173);
3247 	dk3sf_report_errno(app, errno, dk3sf_function_names[17]);
3248       }
3249     }
3250 #else
3251 #error	"No write() function available!"
3252 #endif
3253 #endif
3254 #endif
3255   }
3256   return  back;
3257 }
3258 
3259 
3260 size_t
dk3sf_fread_app(void * db,size_t sz,size_t ne,FILE * fi,dk3_app_t * app)3261 dk3sf_fread_app(void *db, size_t sz, size_t ne, FILE *fi, dk3_app_t *app)
3262 {
3263   size_t back = 0;
3264   if((db) && (sz) && (ne) && (fi)) {
3265 #if DK3_ON_WINDOWS
3266     back = fread(db, sz, ne, fi);
3267     if(back < ne) {
3268       if(ferror(fi)) {
3269         if(app) {
3270 	  dk3app_log_i1(app, DK3_LL_ERROR, 124);
3271 	}
3272       }
3273       clearerr(fi);
3274     }
3275 #else
3276 #if DK3_HAVE_FREAD
3277     back = fread(db, sz, ne, fi);
3278     if(back < ne) {
3279       if(ferror(fi)) {
3280         if(app) {
3281 	  dk3app_log_i1(app, DK3_LL_ERROR, 124);
3282 	  dk3sf_report_errno(app, errno, dk3sf_function_names[18]);
3283 	}
3284       } clearerr(fi);
3285     }
3286 #else
3287 #if DK3_HAVE__FREAD
3288     back = _fread(db, sz, ne, fi);
3289     if(back < ne) {
3290       if(ferror(fi)) {
3291         if(app) {
3292 	  dk3app_log_i1(app, DK3_LL_ERROR, 124);
3293 	  dk3sf_report_errno(app, errno, dk3sf_function_names[19]);
3294 	}
3295       } clearerr(fi);
3296     }
3297 #else
3298 #error	"No fread() function available!"
3299 #endif
3300 #endif
3301 #endif
3302   }
3303   return back;
3304 }
3305 
3306 
3307 
3308 int
dk3sf_fwrite_app(void const * sb,size_t sz,size_t ne,FILE * fi,dk3_app_t * app)3309 dk3sf_fwrite_app(void const *sb, size_t sz, size_t ne, FILE *fi, dk3_app_t *app)
3310 {
3311   int back = 0;
3312   if((sb) && (sz) && (ne) && (fi)) {
3313 #if DK3_ON_WINDOWS
3314     size_t wb;
3315     wb = fwrite(sb, sz, ne, fi);
3316     if(wb == ne) {
3317       back = 1;
3318     } else {
3319       if(app) {
3320         dk3app_log_fwrite_error(app, DK3_LL_ERROR, ne, wb);
3321       }
3322     }
3323 #else
3324 #if DK3_HAVE_FWRITE
3325     size_t wb;
3326     wb = fwrite(sb, sz, ne, fi);
3327     if(wb == ne) {
3328       back = 1;
3329     } else {
3330       if(app) {
3331         dk3app_log_fwrite_error(app, DK3_LL_ERROR, ne, wb);
3332 	dk3sf_report_errno(app, errno, dk3sf_function_names[20]);
3333       }
3334     }
3335 #else
3336 #if DK3_HAVE__FWRITE
3337     size_t wb;
3338     wb = _fwrite(sb, sz, ne, fi);
3339     if(wb == ne) {
3340       back = 1;
3341     } else {
3342       if(app) {
3343         dk3app_log_fwrite_error(app, DK3_LL_ERROR, ne, wb);
3344 	dk3sf_report_errno(app, errno, dk3sf_function_names[21]);
3345       }
3346     }
3347 #else
3348 #error	"No fwrite() function available!"
3349 #endif
3350 #endif
3351 #endif
3352   }
3353   return back;
3354 }
3355 
3356 
3357 
3358 int
dk3sf_inspect_bom_skip_app(dkChar const * fn,int dv,size_t * skb,dk3_app_t * app)3359 dk3sf_inspect_bom_skip_app(
3360   dkChar const	*fn,
3361   int		 dv,
3362   size_t	*skb,
3363   dk3_app_t	*app
3364 )
3365 {
3366   int		back = -1;
3367   int		found = 0;	/* Flag: Any form of BOM found .*/
3368   FILE		*fipo = NULL;	/* Input file. */
3369   unsigned char	bb[4];		/* Buffer for BOM. */
3370   size_t	rb = 0;		/* Number of bytes read. */
3371 
3372   if(skb) { *skb = 0; }
3373   back = dv;
3374   if(fn) {
3375     fipo = dk3sf_fopen_app(fn, dk3app_not_localized(36), app);
3376     if(fipo) {
3377       rb = dk3sf_fread_app(bb, 1, 4, fipo, app);
3378       /* Check UTF-8 */
3379       if(rb >= 3) {
3380         if((bb[0] == 0xEF) && (bb[1] == 0xBB) && (bb[2] == 0xBF)) {
3381 	  found = 1; back = DK3_FILE_ENCODING_UTF8;
3382 	  if(skb) { *skb = 3; }
3383 	}
3384       }
3385       if(!found) {
3386         if(rb >= 2) {
3387 	  if((bb[0] == 0xFE) && (bb[1] == 0xFF)) {
3388 	    found = 1; back = DK3_FILE_ENCODING_UTF16_MSB_FIRST;
3389 	    if(skb) { *skb = 2; }
3390 	  } else {
3391 	    if((bb[0] == 0xFF) && (bb[1] == 0xFE)) {
3392 	      found = 1; back = DK3_FILE_ENCODING_UTF16_LSB_FIRST;
3393 	      if(skb) { *skb = 2; }
3394 	      if(rb >= 4) {
3395 	        if((bb[2] == 0x00) && (bb[3] == 0x00)) {
3396 		  back = DK3_FILE_ENCODING_UNICODE_LSB_FIRST;
3397 		  if(skb) { *skb = 4; }
3398 		}
3399 	      }
3400 	    }
3401 	  }
3402 	}
3403       }
3404       if(!found) {
3405         if(rb >= 4) {
3406 	  if((bb[0] == 0x00) && (bb[1] == 0x00)
3407 	     && (bb[2] == 0xFE) && (bb[3] == 0xFF)
3408 	  )
3409 	  {
3410 	    found = 1; back = DK3_FILE_ENCODING_UNICODE_MSB_FIRST;
3411 	    if(skb) { *skb = 4; }
3412 	  }
3413 	}
3414       }
3415       if(!found) {
3416         /* No BOM found */
3417 	back = dv;
3418       }
3419       fclose(fipo);
3420     }
3421   }
3422   return back;
3423 }
3424 
3425 
3426 
3427 int
dk3sf_inspect_bom_app(dkChar const * fn,int dv,dk3_app_t * app)3428 dk3sf_inspect_bom_app(dkChar const *fn, int dv, dk3_app_t *app)
3429 {
3430   int back;
3431   back = dk3sf_inspect_bom_skip_app(fn, dv, NULL, app);
3432   return back;
3433 }
3434 
3435 
3436 
3437 int
dk3sf_apply_bom_to_file_app(FILE * fipo,int enc,dk3_app_t * app)3438 dk3sf_apply_bom_to_file_app(FILE *fipo, int enc, dk3_app_t *app)
3439 {
3440   int back = 0;
3441 
3442 #if DK3_ON_WINDOWS
3443   if(fipo) {
3444     switch(enc) {
3445       case DK3_FILE_ENCODING_ASCII: {
3446         back = 1;
3447       } break;
3448       case DK3_FILE_ENCODING_UTF8: {
3449         back = 1;
3450 #if defined(_MSC_VER)
3451 	_setmode(_fileno(fipo), _O_U8TEXT);
3452 #endif
3453       } break;
3454       case DK3_FILE_ENCODING_UTF16_LSB_FIRST: {
3455 #if defined(_MSC_VER)
3456         _setmode(_fileno(fipo), _O_U16TEXT);
3457 #endif
3458       } break;
3459       default: {
3460         /* ERROR: Encoding can not be handled directly by file! */
3461 	dk3app_log_i1(app, DK3_LL_ERROR, 204);
3462       } break;
3463     }
3464   }
3465 #else
3466   if(fipo) {
3467     switch(enc) {
3468       case DK3_FILE_ENCODING_ASCII: case DK3_FILE_ENCODING_UTF8: {
3469         back = 1;
3470       } break;
3471       default: {
3472         /* ERROR: Encoding can not be handled direcly by file! */
3473 	dk3app_log_i1(app, DK3_LL_ERROR, 204);
3474       } break;
3475     }
3476   }
3477 #endif
3478 
3479   return back;
3480 }
3481 
3482 
3483 
3484 int
dk3sf_is_dir_app(dkChar const * n,dk3_app_t * app)3485 dk3sf_is_dir_app(dkChar const *n, dk3_app_t *app)
3486 {
3487   int back = 0;
3488   dk3_stat_t	stb;
3489   if(dk3sf_stat_app(&stb, n, app)) {
3490     if(((stb.ft) & (~(DK3_FT_SYMLINK))) == DK3_FT_DIRECTORY) {
3491       back = 1;
3492     } else {
3493       if(app) {
3494         /* ERROR: n is not a directory! */
3495 	dk3app_log_i3(app, DK3_LL_ERROR, 202, 203, n);
3496       }
3497     }
3498   }
3499   return back;
3500 }
3501 
3502 
3503 
3504 int
dk3sf_chdir_app(dkChar const * dn,dk3_app_t * app)3505 dk3sf_chdir_app(dkChar const *dn, dk3_app_t *app)
3506 {
3507   int back = 0;
3508   if(dn) {
3509 #if DK3_CHAR_SIZE > 1
3510 #if DK3_ON_WINDOWS
3511     if(_wchdir(dn) == 0) {
3512       back = 1;
3513     } else {
3514       if(app) {
3515         dk3app_log_i3(app, DK3_LL_ERROR, 242, 243, dn);
3516       }
3517     }
3518 #else
3519 #error	"No chdir() function (16-bit) on non-Windows systems!"
3520 #endif
3521 #else
3522 #if DK3_ON_WINDOWS
3523     if(chdir(dn) == 0) {
3524       back = 1;
3525     } else {
3526       if(app) {
3527         dk3app_log_i3(app, DK3_LL_ERROR, 242, 243, dn);
3528       }
3529     }
3530 #else
3531 #if DK3_HAVE_CHDIR
3532     if(chdir(dn) == 0) {
3533       back = 1;
3534     } else {
3535       if(app) {
3536         dk3app_log_i3(app, DK3_LL_ERROR, 242, 243, dn);
3537 	dk3sf_report_errno(app, errno, dk3sf_function_names[22]);
3538       }
3539     }
3540 #else
3541 #error	"No chdir() function available!"
3542 #endif
3543 #endif
3544 #endif
3545   }
3546   return back;
3547 }
3548 
3549 
3550 
3551 int
dk3sf_must_rebuild(dkChar const * dn,dkChar const * sn)3552 dk3sf_must_rebuild(dkChar const *dn, dkChar const *sn)
3553 {
3554   int 		back = 1;
3555   dk3_stat_t	stbs;
3556   dk3_stat_t	stbd;
3557   if((dn) && (sn)) {
3558     if(dk3sf_stat_app(&stbd, dn, NULL)) {
3559       if(dk3sf_stat_app(&stbs, sn, NULL)) {
3560         if(stbd.mod > stbs.mod) {
3561 	  back = 0;
3562 	}
3563       }
3564     }
3565   }
3566   return back;
3567 }
3568 
3569 
3570 
3571 int
dk3sf_filename_to_c8(char * fnb,size_t szfnb,dkChar const * src,dk3_app_t * app)3572 dk3sf_filename_to_c8(
3573   char *fnb, size_t szfnb, dkChar const *src, dk3_app_t *app
3574 )
3575 {
3576   int		back	= 0;
3577   if((fnb) && (szfnb) && (src)) {
3578 #if DK3_CHAR_SIZE > 1
3579 #if DK3_CHAR_SIZE > 2
3580 #error	"Only 1- or 2-byte character support available!"
3581 #else
3582 #if DK3_ON_WINDOWS
3583     back = dk3str_cnv_c16_to_c8p_app(fnb, szfnb, src, app);
3584 #else
3585 #error "2-byte character support is available on Windows platforms only!"
3586 #endif
3587 #endif
3588 #else
3589     if(dk3str_len(src) < szfnb) {
3590       dk3str_cpy_not_overlapped(fnb, src);
3591       back = 1;
3592     } else {
3593       /* ERROR: File name too long! */
3594       if(app) {
3595         dk3app_log_i3(app, DK3_LL_ERROR, 65, 66, src);
3596       }
3597     }
3598 #endif
3599   }
3600   return back;
3601 }
3602 
3603 
3604 
3605 int
dk3sf_scan_double_app(dkChar const * txt,double * v,dk3_app_t * app)3606 dk3sf_scan_double_app(dkChar const *txt, double *v, dk3_app_t *app)
3607 {
3608   int	back = 0;
3609 
3610   if((txt) && (v)) {
3611 #if DK3_HAVE_SETLOCALE
3612     char oldlocale[64];
3613     char *lcptr;
3614 
3615     lcptr = setlocale(LC_NUMERIC, NULL);
3616     if(lcptr) {
3617       if(dk3str_c8_len(lcptr) < sizeof(oldlocale)) {
3618         dk3str_c8_cpy_not_overlapped(oldlocale, lcptr);
3619 	setlocale(LC_NUMERIC, "C");
3620 #if VERSION_BEFORE_20140716
3621 	back = dk3sf_sscanf3(txt,dkT("%lf"),v);
3622 #else
3623 	back = dk3ma_d_from_string(v, txt, NULL);
3624 #endif
3625 	setlocale(LC_NUMERIC, oldlocale);
3626       } else {
3627 #if VERSION_BEFORE_20140716
3628         dk3sf_sscanf3(txt,dkT("%lf"),v);
3629 #else
3630 	back = dk3ma_d_from_string(v, txt, NULL);
3631 #endif
3632 	if(app) {
3633 	  /* ERROR: Failed to save current locale! */
3634 	  dk3app_log_i1(app, DK3_LL_ERROR, 254);
3635 	}
3636       }
3637     } else {
3638 #if VERSION_BEFORE_20140716
3639       dk3sf_sscanf3(txt,dkT("%lf"),v);
3640 #else
3641       back = dk3ma_d_from_string(v, txt, NULL);
3642 #endif
3643       if(app) {
3644         /* ERROR: Failed to obtain current locale! */
3645 	dk3app_log_i1(app, DK3_LL_ERROR, 253);
3646       }
3647     }
3648 #else
3649 #if VERSION_BEFORE_20140716
3650     back = dk3sf_sscanf3(txt,dkT("%lf"),v);
3651 #else
3652     back = dk3ma_d_from_string(v, txt, NULL);
3653 #endif
3654 #endif
3655   }
3656   return back;
3657 }
3658 
3659 
3660 
3661 int
dk3sf_get_max_files(void)3662 dk3sf_get_max_files(void)
3663 {
3664   int back = 1024;
3665 #if DK3_HAVE_SYS_RESOURCE_H
3666 #if DK3_HAVE_GETRLIMIT
3667     struct rlimit	rl;
3668     if(getrlimit(RLIMIT_NOFILE, &rl)  >= 0) {
3669       if(rl.rlim_max != RLIM_INFINITY) {
3670         /* Open file descriptors are int, so conversion to int is ok here */
3671         back = (int)(rl.rlim_max);
3672       }
3673     }
3674 #endif
3675 #endif
3676   return  back;
3677 }
3678 
3679 
3680 
3681 
3682 int
dk3sf_fclose_fn_app(FILE * fipo,dkChar const * fn,dk3_app_t * app)3683 dk3sf_fclose_fn_app(FILE *fipo, dkChar const *fn, dk3_app_t *app)
3684 {
3685   int		 back = 0;
3686   int		 res;
3687   if(fipo) {
3688     res = fclose(fipo);
3689     if(0 == res) {
3690       back = 1;
3691     } else {
3692       if(fn) {
3693         dk3app_log_i3(app, DK3_LL_ERROR, 341, 342, fn);
3694       } else {
3695         dk3app_log_i1(app, DK3_LL_ERROR, 340);
3696       }
3697       dk3sf_report_errno(app, errno, dk3sf_function_names[1]);
3698     }
3699   }
3700   return back;
3701 }
3702 
3703 
3704 
3705 int
dk3sf_fclose_app(FILE * fipo,dk3_app_t * app)3706 dk3sf_fclose_app(FILE *fipo, dk3_app_t *app)
3707 {
3708   int back = 0;
3709   back = dk3sf_fclose_fn_app(fipo, NULL, app);
3710   return back;
3711 }
3712 
3713 
3714 
3715 int
dk3sf_fgets(dkChar * db,size_t sz,FILE * fi)3716 dk3sf_fgets(dkChar *db, size_t sz, FILE *fi)
3717 {
3718   int back;
3719   back = dk3sf_fgets_fn_app(db, sz, fi, NULL, NULL);
3720   return back;
3721 }
3722 
3723 
3724 
3725 int
dk3sf_fputs(dkChar const * st,FILE * fi)3726 dk3sf_fputs(dkChar const *st, FILE *fi)
3727 {
3728   int back;
3729   back = dk3sf_fputs_fn_app(st, fi, NULL, NULL);
3730   return back;
3731 }
3732 
3733 
3734 
3735 int
dk3sf_fputt(dkChar const * const * txt,FILE * fi)3736 dk3sf_fputt(dkChar const * const *txt, FILE *fi)
3737 {
3738   dkChar const * const	*ptr;
3739   int		 	 back = 0;
3740   if((txt) && (fi)) {
3741     back = 1;
3742     ptr = txt;
3743     while(*ptr) {
3744       if(!(dk3sf_fputs(*(ptr++), fi))) {
3745         back = 0;
3746       }
3747       dk3sf_fputc(dkT('\n'), fi);
3748     }
3749   }
3750   return back;
3751 }
3752 
3753 
3754 int
dk3sf_fputc(dkChar c,FILE * fi)3755 dk3sf_fputc(dkChar c, FILE *fi)
3756 {
3757   int back;
3758   back = dk3sf_fputc_fn_app(c, fi, NULL, NULL);
3759   return back;
3760 }
3761 
3762 
3763 
3764 int
dk3sf_stat_app(dk3_stat_t * st,dkChar const * fn,dk3_app_t * app)3765 dk3sf_stat_app(dk3_stat_t *st, dkChar const *fn, dk3_app_t *app)
3766 {
3767 #if DK3_CHAR_SIZE > 1
3768 #if DK3_CHAR_SIZE > 2
3769 #error "System function for b-byte character strings not available!"
3770 #else
3771 #if DK3_ON_WINDOWS
3772   return(dk3sf_c16_stat_app(st, fn, app));
3773 #else
3774 #error "Wide character functions not defined on non-Windows systems!"
3775 #endif
3776 #endif
3777 #else
3778   return(dk3sf_c8_stat_app(st, fn, app));
3779 #endif
3780 }
3781 
3782 
3783 
3784 FILE *
dk3sf_fopen_app(dkChar const * fn,dkChar const * mo,dk3_app_t * app)3785 dk3sf_fopen_app(dkChar const *fn, dkChar const *mo, dk3_app_t *app)
3786 {
3787 #if DK3_CHAR_SIZE > 1
3788 #if DK3_CHAR_SIZE > 2
3789 #error "System function for b-byte character strings not available!"
3790 #else
3791 #if DK3_ON_WINDOWS
3792   return(dk3sf_c16_fopen_app(fn, mo, app));
3793 #else
3794 #error "Wide character functions not defined on non-Windows systems!"
3795 #endif
3796 #endif
3797 #else
3798   return(dk3sf_c8_fopen_app(fn, mo, app));
3799 #endif
3800 }
3801 
3802 
3803 
3804 int
dk3sf_time_convert_app(dkChar * dest,size_t sz,dk3_time_t const * timer,dk3_app_t * app)3805 dk3sf_time_convert_app(
3806   dkChar		*dest,
3807   size_t		 sz,
3808   dk3_time_t const	*timer,
3809   dk3_app_t		*app
3810 )
3811 {
3812 #if DK3_CHAR_SIZE > 1
3813 #if DK3_CHAR_SIZE > 2
3814 #error "System function for b-byte character strings not available!"
3815 #else
3816 #if DK3_ON_WINDOWS
3817   return(dk3sf_c16_time_convert_app(dest, sz, timer, app));
3818 #else
3819 #error "Wide character functions not defined on non-Windows systems!"
3820 #endif
3821 #endif
3822 #else
3823   return(dk3sf_c8_time_convert_app(dest, sz, timer, app));
3824 #endif
3825 }
3826 
3827 
3828 
3829 int
dk3sf_getcwd_app(dkChar * dest,size_t sz,dk3_app_t * app)3830 dk3sf_getcwd_app(dkChar *dest, size_t sz, dk3_app_t *app)
3831 {
3832 #if DK3_CHAR_SIZE > 1
3833 #if DK3_CHAR_SIZE > 2
3834 #error "System function for b-byte character strings not available!"
3835 #else
3836 #if DK3_ON_WINDOWS
3837   return(dk3sf_c16_getcwd_app(dest, sz, app));
3838 #else
3839 #error "Wide character functions not defined on non-Windows systems!"
3840 #endif
3841 #endif
3842 #else
3843   return(dk3sf_c8_getcwd_app(dest, sz, app));
3844 #endif
3845 }
3846 
3847 
3848 
3849 int
dk3sf_find_exec_app(dkChar * d,size_t s,dkChar const * w,dkChar const * c,dk3_app_t * app)3850 dk3sf_find_exec_app(
3851   dkChar	*d,
3852   size_t	 s,
3853   dkChar const	*w,
3854   dkChar const	*c,
3855   dk3_app_t	*app
3856 )
3857 {
3858 #if DK3_CHAR_SIZE > 1
3859 #if DK3_CHAR_SIZE > 2
3860 #error "System function for b-byte character strings not available!"
3861 #else
3862 #if DK3_ON_WINDOWS
3863   return(dk3sf_c16_find_exec_app(d, s, w, c, app));
3864 #else
3865 #error "Wide character functions not defined on non-Windows systems!"
3866 #endif
3867 #endif
3868 #else
3869   return(dk3sf_c8_find_exec_app(d, s, w, c, app));
3870 #endif
3871 }
3872 
3873 
3874 
3875 int
dk3sf_get_logname_app(dkChar * d,size_t s,dk3_app_t * app)3876 dk3sf_get_logname_app(dkChar *d, size_t s, dk3_app_t *app)
3877 {
3878 #if DK3_CHAR_SIZE > 1
3879 #if DK3_CHAR_SIZE > 2
3880 #error "System function for b-byte character strings not available!"
3881 #else
3882 #if DK3_ON_WINDOWS
3883   return(dk3sf_c16_get_logname_app(d, s, app));
3884 #else
3885 #error "Wide character functions not defined on non-Windows systems!"
3886 #endif
3887 #endif
3888 #else
3889   return(dk3sf_c8_get_logname_app(d, s, app));
3890 #endif
3891 }
3892 
3893 
3894 
3895 int
dk3sf_get_home_app(dkChar * d,size_t s,dk3_app_t * app)3896 dk3sf_get_home_app(dkChar *d, size_t s, dk3_app_t *app)
3897 {
3898 #if DK3_CHAR_SIZE > 1
3899 #if DK3_CHAR_SIZE > 2
3900 #error "System function for b-byte character strings not available!"
3901 #else
3902 #if DK3_ON_WINDOWS
3903   return(dk3sf_c16_get_home_app(d, s, app));
3904 #else
3905 #error "Wide character functions not defined on non-Windows systems!"
3906 #endif
3907 #endif
3908 #else
3909   return(dk3sf_c8_get_home_app(d, s, app));
3910 #endif
3911 }
3912 
3913 
3914 
3915 int
dk3sf_mkdir_app(dkChar const * p,int mo,dk3_app_t * app)3916 dk3sf_mkdir_app(dkChar const *p, int mo, dk3_app_t *app)
3917 {
3918 #if DK3_CHAR_SIZE > 1
3919 #if DK3_CHAR_SIZE > 2
3920 #error "System function for b-byte character strings not available!"
3921 #else
3922 #if DK3_ON_WINDOWS
3923   return(dk3sf_c16_mkdir_app(p, mo, app));
3924 #else
3925 #error "Wide character functions not defined on non-Windows systems!"
3926 #endif
3927 #endif
3928 #else
3929   return(dk3sf_c8_mkdir_app(p, mo, app));
3930 #endif
3931 }
3932 
3933 
3934 
3935 int
dk3sf_remove_file_app(dkChar const * n,dk3_app_t * app)3936 dk3sf_remove_file_app(dkChar const *n, dk3_app_t *app)
3937 {
3938 #if DK3_CHAR_SIZE > 1
3939 #if DK3_CHAR_SIZE > 2
3940 #error "System function for b-byte character strings not available!"
3941 #else
3942 #if DK3_ON_WINDOWS
3943   return(dk3sf_c16_remove_file_app(n, app));
3944 #else
3945 #error "Wide character functions not defined on non-Windows systems!"
3946 #endif
3947 #endif
3948 #else
3949   return(dk3sf_c8_remove_file_app(n, app));
3950 #endif
3951 }
3952 
3953 
3954 
3955 int
dk3sf_remove_dir_app(dkChar const * n,dk3_app_t * app)3956 dk3sf_remove_dir_app(dkChar const *n, dk3_app_t *app)
3957 {
3958 #if DK3_CHAR_SIZE > 1
3959 #if DK3_CHAR_SIZE > 2
3960 #error "System function for b-byte character strings not available!"
3961 #else
3962 #if DK3_ON_WINDOWS
3963   return(dk3sf_c16_remove_dir_app(n, app));
3964 #else
3965 #error "Wide character functions not defined on non-Windows systems!"
3966 #endif
3967 #endif
3968 #else
3969   return(dk3sf_c8_remove_dir_app(n, app));
3970 #endif
3971 }
3972 
3973 
3974 
3975 int
dk3sf_get_hostname_app(dkChar * db,size_t sz,dk3_app_t * app)3976 dk3sf_get_hostname_app(dkChar *db, size_t sz, dk3_app_t *app)
3977 {
3978 #if DK3_CHAR_SIZE > 1
3979 #if DK3_CHAR_SIZE > 2
3980 #error "System function for b-byte character strings not available!"
3981 #else
3982 #if DK3_ON_WINDOWS
3983   return(dk3sf_c16_get_hostname_app(db, sz, app));
3984 #else
3985 #error "Wide character functions not defined on non-Windows systems!"
3986 #endif
3987 #endif
3988 #else
3989   return(dk3sf_c8_get_hostname_app(db, sz, app));
3990 #endif
3991 }
3992 
3993 
3994 
3995 dkChar *
dk3sf_getenv(dkChar const * name)3996 dk3sf_getenv(dkChar const *name)
3997 {
3998 #if DK3_CHAR_SIZE > 1
3999 #if DK3_CHAR_SIZE > 2
4000 #error "System function for b-byte character strings not available!"
4001 #else
4002 #if DK3_ON_WINDOWS
4003   return(dk3sf_c16_getenv(name));
4004 #else
4005 #error "Wide character functions not defined on non-Windows systems!"
4006 #endif
4007 #endif
4008 #else
4009   return(dk3sf_c8_getenv(name));
4010 #endif
4011 }
4012 
4013 
4014 
4015 
4016 /* vim: set ai sw=2 : */
4017 
4018