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