1 /*
2 Copyright (C) 2015-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: dk4mkdh8.ctr
12 */
13
14 /** @file dk4mkdh8.c The dk4mkdh8 module.
15 */
16
17
18 #include "dk4conf.h"
19 #include <libdk4base/dk4types.h>
20
21 #if DK4_ON_WINDOWS
22 #ifndef WINDOWS_H_INCLUDED
23 #include <windows.h>
24 #define WINDOWS_H_INCLUDED 1
25 #endif
26 #endif
27
28 #include <libdk4c/dk4mkdh8.h>
29
30 #if DK4_HAVE_SYS_STAT_H
31 #ifndef SYS_STAT_H_INCLUDED
32 #include <sys/stat.h>
33 #define SYS_STAT_H_INCLUDED 1
34 #endif
35 #endif
36
37 #if DK4_HAVE_SYS_TYPES_H
38 #ifndef SYS_TYPES_H_INCLUDED
39 #include <sys/types.h>
40 #define SYS_TYPES_H_INCLUDED 1
41 #endif
42 #endif
43
44 #if DK4_HAVE_DIRECT_H
45 #ifndef DIRECT_H_INCLUDED
46 #include <direct.h>
47 #define DIRECT_H_INCLUDED 1
48 #endif
49 #endif
50
51 #if DK4_HAVE_STDLIB_H
52 #ifndef STDLIB_H_INCLUDED
53 #include <stdlib.h>
54 #define STDLIB_H_INCLUDED 1
55 #endif
56 #endif
57
58 #if DK4_HAVE_UNISTD_H
59 #ifndef UNISTD_H_INCLUDED
60 #include <unistd.h>
61 #define UNISTD_H_INCLUDED 1
62 #endif
63 #endif
64
65 #if DK4_HAVE_ERRNO_H
66 #ifndef ERRNO_H_INCLUDED
67 #include <errno.h>
68 #define ERRNO_H_INCLUDED 1
69 #endif
70 #endif
71
72 #ifndef DK4MEM_H_INCLUDED
73 #include <libdk4base/dk4mem.h>
74 #endif
75
76 #ifndef DK4MPL_H_INCLUDED
77 #include <libdk4base/dk4mpl.h>
78 #endif
79
80 #ifndef DK4STR8_H_INCLUDED
81 #include <libdk4base/dk4str8.h>
82 #endif
83
84 #ifndef DK4PATH8_H_INCLUDED
85 #include <libdk4c/dk4path8.h>
86 #endif
87
88 #ifndef DK4STAT8_H_INCLUDED
89 #include <libdk4c/dk4stat8.h>
90 #endif
91
92 #ifndef DK4STAT_H_INCLUDED
93 #include <libdk4c/dk4stat.h>
94 #endif
95
96 #if DK4_HAVE_ASSERT_H
97 #ifndef ASSERT_H_INCLUDED
98 #include <assert.h>
99 #define ASSERT_H_INCLUDED 1
100 #endif
101 #endif
102
103
104
105
106
107
108 #if DK4_ON_WINDOWS
109 /* +++ Windows */
110
111
112
113 /** Check whether c is a character.
114 @param c Byte to check.
115 @return 1 for characters, 0 for other bytes.
116 */
117 static
118 int
dk4mkdir_hierarchy_c8_is_char(char c)119 dk4mkdir_hierarchy_c8_is_char(char c)
120 {
121 int back = 0;
122 if (('a' <= c) && ('z' >= c)) {
123 back = 1;
124 } else {
125 if (('A' <= c) && ('Z' >= c)) {
126 back = 1;
127 }
128 }
129 return back;
130 }
131
132
133
134 int
dk4mkdir_hierarchy_c8_one(const char * fn,int ro,dk4_er_t * erp)135 dk4mkdir_hierarchy_c8_one(const char *fn, int ro, dk4_er_t *erp)
136 {
137 BY_HANDLE_FILE_INFORMATION bhfi;
138 WIN32_FIND_DATAA ffdata;
139 HANDLE ha;
140 DWORD dwattr;
141 int found;
142 int i;
143 int back = 0;
144
145 #if DK4_USE_ASSERT
146 assert(NULL != fn);
147 #endif
148 if (NULL == fn) {
149 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
150 goto finished;
151 }
152 #if 1
153 dwattr = GetFileAttributesA(fn);
154 if (INVALID_FILE_ATTRIBUTES == dwattr) {
155 ha = FindFirstFileA(fn, &ffdata);
156 if (INVALID_HANDLE_VALUE != ha) {
157 dwattr = ffdata.dwFileAttributes;
158 FindClose(ha);
159 }
160 }
161 if (INVALID_FILE_ATTRIBUTES != dwattr) {
162 if (0 != (FILE_ATTRIBUTE_DIRECTORY & dwattr)) {
163 back = 1;
164 } else {
165 if (0 != (FILE_ATTRIBUTE_REPARSE_POINT & dwattr)) {
166 found = 0;
167 for (i = 0; ((3 > i) && (0 == back) && (0 == found)); i++) {
168 ha = CreateFileA(
169 fn,
170 (
171 (0 == i)
172 ? (0)
173 : ((1 == i) ? (FILE_READ_ATTRIBUTES) : (GENERIC_READ))
174 ),
175 (FILE_SHARE_READ | FILE_SHARE_WRITE),
176 NULL,
177 OPEN_EXISTING,
178 (dwattr | FILE_FLAG_BACKUP_SEMANTICS),
179 NULL
180 );
181 if (INVALID_HANDLE_VALUE != ha) {
182 if (GetFileInformationByHandle(ha, &bhfi)) {
183 found = 1;
184 if (0 != (FILE_ATTRIBUTE_DIRECTORY & (bhfi.dwFileAttributes))) {
185 back = 1;
186 }
187 }
188 CloseHandle(ha);
189 }
190 }
191 }
192 if (0 == back) {
193 dk4error_set_simple_error_code(erp, DK4_E_NON_DIR);
194 }
195 }
196 } else {
197 if (0 != ro) {
198 dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
199 } else {
200 #if DK4_WIN_AVOID_CRT || DK4_WIN_DENY_CRT
201 if (CreateDirectoryA(fn, NULL)) {
202 back = 1;
203 } else {
204 dk4error_set_ldetails(
205 erp, DK4_E_CREATE_DIR_FAILED ,
206 (long)((unsigned long)GetLastError())
207 );
208 }
209 #else
210 if (CreateDirectoryA(fn, NULL)) {
211 back = 1;
212 } else {
213 errno = 0;
214 if (0 == _mkdir(fn)) {
215 back = 1;
216 } else {
217 dk4error_set_idetails(erp, DK4_E_MKDIR_FAILED, errno);
218 }
219 }
220 #endif
221 }
222 }
223 #else
224 back = 1;
225 #endif
226
227 finished:
228 return back;
229 }
230
231
232
233 char *
dk4mkdir_hierarchy_c8_first_sep(char * fn,int * bptr,int lc,dk4_er_t * erp)234 dk4mkdir_hierarchy_c8_first_sep(char *fn, int *bptr, int lc, dk4_er_t *erp)
235 {
236 char *pc = NULL;
237 int back = 0;
238 char sc;
239
240 #if DK4_USE_ASSERT
241 assert(NULL != fn);
242 #endif
243 if (NULL == fn) {
244 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
245 goto finished;
246 }
247
248 if ('\\' == *fn) { /* leading bs */
249 if ('\\' == fn[1]) { /* server and share */
250 pc = dk4str8_chr(&(fn[2]), '\\');
251 if (NULL != pc) { /* Share name */
252 pc = dk4str8_chr(&(pc[1]), '\\');
253 if (NULL != pc) { /* First dir */
254 *pc = '\0';
255 back = dk4mkdir_hierarchy_c8_one(fn, 1, erp);
256 *pc = '\\';
257 if (0 != back) {
258 back = 0;
259 pc = dk4str8_chr(&(pc[1]), '\\');
260 if (NULL == pc) {
261 if (0 != lc) {
262 back = dk4mkdir_hierarchy_c8_one(fn, 0, erp);
263 } else {
264 back = 1;
265 }
266 }
267 } else {
268 pc = dk4str8_chr(&(pc[1]), '\\');
269 if (NULL == pc) {
270 if (0 != lc) {
271 back = dk4mkdir_hierarchy_c8_one(fn, 0, erp);
272 }
273 }
274 }
275 } else { /* Share name but no dir */
276 if (0 != lc) {
277 back = dk4mkdir_hierarchy_c8_one(fn, 1, erp);
278 } else {
279 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
280 }
281 }
282 } else {
283 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
284 }
285 } else { /* abs path, no drive */
286 pc = dk4str8_chr(&(fn[1]), '\\');
287 if (NULL == pc) {
288 if (0 != lc) {
289 back = dk4mkdir_hierarchy_c8_one(fn, 0, erp);
290 } else {
291 back = 1;
292 }
293 }
294 }
295 } else { /* no leading bs */
296 if (0 != dk4mkdir_hierarchy_c8_is_char(*fn)) { /* leading char */
297 if (':' == fn[1]) { /* drive */
298 if ('\\' == fn[2]) { /* drive, abs path */
299 sc = fn[3];
300 fn[3] = '\0';
301 back = dk4mkdir_hierarchy_c8_one(fn, 1, erp);
302 fn[3] = sc;
303 if (0 != back) {
304 back = 0;
305 pc = dk4str8_chr(&(fn[3]), '\\');
306 if (NULL == pc) {
307 if (0 != lc) {
308 back = dk4mkdir_hierarchy_c8_one(fn, 0, erp);
309 } else {
310 back = 1;
311 }
312 }
313 }
314 } else { /* drive, rel path */
315 sc = fn[2];
316 fn[2] = '\0';
317 back = dk4mkdir_hierarchy_c8_one(fn, 1, erp);
318 fn[2] = sc;
319 if (0 != back) {
320 back = 0;
321 pc = dk4str8_chr(&(fn[3]), '\\');
322 if (NULL == pc) {
323 if (0 != lc) {
324 back = dk4mkdir_hierarchy_c8_one(fn, 0, erp);
325 } else {
326 back = 1;
327 }
328 }
329 }
330 }
331 } else { /* no drive */
332 pc = dk4str8_chr(fn, '\\');
333 if (NULL == pc) {
334 if (0 != lc) {
335 back = dk4mkdir_hierarchy_c8_one(fn, 0, erp);
336 } else {
337 back = 1;
338 }
339 }
340 }
341 } else { /* no leading char */
342 pc = dk4str8_chr(fn, '\\');
343 if (NULL == pc) {
344 if (0 != lc) {
345 back = dk4mkdir_hierarchy_c8_one(fn, 0, erp);
346 } else {
347 back = 1;
348 }
349 }
350 }
351 }
352
353 finished:
354 if (NULL != bptr) { *bptr = back; }
355 return pc;
356 }
357
358
359
360 /* --- Windows */
361 #else
362 /* +++ non-Windows */
363
364
365
366 int
dk4mkdir_hierarchy_c8_one(const char * fn,int ro,dk4_er_t * erp)367 dk4mkdir_hierarchy_c8_one(const char *fn, int ro, dk4_er_t *erp)
368 {
369 dk4_stat_t stb;
370 int back = 0;
371
372 #if DK4_USE_ASSERT
373 assert(NULL != fn);
374 #endif
375 if (NULL == fn) {
376 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
377 goto finished;
378 }
379 #if 1
380 if (0 != dk4stat_c8(&stb, fn, NULL)) {
381 back = dk4stat_is_directory(&stb, erp);
382 if (0 == back) {
383 dk4error_set_simple_error_code(erp, DK4_E_NON_DIR);
384 }
385 } else {
386 if (0 != ro) {
387 dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
388 } else {
389 errno = 0;
390 if (0 == mkdir(fn, 0700)) {
391 back = 1;
392 } else {
393 dk4error_set_idetails(erp, DK4_E_MKDIR_FAILED, errno);
394 }
395 }
396 }
397 #else
398 back = 1;
399 #endif
400
401 finished:
402 return back;
403 }
404
405
406
407 char *
dk4mkdir_hierarchy_c8_first_sep(char * fn,int * bptr,int lc,dk4_er_t * erp)408 dk4mkdir_hierarchy_c8_first_sep(char *fn, int *bptr, int lc, dk4_er_t *erp)
409 {
410 char *pc = NULL;
411 int back = 0;
412
413 #if DK4_USE_ASSERT
414 assert(NULL != fn);
415 #endif
416 if (NULL == fn) {
417 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
418 goto finished;
419 }
420
421 if ('/' == *fn) {
422 pc = dk4str8_chr(&(fn[1]), '/');
423 } else {
424 pc = dk4str8_chr(fn, '/');
425 }
426 if (NULL == pc) {
427 if (0 != lc) {
428 back = dk4mkdir_hierarchy_c8_one(fn, 0, erp);
429 } else {
430 back = 1;
431 }
432 }
433
434 finished:
435 if (NULL != bptr) { *bptr = back; }
436 return pc;
437 }
438
439
440
441 /* --- non-Windows */
442 #endif
443
444
445
446 /** Create directory structure using an editable copy of the path.
447 @param fn File name.
448 @param lc Flag: Last component in fn is directory too.
449 @param erp Error report, may be NULL.
450 @return 1 on success, 0 on error.
451
452 Error codes:
453 - DK4_E_INVALID_ARGUMENTS<br>
454 if fn is NULL,
455 - DK4_E_BUFFER_TOO_SMALL<br>
456 if fn is too long,
457 - DK4_E_MATH_OVERFLOW<br>
458 if a mathematical overflow occured in size allocation,
459 - DK4_E_NOT_FOUND<br>
460 if a server/share combination is not present on Windows,
461 - DK4_E_NON_DIR<br>
462 if one of the components in fn is not a directory,
463 - DK4_E_MKDIR_FAILED<br>
464 with errno in idetails if the function fails to create the directory
465 or a parent directory,
466 - DK4_E_CREATE_DIR_FAILED<br>
467 with GetLastError() result in lDetails1 if the CreateDirectory()
468 function failed on a Windows system.
469 */
470 static
471 int
dk4mkdir_hierarchy_c8_on_copy(char * fn,int lc,dk4_er_t * erp)472 dk4mkdir_hierarchy_c8_on_copy(char *fn, int lc, dk4_er_t *erp)
473 {
474 char *pc;
475 int back = 0;
476
477
478 #if DK4_USE_ASSERT
479 assert(NULL != fn);
480 #endif
481
482 /* Correct file name */
483 dk4path8_correct_sep(fn);
484
485 /* Find first real separator */
486 pc = dk4mkdir_hierarchy_c8_first_sep(fn, &back, lc, erp);
487
488 /* Process directories */
489 if (NULL != pc) {
490 back = 1;
491 while (NULL != pc) {
492 *pc = '\0';
493 if (0 < dk4str8_len(fn)) {
494 if (0 == dk4mkdir_hierarchy_c8_one(fn, 0, erp)) {
495 back = 0;
496 }
497 }
498 #if DK4_HAVE_BACKSLASH_AS_SEP
499 *pc = '\\';
500 pc = dk4str8_chr(&(pc[1]), '\\');
501 #else
502 *pc = '/';
503 pc = dk4str8_chr(&(pc[1]), '/');
504 #endif
505 }
506 if (0 != lc) {
507 if (0 == dk4mkdir_hierarchy_c8_one(fn, 0, erp)) {
508 back = 0;
509 }
510 }
511 }
512
513 return back;
514 }
515
516
517
518 /** Create directory structure using a local copy of the path.
519 @param fn File name.
520 @param lc Flag: Last component in fn is directory too.
521 @param erp Error report, may be NULL.
522 @return 1 on success, 0 on error.
523
524 Error codes:
525 - DK4_E_INVALID_ARGUMENTS<br>
526 if fn is NULL,
527 - DK4_E_BUFFER_TOO_SMALL<br>
528 if fn is too long,
529 - DK4_E_MATH_OVERFLOW<br>
530 if a mathematical overflow occured in size allocation,
531 - DK4_E_NOT_FOUND<br>
532 if a server/share combination is not present on Windows,
533 - DK4_E_NON_DIR<br>
534 if one of the components in fn is not a directory,
535 - DK4_E_MKDIR_FAILED<br>
536 with errno in idetails if the function fails to create the directory
537 or a parent directory,
538 - DK4_E_CREATE_DIR_FAILED<br>
539 with GetLastError() result in lDetails1 if the CreateDirectory()
540 function failed on a Windows system.
541 */
542 static
543 int
dk4mkdir_hierarchy_c8_local(const char * fn,int lc,dk4_er_t * erp)544 dk4mkdir_hierarchy_c8_local(const char *fn, int lc, dk4_er_t *erp)
545 {
546 char mycp[DK4_MAX_PATH];
547 int back = 0;
548
549 #if DK4_USE_ASSERT
550 assert(NULL != fn);
551 #endif
552 if (0 != dk4str8_cpy_s(mycp, sizeof(mycp), fn, erp)) {
553 back = dk4mkdir_hierarchy_c8_on_copy(mycp, lc, erp);
554 }
555 return back;
556 }
557
558
559
560 int
dk4mkdir_hierarchy_c8(const char * fn,int lc,dk4_er_t * erp)561 dk4mkdir_hierarchy_c8(const char *fn, int lc, dk4_er_t *erp)
562 {
563 char *mycp;
564 size_t sz;
565 int back = 0;
566
567 #if DK4_USE_ASSERT
568 assert(NULL != fn);
569 #endif
570 if (NULL != fn) {
571 sz = dk4str8_len(fn);
572 if (DK4_MAX_PATH > sz) {
573 back = dk4mkdir_hierarchy_c8_local(fn, lc, erp);
574 } else {
575 mycp = dk4str8_dup(fn, erp);
576 if (NULL != mycp) {
577 back = dk4mkdir_hierarchy_c8_on_copy(mycp, lc, erp);
578 dk4mem_free(mycp);
579 }
580 }
581 } else {
582 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
583 }
584 return back;
585 }
586
587
588
589 #if DK4_HAVE_UID_T && DK4_HAVE_GID_T && DK4_HAVE_MODE_T && (!DK4_ON_WINDOWS)
590
591
592
593 /** Check whether directory exists or attempt to create directory.
594 @param fn File name.
595 @param ro Flag: Read only (test directory presence),
596 do not attempt to create the directory.
597 @param uid User ID for new directories.
598 @param gid Group ID for new directories.
599 @param mode Mode for new directories.
600 @param erp Error report, may be NULL.
601 @return 1 if directory is available now, 0 otherwise.
602
603 Error codes:
604 - DK4_E_INVALID_ARGUMENTS<br>
605 if fn is NULL,
606 - DK4_E_NOT_FOUND<br>
607 if a server/share combination is not present on Windows,
608 - DK4_E_NON_DIR<br>
609 if any component in the path is not a directory,
610 - DK4_E_MKDIR_FAILED<br>
611 with errno value in iDetails1 if the mkdir() function failed on a
612 non-Windows system,
613 - DK4_E_CHOWN_FAILED<br>
614 with errno value in iDetails1 if the chown() function failed on a
615 non-Windows system,
616 - DK4_E_CHMOD_FAILED<br>
617 with errno value in iDetails1 if the chmod() function failed on a
618 non-Windows system,
619 - DK4_E_CREATE_DIR_FAILED<br>
620 with GetLastError() result in lDetails1 if the CreateDirectory()
621 function failed on a Windows system.
622 */
623 static
624 int
dk4mkdir_hierarchy_ugm_c8_one(const char * fn,int ro,uid_t uid,gid_t gid,mode_t mode,dk4_er_t * erp)625 dk4mkdir_hierarchy_ugm_c8_one(
626 const char *fn,
627 int ro,
628 uid_t uid,
629 gid_t gid,
630 mode_t mode,
631 dk4_er_t *erp
632 )
633 {
634 dk4_stat_t stb;
635 int back = 0;
636
637 #if DK4_USE_ASSERT
638 assert(NULL != fn);
639 #endif
640 if (NULL == fn) {
641 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
642 goto finished;
643 }
644 #if 1
645 if (0 != dk4stat_c8(&stb, fn, NULL)) {
646 back = dk4stat_is_directory(&stb, erp);
647 if (0 == back) {
648 dk4error_set_simple_error_code(erp, DK4_E_NON_DIR);
649 }
650 } else {
651 if (0 != ro) {
652 dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
653 } else {
654 errno = 0;
655 if (0 == mkdir(fn, mode)) {
656 errno = 0;
657 if (0 == chown(fn, uid, gid)) {
658 errno = 0;
659 if (0 == chmod(fn, mode)) {
660 back = 1;
661 } else {
662 dk4error_set_idetails(erp, DK4_E_CHMOD_FAILED, errno);
663 }
664 } else {
665 dk4error_set_idetails(erp, DK4_E_CHOWN_FAILED, errno);
666 }
667 } else {
668 dk4error_set_idetails(erp, DK4_E_MKDIR_FAILED, errno);
669 }
670 }
671 }
672 #else
673 back = 1;
674 #endif
675
676 finished:
677 return back;
678 }
679
680
681
682 /** Create directory structure using an editable copy of the path.
683 @param fn File name.
684 @param lc Flag: Last component in fn is directory too.
685 @param uid User ID for new directories.
686 @param gid Group ID for new directories.
687 @param mode Mode for new directories.
688 @param erp Error report, may be NULL.
689 @return 1 on success, 0 on error.
690
691 Error codes:
692 - DK4_E_INVALID_ARGUMENTS<br>
693 if fn is NULL,
694 - DK4_E_BUFFER_TOO_SMALL<br>
695 if fn is too long,
696 - DK4_E_MATH_OVERFLOW<br>
697 if a mathematical overflow occured in size allocation,
698 - DK4_E_NOT_FOUND<br>
699 if a server/share combination is not present on Windows,
700 - DK4_E_NON_DIR<br>
701 if one of the components in fn is not a directory,
702 - DK4_E_MKDIR_FAILED<br>
703 with errno in idetails if the function fails to create the directory
704 or a parent directory,
705 - DK4_E_CHOWN_FAILED<br>
706 with errno value in iDetails1 if the chown() function failed on a
707 non-Windows system,
708 - DK4_E_CHMOD_FAILED<br>
709 with errno value in iDetails1 if the chmod() function failed on a
710 non-Windows system,
711 - DK4_E_CREATE_DIR_FAILED<br>
712 with GetLastError() result in lDetails1 if the CreateDirectory()
713 function failed on a Windows system.
714 */
715 static
716 int
dk4mkdir_hierarchy_ugm_c8_on_copy(char * fn,int lc,uid_t uid,gid_t gid,mode_t mode,dk4_er_t * erp)717 dk4mkdir_hierarchy_ugm_c8_on_copy(
718 char *fn,
719 int lc,
720 uid_t uid,
721 gid_t gid,
722 mode_t mode,
723 dk4_er_t *erp
724 )
725 {
726 char *pc;
727 int back = 0;
728
729
730
731 #if DK4_USE_ASSERT
732 assert(NULL != fn);
733 #endif
734
735 /* Correct file name */
736 dk4path8_correct_sep(fn);
737
738 /* Find first real separator */
739 pc = dk4mkdir_hierarchy_c8_first_sep(fn, &back, lc, erp);
740
741 /* Process directories */
742 if (NULL != pc) {
743 back = 1;
744 while (NULL != pc) {
745 *pc = '\0';
746 if (0 < dk4str8_len(fn)) {
747 if (0 == dk4mkdir_hierarchy_ugm_c8_one(fn, 0, uid, gid, mode, erp)) {
748 back = 0;
749 }
750 }
751 #if DK4_HAVE_BACKSLASH_AS_SEP
752 *pc = '\\';
753 pc = dk4str8_chr(&(pc[1]), '\\');
754 #else
755 *pc = '/';
756 pc = dk4str8_chr(&(pc[1]), '/');
757 #endif
758 }
759 if (0 != lc) {
760 if (0 == dk4mkdir_hierarchy_ugm_c8_one(fn, 0, uid, gid, mode, erp)) {
761 back = 0;
762 }
763 }
764 }
765
766 return back;
767 }
768
769
770
771 /** Create directory structure using a local copy of the path.
772 @param fn File name.
773 @param lc Flag: Last component in fn is directory too.
774 @param uid User ID for new directories.
775 @param gid Group ID for new directories.
776 @param mode Mode for new directories.
777 @param erp Error report, may be NULL.
778 @return 1 on success, 0 on error.
779
780 Error codes:
781 - DK4_E_INVALID_ARGUMENTS<br>
782 if fn is NULL,
783 - DK4_E_BUFFER_TOO_SMALL<br>
784 if fn is too long,
785 - DK4_E_MATH_OVERFLOW<br>
786 if a mathematical overflow occured in size allocation,
787 - DK4_E_NOT_FOUND<br>
788 if a server/share combination is not present on Windows,
789 - DK4_E_NON_DIR<br>
790 if one of the components in fn is not a directory,
791 - DK4_E_MKDIR_FAILED<br>
792 with errno in idetails if the function fails to create the directory
793 or a parent directory,
794 - DK4_E_CHOWN_FAILED<br>
795 with errno value in iDetails1 if the chown() function failed on a
796 non-Windows system,
797 - DK4_E_CHMOD_FAILED<br>
798 with errno value in iDetails1 if the chmod() function failed on a
799 non-Windows system,
800 - DK4_E_CREATE_DIR_FAILED<br>
801 with GetLastError() result in lDetails1 if the CreateDirectory()
802 function failed on a Windows system.
803 */
804 static
805 int
dk4mkdir_hierarchy_ugm_c8_local(const char * fn,int lc,uid_t uid,gid_t gid,mode_t mode,dk4_er_t * erp)806 dk4mkdir_hierarchy_ugm_c8_local(
807 const char *fn,
808 int lc,
809 uid_t uid,
810 gid_t gid,
811 mode_t mode,
812 dk4_er_t *erp
813 )
814 {
815 char mycp[DK4_MAX_PATH];
816 int back = 0;
817
818 #if DK4_USE_ASSERT
819 assert(NULL != fn);
820 #endif
821 if (0 != dk4str8_cpy_s(mycp, sizeof(mycp), fn, erp)) {
822 back = dk4mkdir_hierarchy_ugm_c8_on_copy(mycp, lc, uid, gid, mode, erp);
823 }
824 return back;
825 }
826
827
828
829 int
dk4mkdir_hierarchy_ugm_c8(const char * fn,int lc,uid_t uid,gid_t gid,mode_t mode,dk4_er_t * erp)830 dk4mkdir_hierarchy_ugm_c8(
831 const char *fn,
832 int lc,
833 uid_t uid,
834 gid_t gid,
835 mode_t mode,
836 dk4_er_t *erp
837 )
838 {
839 char *mycp;
840 size_t sz;
841 int back = 0;
842
843 #if DK4_USE_ASSERT
844 assert(NULL != fn);
845 #endif
846 if (NULL != fn) {
847 sz = dk4str8_len(fn);
848 if (DK4_MAX_PATH > sz) {
849 back = dk4mkdir_hierarchy_ugm_c8_local(fn, lc, uid, gid, mode, erp);
850 } else {
851 mycp = dk4str8_dup(fn, erp);
852 if (NULL != mycp) {
853 back = dk4mkdir_hierarchy_ugm_c8_on_copy(mycp, lc, uid, gid, mode, erp);
854 dk4mem_free(mycp);
855 }
856 }
857 } else {
858 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
859 }
860 return back;
861 }
862
863
864
865 #endif
866