- Start rosapps rearrange and cleanup process.
[reactos.git] / rosapps / applications / net / ncftp / libncftp / util.c
1 /* util.c
2 *
3 * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
4 * All rights reserved.
5 *
6 */
7
8 #include "syshdrs.h"
9
10 #if defined(WIN32) || defined(_WINDOWS)
11 #include <conio.h>
12 extern void GetSpecialDir(char *dst, size_t size, int whichDir);
13 #endif
14
15
16 static void *
17 Realloc(void *ptr, size_t siz)
18 {
19 if (ptr == NULL)
20 return (void *) malloc(siz);
21 return ((void *) realloc(ptr, siz));
22 } /* Realloc */
23
24
25 /* Use getcwd/getwd to get the full path of the current local
26 * working directory.
27 */
28 char *
29 FTPGetLocalCWD(char *buf, size_t size)
30 {
31 #ifdef HAVE_GETCWD
32 static char *cwdBuf = NULL;
33 static size_t cwdBufSize = 0;
34
35 if (cwdBufSize == 0) {
36 cwdBufSize = (size_t) 128;
37 cwdBuf = (char *) malloc(cwdBufSize);
38 }
39
40 for (errno = 0; ; ) {
41 if (cwdBuf == NULL) {
42 return NULL;
43 }
44
45 if (getcwd(cwdBuf, cwdBufSize) != NULL)
46 break;
47 if (errno != ERANGE) {
48 (void) Strncpy(buf, ".", size);
49 return NULL;
50 }
51 cwdBufSize *= 2;
52 cwdBuf = (char *) Realloc(cwdBuf, cwdBufSize);
53 }
54
55 return (Strncpy(buf, cwdBuf, size));
56 #else
57 #ifdef HAVE_GETWD
58 static char *cwdBuf = NULL;
59 char *dp;
60
61 /* Due to the way getwd is usually implemented, it's
62 * important to have a buffer large enough to hold the
63 * whole thing. getwd usually starts at the end of the
64 * buffer, and works backwards, returning you a pointer
65 * to the beginning of it when it finishes.
66 */
67 if (size < MAXPATHLEN) {
68 /* Buffer not big enough, so use a temporary one,
69 * and then copy the first 'size' bytes of the
70 * temporary buffer to your 'buf.'
71 */
72 if (cwdBuf == NULL) {
73 cwdBuf = (char *) malloc((size_t) MAXPATHLEN);
74 if (cwdBuf == NULL) {
75 return NULL;
76 }
77 }
78 dp = cwdBuf;
79 } else {
80 /* Buffer is big enough already. */
81 dp = buf;
82 }
83 *dp = '\0';
84 if (getwd(dp) == NULL) {
85 /* getwd() should write the reason why in the buffer then,
86 * according to the man pages.
87 */
88 (void) Strncpy(buf, ".", size);
89 return (NULL);
90 }
91 return (Strncpy(buf, dp, size));
92
93 #elif defined(WIN32) || defined(_WINDOWS)
94 if (GetCurrentDirectory((DWORD) size - 1, buf) < 1)
95 return NULL;
96 buf[size - 1] = '\0';
97 return buf;
98 #else
99 /* Not a solution, but does anybody not have either of
100 * getcwd or getwd?
101 */
102 --Error--;
103 #endif
104 #endif
105 } /* GetCWD */
106
107
108
109 /* Read a line, and axe the end-of-line. */
110 char *
111 FGets(char *str, size_t size, FILE *fp)
112 {
113 char *cp, *nlptr;
114
115 cp = fgets(str, ((int) size) - 1, fp);
116 if (cp != NULL) {
117 cp[((int) size) - 1] = '\0'; /* ensure terminator */
118 nlptr = cp + strlen(cp) - 1;
119 if (*nlptr == '\n')
120 *nlptr = '\0';
121 } else {
122 memset(str, 0, size);
123 }
124 return cp;
125 } /* FGets */
126
127
128
129
130 #if defined(WIN32) || defined(_WINDOWS)
131
132 int gettimeofday(struct timeval *const tp, void *junk)
133 {
134 SYSTEMTIME systemTime;
135
136 GetSystemTime(&systemTime);
137
138 /* Create an arbitrary second counter;
139 * Note that this particular one creates
140 * a problem at the end of the month.
141 */
142 tp->tv_sec =
143 systemTime.wSecond +
144 systemTime.wMinute * 60 +
145 systemTime.wHour * 3600 +
146 systemTime.wDay * 86400;
147
148 tp->tv_usec = systemTime.wMilliseconds * 1000;
149
150 return 0;
151 } /* gettimeofday */
152
153 #endif
154
155
156
157
158 #if defined(WIN32) || defined(_WINDOWS)
159 #else
160 /* This looks up the user's password entry, trying to look by the username.
161 * We have a couple of extra hacks in place to increase the probability
162 * that we can get the username.
163 */
164 struct passwd *
165 GetPwByName(void)
166 {
167 char *cp;
168 struct passwd *pw;
169
170 cp = getlogin();
171 if (cp == NULL) {
172 cp = (char *) getenv("LOGNAME");
173 if (cp == NULL)
174 cp = (char *) getenv("USER");
175 }
176 pw = NULL;
177 if (cp != NULL)
178 pw = getpwnam(cp);
179 return (pw);
180 } /* GetPwByName */
181 #endif
182
183
184
185 char *
186 GetPass(const char *const prompt)
187 {
188 #ifdef HAVE_GETPASS
189 return getpass(prompt);
190 #elif defined(_CONSOLE) && (defined(WIN32) || defined(_WINDOWS))
191 static char pwbuf[128];
192 char *dst, *dlim;
193 int c;
194
195 (void) memset(pwbuf, 0, sizeof(pwbuf));
196 if (! _isatty(_fileno(stdout)))
197 return (pwbuf);
198 (void) fputs(prompt, stdout);
199 (void) fflush(stdout);
200
201 for (dst = pwbuf, dlim = dst + sizeof(pwbuf) - 1;;) {
202 c = _getch();
203 if ((c == 0) || (c == 0xe0)) {
204 /* The key is a function or arrow key; read and discard. */
205 (void) _getch();
206 }
207 if ((c == '\r') || (c == '\n'))
208 break;
209 if (dst < dlim)
210 *dst++ = c;
211 }
212 *dst = '\0';
213
214 (void) fflush(stdout);
215 (void) fflush(stdin);
216 return (pwbuf);
217 #else
218 static char pwbuf[128];
219
220 (void) memset(pwbuf, 0, sizeof(pwbuf));
221 #if defined(WIN32) || defined(_WINDOWS)
222 if (! _isatty(_fileno(stdout)))
223 #else
224 if (! isatty(1))
225 #endif
226 return (pwbuf);
227 (void) fputs(prompt, stdout);
228 (void) fflush(stdout);
229 (void) FGets(pwbuf, sizeof(pwbuf), stdin);
230 (void) fflush(stdout);
231 (void) fflush(stdin);
232 return (pwbuf);
233 #endif
234 } /* GetPass */
235
236
237
238
239 void
240 GetHomeDir(char *dst, size_t size)
241 {
242 #if defined(WIN32) || defined(_WINDOWS)
243 const char *homedrive, *homepath;
244
245 homedrive = getenv("HOMEDRIVE");
246 homepath = getenv("HOMEPATH");
247 if ((homedrive != NULL) && (homepath != NULL)) {
248 (void) Strncpy(dst, homedrive, size);
249 (void) Strncat(dst, homepath, size);
250 return;
251 }
252
253 // GetSpecialDir(dst, size, CSIDL_PERSONAL /* "My Documents" */);
254 // if (dst[0] != '\0')
255 // return;
256 //
257 // dst[0] = '\0';
258 // if (GetWindowsDirectory(dst, size - 1) < 1)
259 // (void) Strncpy(dst, ".", size);
260 // else if (dst[1] == ':') {
261 // dst[2] = '\\';
262 // dst[3] = '\0';
263 // }
264 #else
265 const char *cp;
266 struct passwd *pw;
267
268 pw = NULL;
269 #if defined(USE_GETPWUID)
270 /* Try to use getpwuid(), but if we have to, fall back to getpwnam(). */
271 if ((pw = getpwuid(getuid())) == NULL)
272 pw = GetPwByName(); /* Oh well, try getpwnam() then. */
273 #else
274 /* Try to use getpwnam(), but if we have to, fall back to getpwuid(). */
275 if ((pw = GetPwByName()) == NULL)
276 pw = getpwuid(getuid()); /* Try getpwnam() then. */
277 #endif
278 if (pw != NULL)
279 cp = pw->pw_dir;
280 else if ((cp = (const char *) getenv("LOGNAME")) == NULL)
281 cp = ".";
282 (void) Strncpy(dst, cp, size);
283 #endif
284 } /* GetHomeDir */
285
286
287
288
289 void
290 GetUsrName(char *dst, size_t size)
291 {
292 #if defined(WIN32) || defined(_WINDOWS)
293 DWORD size1;
294
295 size1 = size - 1;
296 if (! GetUserName(dst, &size1))
297 (void) strncpy(dst, "unknown", size);
298 dst[size - 1] = '\0';
299 #else
300 const char *cp;
301 struct passwd *pw;
302
303 pw = NULL;
304 #ifdef USE_GETPWUID
305 /* Try to use getpwuid(), but if we have to, fall back to getpwnam(). */
306 if ((pw = getpwuid(getuid())) == NULL)
307 pw = GetPwByName(); /* Oh well, try getpwnam() then. */
308 #else
309 /* Try to use getpwnam(), but if we have to, fall back to getpwuid(). */
310 if ((pw = GetPwByName()) == NULL)
311 pw = getpwuid(getuid()); /* Try getpwnam() then. */
312 #endif
313 if (pw != NULL)
314 cp = pw->pw_name;
315 else if ((cp = (const char *) getenv("LOGNAME")) == NULL)
316 cp = "UNKNOWN";
317 (void) Strncpy(dst, cp, size);
318 #endif
319 } /* GetUserName */
320
321
322
323
324
325 /* Closes the file supplied, if it isn't a std stream. */
326 void
327 CloseFile(FILE **f)
328 {
329 if (*f != NULL) {
330 if ((*f != stdout) && (*f != stdin) && (*f != stderr))
331 (void) fclose(*f);
332 *f = NULL;
333 }
334 } /* CloseFile */
335
336
337
338 /*VARARGS*/
339 void
340 PrintF(const FTPCIPtr cip, const char *const fmt, ...)
341 {
342 va_list ap;
343 char buf[256];
344
345 va_start(ap, fmt);
346 if (cip->debugLog != NULL) {
347 (void) vfprintf(cip->debugLog, fmt, ap);
348 (void) fflush(cip->debugLog);
349 }
350 if (cip->debugLogProc != NULL) {
351 #ifdef HAVE_VSNPRINTF
352 (void) vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
353 buf[sizeof(buf) - 1] = '\0';
354 #else
355 (void) vsprintf(buf, fmt, ap);
356 #endif
357 (*cip->debugLogProc)(cip, buf);
358 }
359 va_end(ap);
360 } /* PrintF */
361
362
363
364
365
366 /*VARARGS*/
367 void
368 Error(const FTPCIPtr cip, const int pError, const char *const fmt, ...)
369 {
370 va_list ap;
371 int errnum;
372 size_t len;
373 char buf[256];
374 int endsinperiod;
375 int endsinnewline;
376 #ifndef HAVE_STRERROR
377 char errnostr[16];
378 #endif
379
380 errnum = errno;
381 va_start(ap, fmt);
382 #ifdef HAVE_VSNPRINTF
383 vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
384 buf[sizeof(buf) - 1] = '\0';
385 #else
386 (void) vsprintf(buf, fmt, ap);
387 #endif
388 va_end(ap);
389
390 if (pError != 0) {
391 len = strlen(buf);
392 endsinperiod = 0;
393 endsinnewline = 0;
394 if (len > 2) {
395 if (buf[len - 1] == '\n') {
396 endsinnewline = 1;
397 buf[len - 1] = '\0';
398 if (buf[len - 2] == '.') {
399 endsinperiod = 1;
400 buf[len - 2] = '\0';
401 }
402 } else if (buf[len - 1] == '.') {
403 endsinperiod = 1;
404 buf[len - 1] = '\0';
405 }
406 }
407 #ifdef HAVE_STRERROR
408 (void) STRNCAT(buf, ": ");
409 (void) STRNCAT(buf, strerror(errnum));
410 #else
411 # ifdef HAVE_SNPRINTF
412 sprintf(errnostr, sizeof(errnostr) - 1, " (errno = %d)", errnum);
413 errnostr[sizeof(errnostr) - 1] = '\0';
414 # else
415 sprintf(errnostr, " (errno = %d)", errnum);
416 # endif
417 STRNCAT(buf, errnostr);
418 #endif
419 if (endsinperiod != 0)
420 (void) STRNCAT(buf, ".");
421 if (endsinnewline != 0)
422 (void) STRNCAT(buf, "\n");
423 }
424
425 if (cip->errLog != NULL) {
426 (void) fprintf(cip->errLog, "%s", buf);
427 (void) fflush(cip->errLog);
428 }
429 if ((cip->debugLog != NULL) && (cip->debugLog != cip->errLog)) {
430 if ((cip->errLog != stderr) || (cip->debugLog != stdout)) {
431 (void) fprintf(cip->debugLog, "%s", buf);
432 (void) fflush(cip->debugLog);
433 }
434 }
435 if (cip->errLogProc != NULL) {
436 (*cip->errLogProc)(cip, buf);
437 }
438 if ((cip->debugLogProc != NULL) && (cip->debugLogProc != cip->errLogProc)) {
439 (*cip->debugLogProc)(cip, buf);
440 }
441 } /* Error */
442
443
444
445
446 /* Cheezy, but somewhat portable way to get GMT offset. */
447 #ifdef HAVE_MKTIME
448 static
449 time_t GetUTCOffset(int mon, int mday)
450 {
451 struct tm local_tm, utc_tm, *utc_tmptr;
452 time_t local_t, utc_t, utcOffset;
453
454 ZERO(local_tm);
455 ZERO(utc_tm);
456 utcOffset = 0;
457
458 local_tm.tm_year = 94; /* Doesn't really matter. */
459 local_tm.tm_mon = mon;
460 local_tm.tm_mday = mday;
461 local_tm.tm_hour = 12;
462 local_tm.tm_isdst = -1;
463 local_t = mktime(&local_tm);
464
465 if (local_t != (time_t) -1) {
466 utc_tmptr = gmtime(&local_t);
467 utc_tm.tm_year = utc_tmptr->tm_year;
468 utc_tm.tm_mon = utc_tmptr->tm_mon;
469 utc_tm.tm_mday = utc_tmptr->tm_mday;
470 utc_tm.tm_hour = utc_tmptr->tm_hour;
471 utc_tm.tm_isdst = -1;
472 utc_t = mktime(&utc_tm);
473
474 if (utc_t != (time_t) -1)
475 utcOffset = (local_t - utc_t);
476 }
477 return (utcOffset);
478 } /* GetUTCOffset */
479 #endif /* HAVE_MKTIME */
480
481
482
483 /* Converts a MDTM date, like "19930602204445"
484 * format to a time_t.
485 */
486 time_t UnMDTMDate(char *dstr)
487 {
488 #ifndef HAVE_MKTIME
489 return (kModTimeUnknown);
490 #else
491 struct tm ut, *t;
492 time_t mt, now;
493 time_t result = kModTimeUnknown;
494
495 if (strncmp(dstr, "19100", 5) == 0) {
496 /* Server Y2K bug! */
497 return (result);
498 }
499
500 (void) time(&now);
501 t = localtime(&now);
502
503 /* Copy the whole structure of the 'tm' pointed to by t, so it will
504 * also set all fields we don't specify explicitly to be the same as
505 * they were in t. That way we copy non-standard fields such as
506 * tm_gmtoff, if it exists or not.
507 */
508 ut = *t;
509
510 /* The time we get back from the server is (should be) in UTC. */
511 if (sscanf(dstr, "%04d%02d%02d%02d%02d%02d",
512 &ut.tm_year,
513 &ut.tm_mon,
514 &ut.tm_mday,
515 &ut.tm_hour,
516 &ut.tm_min,
517 &ut.tm_sec) == 6)
518 {
519 --ut.tm_mon;
520 ut.tm_year -= 1900;
521 mt = mktime(&ut);
522 if (mt != (time_t) -1) {
523 mt += GetUTCOffset(ut.tm_mon, ut.tm_mday);
524 result = (time_t) mt;
525 }
526 }
527 return result;
528 #endif /* HAVE_MKTIME */
529 } /* UnMDTMDate */
530
531
532
533 int
534 GetSockBufSize(int sockfd, size_t *rsize, size_t *ssize)
535 {
536 #ifdef SO_SNDBUF
537 int rc = -1;
538 int opt;
539 int optsize;
540
541 if (ssize != NULL) {
542 opt = 0;
543 optsize = sizeof(opt);
544 rc = getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, &optsize);
545 if (rc == 0)
546 *ssize = (size_t) opt;
547 else
548 *ssize = 0;
549 }
550 if (rsize != NULL) {
551 opt = 0;
552 optsize = sizeof(opt);
553 rc = getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, &optsize);
554 if (rc == 0)
555 *rsize = (size_t) opt;
556 else
557 *rsize = 0;
558 }
559 return (rc);
560 #else
561 if (ssize != NULL)
562 *ssize = 0;
563 if (rsize != NULL)
564 *rsize = 0;
565 return (-1);
566 #endif
567 } /* GetSockBufSize */
568
569
570
571 int
572 SetSockBufSize(int sockfd, size_t rsize, size_t ssize)
573 {
574 #ifdef SO_SNDBUF
575 int rc = -1;
576 int opt;
577 int optsize;
578
579 #ifdef TCP_RFC1323
580 /* This is an AIX-specific socket option to do RFC1323 large windows */
581 if (ssize > 0 || rsize > 0) {
582 opt = 1;
583 optsize = sizeof(opt);
584 rc = setsockopt(sockfd, IPPROTO_TCP, TCP_RFC1323, &opt, optsize);
585 }
586 #endif
587
588 if (ssize > 0) {
589 opt = (int) ssize;
590 optsize = sizeof(opt);
591 rc = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, optsize);
592 }
593 if (rsize > 0) {
594 opt = (int) rsize;
595 optsize = sizeof(opt);
596 rc = setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, optsize);
597 }
598 return (rc);
599 #else
600 return (-1);
601 #endif
602 } /* SetSockBufSize */
603
604
605
606 void
607 Scramble(unsigned char *dst, size_t dsize, unsigned char *src, char *key)
608 {
609 int i;
610 unsigned int ch;
611 unsigned char *k2;
612 size_t keyLen;
613
614 keyLen = strlen(key);
615 k2 = (unsigned char *) key;
616 for (i=0; i < (int) dsize - 1; i++) {
617 ch = src[i];
618 if (ch == 0)
619 break;
620 dst[i] = (unsigned char) (ch ^ (int) (k2[i % (int) keyLen]));
621 }
622 dst[i] = '\0';
623 } /* Scramble */
624
625
626
627
628
629 #if defined(WIN32) || defined(_WINDOWS)
630 void WinSleep(unsigned int seconds)
631 {
632 DWORD now, deadline;
633 DWORD milliseconds = seconds * 1000;
634
635 if (milliseconds > 0) {
636 now = GetTickCount();
637 deadline = now + milliseconds;
638 if (now < deadline) {
639 /* Typical case */
640 do {
641 milliseconds = deadline - now;
642 Sleep(milliseconds);
643 now = GetTickCount();
644 } while (now < deadline);
645 } else {
646 /* Overflow case */
647 deadline = now - 1;
648 milliseconds -= (0xFFFFFFFF - now);
649 do {
650 Sleep(0xFFFFFFFF - now);
651 now = GetTickCount();
652 } while (now > deadline);
653 /* Counter has now wrapped around */
654 deadline = now + milliseconds;
655 do {
656 milliseconds = deadline - now;
657 Sleep(milliseconds);
658 now = GetTickCount();
659 } while (now < deadline);
660 }
661 }
662 } /* WinSleep */
663
664
665
666
667 char *
668 StrFindLocalPathDelim(const char *src) /* TODO: optimize */
669 {
670 const char *first;
671 int c;
672
673 first = NULL;
674 for (;;) {
675 c = *src++;
676 if (c == '\0')
677 break;
678 if (IsLocalPathDelim(c)) {
679 first = src - 1;
680 break;
681 }
682 }
683
684 return ((char *) first);
685 } /* StrFindLocalPathDelim */
686
687
688
689 char *
690 StrRFindLocalPathDelim(const char *src) /* TODO: optimize */
691 {
692 const char *last;
693 int c;
694
695 last = NULL;
696 for (;;) {
697 c = *src++;
698 if (c == '\0')
699 break;
700 if (IsLocalPathDelim(c))
701 last = src - 1;
702 }
703
704 return ((char *) last);
705 } /* StrRFindLocalPathDelim */
706
707
708
709
710 void
711 StrRemoveTrailingLocalPathDelim(char *dst)
712 {
713 char *cp;
714
715 cp = StrRFindLocalPathDelim(dst);
716 if ((cp == NULL) || (cp[1] != '\0'))
717 return;
718
719 /* Note: Do not destroy a path of "/" */
720 while ((cp > dst) && (IsLocalPathDelim(*cp)))
721 *cp-- = '\0';
722 } /* StrRemoveTrailingLocalPathDelim */
723
724
725
726 void
727 TVFSPathToLocalPath(char *dst)
728 {
729 int c;
730
731 /* Note: Technically we don't need to do this,
732 * since Win32 accepts a / as equivalent to a \
733 * in a pathname.
734 */
735 if (dst != NULL) {
736 for (;;) {
737 c = *dst++;
738 if (c == '\0')
739 break;
740 if (c == '/')
741 dst[-1] = LOCAL_PATH_DELIM;
742 }
743 }
744 } /* TVFSPathToLocalPath */
745
746
747 void
748 LocalPathToTVFSPath(char *dst)
749 {
750 int c;
751
752 if (dst != NULL) {
753 for (;;) {
754 c = *dst++;
755 if (c == '\0')
756 break;
757 if (c == LOCAL_PATH_DELIM)
758 dst[-1] = '/';
759 }
760 }
761 } /* LocalPathToTVFSPath */
762 #endif /* WINDOWS */
763
764
765
766
767 void
768 StrRemoveTrailingSlashes(char *dst)
769 {
770 char *cp;
771
772 cp = strrchr(dst, '/');
773 if ((cp == NULL) || (cp[1] != '\0'))
774 return;
775
776 /* Note: Do not destroy a path of "/" */
777 while ((cp > dst) && (*cp == '/'))
778 *cp-- = '\0';
779 } /* StrRemoveTrailingSlashes */
780
781
782
783
784 int
785 MkDirs(const char *const newdir, int mode1)
786 {
787 char s[512];
788 int rc;
789 char *cp, *sl;
790 #if defined(WIN32) || defined(_WINDOWS)
791 struct _stat st;
792 char *share;
793 #else
794 struct Stat st;
795 mode_t mode = (mode_t) mode1;
796 #endif
797
798 #if defined(WIN32) || defined(_WINDOWS)
799 if ((isalpha(newdir[0])) && (newdir[1] == ':')) {
800 if (! IsLocalPathDelim(newdir[2])) {
801 /* Special case "c:blah", and errout.
802 * "c:\blah" must be used or _access GPFs.
803 */
804 errno = EINVAL;
805 return (-1);
806 } else if (newdir[3] == '\0') {
807 /* Special case root directory, which cannot be made. */
808 return (0);
809 }
810 } else if (IsUNCPrefixed(newdir)) {
811 share = StrFindLocalPathDelim(newdir + 2);
812 if ((share == NULL) || (StrFindLocalPathDelim(share + 1) == NULL))
813 return (-1);
814 }
815
816 if (_access(newdir, 00) == 0) {
817 if (_stat(newdir, &st) < 0)
818 return (-1);
819 if (! S_ISDIR(st.st_mode)) {
820 errno = ENOTDIR;
821 return (-1);
822 }
823 return 0;
824 }
825 #else
826 if (access(newdir, F_OK) == 0) {
827 if (Stat(newdir, &st) < 0)
828 return (-1);
829 if (! S_ISDIR(st.st_mode)) {
830 errno = ENOTDIR;
831 return (-1);
832 }
833 return 0;
834 }
835 #endif
836
837 (void) strncpy(s, newdir, sizeof(s));
838 if (s[sizeof(s) - 1] != '\0') {
839 #ifdef ENAMETOOLONG
840 errno = ENAMETOOLONG;
841 #else
842 errno = EINVAL;
843 return (-1);
844 #endif
845 }
846
847 cp = StrRFindLocalPathDelim(s);
848 if (cp == NULL) {
849 #if defined(WIN32) || defined(_WINDOWS)
850 if (! CreateDirectory(newdir, (LPSECURITY_ATTRIBUTES) 0))
851 return (-1);
852 return (0);
853 #else
854 rc = mkdir(newdir, mode);
855 return (rc);
856 #endif
857 } else if (cp[1] == '\0') {
858 /* Remove trailing slashes from path. */
859 --cp;
860 while (cp > s) {
861 if (! IsLocalPathDelim(*cp))
862 break;
863 --cp;
864 }
865 cp[1] = '\0';
866 cp = StrRFindLocalPathDelim(s);
867 if (cp == NULL) {
868 #if defined(WIN32) || defined(_WINDOWS)
869 if (! CreateDirectory(s, (LPSECURITY_ATTRIBUTES) 0))
870 return (-1);
871 #else
872 rc = mkdir(s, mode);
873 return (rc);
874 #endif
875 }
876 }
877
878 /* Find the deepest directory in this
879 * path that already exists. When
880 * we do, we want to have the 's'
881 * string as it was originally, but
882 * with 'cp' pointing to the first
883 * slash in the path that starts the
884 * part that does not exist.
885 */
886 sl = NULL;
887 for (;;) {
888 *cp = '\0';
889 #if defined(WIN32) || defined(_WINDOWS)
890 rc = _access(s, 00);
891 #else
892 rc = access(s, F_OK);
893 #endif
894 if (sl != NULL)
895 *sl = LOCAL_PATH_DELIM;
896 if (rc == 0) {
897 *cp = LOCAL_PATH_DELIM;
898 break;
899 }
900 sl = cp;
901 cp = StrRFindLocalPathDelim(s);
902 if (cp == NULL) {
903 /* We do not have any more
904 * slashes, so none of the
905 * new directory's components
906 * existed before, so we will
907 * have to make everything
908 * starting at the first node.
909 */
910 if (sl != NULL)
911 *sl = LOCAL_PATH_DELIM;
912
913 /* We refer to cp + 1 below,
914 * so this is why we can
915 * set "cp" to point to the
916 * byte before the array starts.
917 */
918 cp = s - 1;
919 break;
920 }
921 }
922
923 for (;;) {
924 /* Extend the path we have to
925 * include the next component
926 * to make.
927 */
928 sl = StrFindLocalPathDelim(cp + 1);
929 if (sl == s) {
930 /* If the next slash is pointing
931 * to the start of the string, then
932 * the path is an absolute path and
933 * we don't need to make the root node,
934 * and besides the next mkdir would
935 * try an empty string.
936 */
937 ++cp;
938 sl = StrFindLocalPathDelim(cp + 1);
939 }
940 if (sl != NULL) {
941 *sl = '\0';
942 }
943 #if defined(WIN32) || defined(_WINDOWS)
944 if (! CreateDirectory(s, (LPSECURITY_ATTRIBUTES) 0))
945 return (-1);
946 #else
947 rc = mkdir(s, mode);
948 if (rc < 0)
949 return rc;
950 #endif
951 if (sl == NULL)
952 break;
953 *sl = LOCAL_PATH_DELIM;
954 cp = sl;
955 }
956 return (0);
957 } /* MkDirs */
958
959
960
961
962 int
963 FilenameExtensionIndicatesASCII(const char *const pathName, const char *const extnList)
964 {
965 const char *extn;
966 char *cp;
967 int c;
968 char extnPattern[16];
969
970 extn = pathName + strlen(pathName) - 1;
971 forever {
972 if (extn <= pathName)
973 return (0); /* End of pathname, no extension. */
974 c = (int) *--extn;
975 if (IsLocalPathDelim(c))
976 return (0); /* End of filename, no extension. */
977 if (c == '.') {
978 extn += 1;
979 break;
980 }
981 }
982 if (strlen(extn) > (sizeof(extnPattern) - 2 - 1 - 1)) {
983 return (0);
984 }
985 #ifdef HAVE_SNPRINTF
986 snprintf(extnPattern, sizeof(extnPattern),
987 #else
988 sprintf(extnPattern,
989 #endif
990 "|.%s|",
991 extn
992 );
993
994 cp = extnPattern;
995 forever {
996 c = *cp;
997 if (c == '\0')
998 break;
999 if (isupper(c)) {
1000 c = tolower(c);
1001 *cp++ = (char) c;
1002 } else {
1003 cp++;
1004 }
1005 }
1006
1007 /* Extension list is specially formatted, like this:
1008 *
1009 * |ext1|ext2|ext3|...|extN|
1010 *
1011 * I.e, each filename extension is delimited with
1012 * a pipe, and we always begin and end the string
1013 * with a pipe.
1014 */
1015 if (strstr(extnList, extnPattern) != NULL) {
1016 return (1);
1017 }
1018 return (0);
1019 } /* FilenameExtensionIndicatesASCII */
1020
1021
1022
1023
1024
1025 #ifdef HAVE_SIGACTION
1026 void (*NcSignal(int signum, void (*handler)(int)))(int)
1027 {
1028 struct sigaction sa, osa;
1029
1030 (void) sigemptyset(&sa.sa_mask);
1031 sa.sa_flags = 0;
1032 sa.sa_handler = handler;
1033 if (signum == SIGALRM) {
1034 #ifdef SA_INTERRUPT
1035 sa.sa_flags |= SA_INTERRUPT;
1036 #endif
1037 } else {
1038 #ifdef SA_RESTART
1039 sa.sa_flags |= SA_RESTART;
1040 #endif
1041 }
1042 if (sigaction(signum, &sa, &osa) < 0)
1043 return ((FTPSigProc) SIG_ERR);
1044 return (osa.sa_handler);
1045 }
1046 #endif /* HAVE_SIGACTION */
1047
1048 /* eof */