dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libast / common / comp / omitted.c
blob9ffc128c2efddab9922101c033f4063dba409710
1 #pragma prototyped noticed
3 /*
4 * workarounds to bring the native interface close to posix and x/open
5 */
7 #if defined(__STDPP__directive) && defined(__STDPP__hide)
8 __STDPP__directive pragma pp:hide utime utimes
9 #else
10 #define utime ______utime
11 #define utimes ______utimes
12 #endif
14 #include <ast.h>
15 #include <error.h>
16 #include <tm.h>
18 #include "FEATURE/omitted"
20 #undef OMITTED
22 #if _win32_botch
24 #define OMITTED 1
26 #include <ls.h>
27 #include <utime.h>
29 #if __CYGWIN__
30 #include <ast_windows.h>
31 #if _win32_botch_execve || _lib_spawn_mode
32 #define CONVERT 1
33 #endif
34 #endif
36 #if defined(__STDPP__directive) && defined(__STDPP__hide)
37 __STDPP__directive pragma pp:nohide utime utimes
38 #else
39 #undef utime
40 #undef utimes
41 #endif
43 #ifndef MAX_PATH
44 #define MAX_PATH PATH_MAX
45 #endif
48 * these workarounds assume each system call foo() has a _foo() entry
49 * which is true for __CYGWIN__ and __EMX__ (both gnu based)
51 * the workarounds handle:
53 * (1) .exe suffix inconsistencies
54 * (2) /bin/sh reference in execve() and spawnve()
55 * (3) bogus getpagesize() return values
56 * (4) a fork() bug that screws up shell fork()+script
58 * NOTE: Not all workarounds can be handled by unix syscall intercepts.
59 * In particular, { ksh nmake } have workarounds for case-ignorant
60 * filesystems and { libast } has workarounds for win32 locale info.
63 #undef _pathconf
64 #undef pathconf
65 #undef stat
67 extern int _access(const char*, int);
68 extern unsigned int _alarm(unsigned int);
69 extern int _chmod(const char*, mode_t);
70 extern int _close(int);
71 extern pid_t _execve(const char*, char* const*, char* const*);
72 extern int _link(const char*, const char*);
73 extern int _open(const char*, int, ...);
74 extern long _pathconf(const char*, int);
75 extern ssize_t _read(int, void*, size_t);
76 extern int _rename(const char*, const char*);
77 extern pid_t _spawnve(int, const char*, char* const*, char* const*);
78 extern int _stat(const char*, struct stat*);
79 extern int _unlink(const char*);
80 extern int _utime(const char*, const struct utimbuf*);
81 extern int _utimes(const char*, const struct timeval*);
82 extern ssize_t _write(int, const void*, size_t);
84 #if defined(__EXPORT__)
85 #define extern __EXPORT__
86 #endif
88 static char*
89 suffix(register const char* path)
91 register const char* s = path + strlen(path);
92 register int c;
94 while (s > path)
95 if ((c = *--s) == '.')
96 return (char*)s + 1;
97 else if (c == '/' || c == '\\')
98 break;
99 return 0;
102 static int
103 execrate(const char* path, char* buf, int size, int physical)
105 char* s;
106 int n;
107 int oerrno;
109 if (suffix(path))
110 return 0;
111 oerrno = errno;
112 if (physical || strlen(path) >= size || !(s = pathcanon(strcpy(buf, path), PATH_PHYSICAL|PATH_DOTDOT|PATH_EXISTS)))
113 snprintf(buf, size, "%s.exe", path);
114 else if (!suffix(buf) && ((buf + size) - s) >= 4)
115 strcpy(s, ".exe");
116 errno = oerrno;
117 return 1;
121 * return 0 if path is magic, -1 otherwise
122 * ux!=0 set to 1 if path is unix executable
123 * ux!=0 also retains errno for -1 return
126 static int
127 magic(const char* path, int* ux)
129 int fd;
130 int r;
131 int n;
132 int m;
133 int oerrno;
134 #if CONVERT
135 unsigned char buf[512];
136 #else
137 unsigned char buf[2];
138 #endif
140 oerrno = errno;
141 if ((fd = _open(path, O_RDONLY, 0)) >= 0)
143 #if CONVERT
144 if (ux)
145 n = sizeof(buf);
146 else
147 #endif
148 n = 2;
149 r = (m = _read(fd, buf, n)) >= 2 && (buf[1] == 0x5a && (buf[0] == 0x4c || buf[0] == 0x4d) || ux && buf[0] == '#' && buf[1] == '!' && (*ux = 1) && !(ux = 0)) ? 0 : -1;
150 close(fd);
151 if (ux)
153 if (r)
154 oerrno = ENOEXEC;
155 else if (m > 61 && (n = buf[60] | (buf[61]<<8) + 92) < (m - 1))
156 *ux = (buf[n] | (buf[n+1]<<8)) == 3;
157 else
158 *ux = 0;
161 else if (!ux)
162 r = -1;
163 else if (errno == ENOENT)
165 oerrno = errno;
166 r = -1;
168 else
170 r = 0;
171 *ux = 0;
173 errno = oerrno;
174 return r;
177 #if _win32_botch_access
179 extern int
180 access(const char* path, int op)
182 int r;
183 int oerrno;
184 char buf[PATH_MAX];
186 oerrno = errno;
187 if ((r = _access(path, op)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
189 errno = oerrno;
190 r = _access(buf, op);
192 return r;
195 #endif
197 #if _win32_botch_alarm
199 extern unsigned int
200 alarm(unsigned int s)
202 unsigned int n;
203 unsigned int r;
205 static unsigned int a;
207 n = (unsigned int)time(NiL);
208 if (a <= n)
209 r = 0;
210 else
211 r = a - n;
212 a = n + s - 1;
213 (void)_alarm(s);
214 return r;
217 #endif
219 #if _win32_botch_chmod
221 extern int
222 chmod(const char* path, mode_t mode)
224 int r;
225 int oerrno;
226 char buf[PATH_MAX];
228 if ((r = _chmod(path, mode)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
230 errno = oerrno;
231 return _chmod(buf, mode);
233 if (!(r = _chmod(path, mode)) &&
234 (mode & (S_IXUSR|S_IXGRP|S_IXOTH)) &&
235 !suffix(path) &&
236 (strlen(path) + 4) < sizeof(buf))
238 oerrno = errno;
239 if (!magic(path, NiL))
241 snprintf(buf, sizeof(buf), "%s.exe", path);
242 _rename(path, buf);
244 errno = oerrno;
246 return r;
249 #endif
251 #if _win32_botch_execve || _lib_spawn_mode
253 #if _lib_spawn_mode
256 * can anyone get const prototype args straight?
259 #define execve ______execve
260 #define spawnve ______spawnve
262 #include <process.h>
264 #undef execve
265 #undef spawnve
267 #endif
269 #if CONVERT
272 * this intercept converts dos env vars to unix
273 * we'd rather intercept main but can't twist cc to do it
274 * getuid() gets ksh to do the right thing and
275 * that's our main concern
277 * DOSPATHVARS='a b c' convert { a b c }
280 extern uid_t _getuid(void);
282 static int convertinit;
285 * convertvars[0] names the list of env var names
286 * convertvars[i] are not converted
289 static const char* convertvars[] = { "DOSPATHVARS", "PATH" };
291 static int
292 convert(register const char* d, const char* s)
294 register const char* t;
295 register const char* v;
296 int i;
298 for (i = 0; i < elementsof(convertvars); i++)
300 for (v = convertvars[i], t = s; *t && *t == *v; t++, v++);
301 if (*t == '=' && *v == 0)
302 return 0;
304 for (;;)
306 while (*d == ' ' || *d == '\t')
307 d++;
308 if (!*d)
309 break;
310 for (t = s; *t && *t == *d; d++, t++);
311 if (*t == '=' && (*d == ' ' || *d == '\t' || *d == 0))
312 return t - s + 1;
313 while (*d && *d != ' ' && *d != '\t')
314 d++;
316 return 0;
319 uid_t
320 getuid(void)
322 register char* d;
323 register char* s;
324 register char* t;
325 register char** e;
326 int n;
327 int m;
329 if (!convertinit++ && (d = getenv(convertvars[0])))
330 for (e = environ; s = *e; e++)
331 if ((n = convert(d, s)) && (m = cygwin_win32_to_posix_path_list_buf_size(s + n)) > 0)
333 if (!(t = malloc(n + m + 1)))
334 break;
335 *e = t;
336 memcpy(t, s, n);
337 cygwin_win32_to_posix_path_list(s + n, t + n);
339 return _getuid();
342 #endif
344 #ifndef _P_OVERLAY
345 #define _P_OVERLAY (-1)
346 #endif
348 #define DEBUG 1
350 static pid_t
351 runve(int mode, const char* path, char* const* argv, char* const* envv)
353 register char* s;
354 register char** p;
355 register char** v;
357 void* m1;
358 void* m2;
359 pid_t pid;
360 int oerrno;
361 int ux;
362 int n;
363 #if defined(_P_DETACH) && defined(_P_NOWAIT)
364 int pgrp;
365 #endif
366 #if CONVERT
367 char* d;
368 char* t;
369 int m;
370 #endif
371 struct stat st;
372 char buf[PATH_MAX];
373 char tmp[PATH_MAX];
375 #if DEBUG
376 static int trace;
377 #endif
379 #if defined(_P_DETACH) && defined(_P_NOWAIT)
380 if (mode == _P_DETACH)
383 * 2004-02-29 cygwin _P_DETACH is useless:
384 * spawn*() returns 0 instead of the spawned pid
385 * spawned { pgid sid } are the same as the parent
388 mode = _P_NOWAIT;
389 pgrp = 1;
391 else
392 pgrp = 0;
393 #endif
394 if (!envv)
395 envv = (char* const*)environ;
396 m1 = m2 = 0;
397 oerrno = errno;
398 #if DEBUG
399 if (!trace)
400 trace = (s = getenv("_AST_exec_trace")) ? *s : 'n';
401 #endif
402 if (execrate(path, buf, sizeof(buf), 0))
404 if (!_stat(buf, &st))
405 path = (const char*)buf;
406 else
407 errno = oerrno;
409 if (path != (const char*)buf && _stat(path, &st))
410 return -1;
411 if (!S_ISREG(st.st_mode) || !(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
413 errno = EACCES;
414 return -1;
416 if (magic(path, &ux))
418 #if _CYGWIN_fork_works
419 errno = ENOEXEC;
420 return -1;
421 #else
422 ux = 1;
423 p = (char**)argv;
424 while (*p++);
425 if (!(v = (char**)malloc((p - (char**)argv + 2) * sizeof(char*))))
427 errno = EAGAIN;
428 return -1;
430 m1 = v;
431 p = v;
432 *p++ = (char*)path;
433 *p++ = (char*)path;
434 path = (const char*)pathshell();
435 if (*argv)
436 argv++;
437 while (*p++ = (char*)*argv++);
438 argv = (char* const*)v;
439 #endif
443 * the win32 dll search order is
444 * (1) the directory of path
445 * (2) .
446 * (3) /c/(WINNT|WINDOWS)/system32 /c/(WINNT|WINDOWS)
447 * (4) the directories on $PATH
448 * there are no cygwin dlls in (3), so if (1) and (2) fail
449 * to produce the required dlls its up to (4)
451 * the standard allows PATH to be anything once the path
452 * to an executable is determined; this code ensures that PATH
453 * contains /bin so that at least the cygwin dll, required
454 * by all cygwin executables, will be found
457 if (p = (char**)envv)
459 n = 1;
460 while (s = *p++)
461 if (strneq(s, "PATH=", 5))
463 s += 5;
466 s = pathcat(tmp, s, ':', NiL, "");
467 if (streq(tmp, "/usr/bin/") || streq(tmp, "/bin/"))
469 n = 0;
470 break;
472 } while (s);
473 if (n)
475 n = 0;
476 snprintf(tmp, sizeof(tmp), "%s:/bin", *(p - 1));
477 *(p - 1) = tmp;
479 break;
481 if (n)
483 n = p - (char**)envv + 1;
484 p = (char**)envv;
485 if (v = (char**)malloc(n * sizeof(char*)))
487 m2 = v;
488 envv = (char* const*)v;
489 *v++ = strcpy(tmp, "PATH=/bin");
490 while (*v++ = *p++);
493 #if CONVERT
494 if (!ux && (d = getenv(convertvars[0])))
495 for (p = (char**)envv; s = *p; p++)
496 if ((n = convert(d, s)) && (m = cygwin_posix_to_win32_path_list_buf_size(s + n)) > 0)
498 if (!(t = malloc(n + m + 1)))
499 break;
500 *p = t;
501 memcpy(t, s, n);
502 cygwin_posix_to_win32_path_list(s + n, t + n);
504 #endif
507 #if DEBUG
508 if (trace == 'a' || trace == 'e')
510 sfprintf(sfstderr, "%s %s [", mode == _P_OVERLAY ? "_execve" : "_spawnve", path);
511 for (n = 0; argv[n]; n++)
512 sfprintf(sfstderr, " '%s'", argv[n]);
513 if (trace == 'e')
515 sfprintf(sfstderr, " ] [");
516 for (n = 0; envv[n]; n++)
517 sfprintf(sfstderr, " '%s'", envv[n]);
519 sfprintf(sfstderr, " ]\n");
520 sfsync(sfstderr);
522 #endif
523 #if _lib_spawn_mode
524 if (mode != _P_OVERLAY)
526 pid = _spawnve(mode, path, argv, envv);
527 #if defined(_P_DETACH) && defined(_P_NOWAIT)
528 if (pid > 0 && pgrp)
529 setpgid(pid, 0);
530 #endif
532 else
533 #endif
535 #if defined(_P_DETACH) && defined(_P_NOWAIT)
536 if (pgrp)
537 setpgid(0, 0);
538 #endif
539 pid = _execve(path, argv, envv);
541 free(m1);
542 free(m2);
543 return pid;
546 #if _win32_botch_execve
548 extern pid_t
549 execve(const char* path, char* const* argv, char* const* envv)
551 return runve(_P_OVERLAY, path, argv, envv);
554 #endif
556 #if _lib_spawn_mode
558 extern pid_t
559 spawnve(int mode, const char* path, char* const* argv, char* const* envv)
561 return runve(mode, path, argv, envv);
564 #endif
566 #endif
568 #if _win32_botch_getpagesize
570 extern size_t
571 getpagesize(void)
573 return 64 * 1024;
576 #endif
578 #if _win32_botch_link
580 extern int
581 link(const char* fp, const char* tp)
583 int r;
584 int oerrno;
585 char fb[PATH_MAX];
586 char tb[PATH_MAX];
588 oerrno = errno;
589 if ((r = _link(fp, tp)) && errno == ENOENT && execrate(fp, fb, sizeof(fb), 1))
591 if (execrate(tp, tb, sizeof(tb), 1))
592 tp = tb;
593 errno = oerrno;
594 r = _link(fb, tp);
596 return r;
599 #endif
601 #if _win32_botch_open || _win32_botch_copy
603 #if _win32_botch_copy
606 * this should intercept the important cases
607 * dup*() and exec*() fd's will not be intercepted
610 typedef struct Exe_test_s
612 int test;
613 ino_t ino;
614 char path[PATH_MAX];
615 } Exe_test_t;
617 static Exe_test_t* exe[16];
619 extern int
620 close(int fd)
622 int r;
623 int oerrno;
624 struct stat st;
625 char buf[PATH_MAX];
627 if (fd >= 0 && fd < elementsof(exe) && exe[fd])
629 r = exe[fd]->test;
630 exe[fd]->test = 0;
631 if (r > 0 && !fstat(fd, &st) && st.st_ino == exe[fd]->ino)
633 if (r = _close(fd))
634 return r;
635 oerrno = errno;
636 if (!stat(exe[fd]->path, &st) && st.st_ino == exe[fd]->ino)
638 snprintf(buf, sizeof(buf), "%s.exe", exe[fd]->path);
639 _rename(exe[fd]->path, buf);
641 errno = oerrno;
642 return 0;
645 return _close(fd);
648 extern ssize_t
649 write(int fd, const void* buf, size_t n)
651 if (fd >= 0 && fd < elementsof(exe) && exe[fd] && exe[fd]->test < 0)
652 exe[fd]->test = n >= 2 && ((unsigned char*)buf)[1] == 0x5a && (((unsigned char*)buf)[0] == 0x4c || ((unsigned char*)buf)[0] == 0x4d) && !lseek(fd, (off_t)0, SEEK_CUR);
653 return _write(fd, buf, n);
656 #endif
658 extern int
659 open(const char* path, int flags, ...)
661 int fd;
662 int mode;
663 int oerrno;
664 char buf[PATH_MAX];
665 #if _win32_botch_copy
666 struct stat st;
667 #endif
668 va_list ap;
670 va_start(ap, flags);
671 mode = (flags & O_CREAT) ? va_arg(ap, int) : 0;
672 oerrno = errno;
673 fd = _open(path, flags, mode);
674 #if _win32_botch_open
675 if (fd < 0 && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
677 errno = oerrno;
678 fd = _open(buf, flags, mode);
680 #endif
681 #if _win32_botch_copy
682 if (fd >= 0 && fd < elementsof(exe) && strlen(path) < PATH_MAX &&
683 (flags & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC) && (mode & 0111))
685 if (!suffix(path) && !fstat(fd, &st) && (exe[fd] || (exe[fd] = (Exe_test_t*)malloc(sizeof(Exe_test_t)))))
687 exe[fd]->test = -1;
688 exe[fd]->ino = st.st_ino;
689 strcpy(exe[fd]->path, path);
691 errno = oerrno;
693 #endif
694 va_end(ap);
695 return fd;
698 #endif
700 #if _win32_botch_pathconf
702 extern long
703 pathconf(const char* path, int op)
705 if (_access(path, F_OK))
706 return -1;
707 return _pathconf(path, op);
710 #endif
712 #if _win32_botch_rename
714 extern int
715 rename(const char* fp, const char* tp)
717 int r;
718 int oerrno;
719 char fb[PATH_MAX];
720 char tb[PATH_MAX];
722 oerrno = errno;
723 if ((r = _rename(fp, tp)) && errno == ENOENT && execrate(fp, fb, sizeof(fb), 1))
725 if (execrate(tp, tb, sizeof(tb), 1))
726 tp = tb;
727 errno = oerrno;
728 r = _rename(fb, tp);
730 return r;
733 #endif
735 #if _win32_botch_stat
737 extern int
738 stat(const char* path, struct stat* st)
740 int r;
741 int oerrno;
742 char buf[PATH_MAX];
744 oerrno = errno;
745 if ((r = _stat(path, st)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
747 errno = oerrno;
748 r = _stat(buf, st);
750 return r;
753 #endif
755 #if _win32_botch_truncate
757 extern int
758 truncate(const char* path, off_t offset)
760 int r;
761 int oerrno;
762 char buf[PATH_MAX];
764 oerrno = errno;
765 if ((r = _truncate(path, offset)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
767 errno = oerrno;
768 r = _truncate(buf, offset);
770 return r;
773 #endif
775 #if _win32_botch_unlink
777 extern int
778 unlink(const char* path)
780 int r;
781 int drive;
782 int mask;
783 int suffix;
784 int stop;
785 int oerrno;
786 unsigned long base;
787 char buf[PATH_MAX];
788 char tmp[MAX_PATH];
790 #define DELETED_DIR_1 7
791 #define DELETED_DIR_2 16
793 static char deleted[] = "%c:\\temp\\.deleted\\%08x.%03x";
795 static int count = 0;
797 #if __CYGWIN__
799 DWORD fattr = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE;
800 DWORD share = FILE_SHARE_DELETE;
801 HANDLE hp;
802 struct stat st;
803 char nat[MAX_PATH];
805 oerrno = errno;
806 if (lstat(path, &st) || !S_ISREG(st.st_mode))
807 goto try_unlink;
808 cygwin_conv_to_full_win32_path(path, nat);
809 if (!strncasecmp(nat + 1, ":\\temp\\", 7))
810 goto try_unlink;
811 drive = nat[0];
812 path = (const char*)nat;
813 for (;;)
815 hp = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL);
816 if (hp != INVALID_HANDLE_VALUE)
818 CloseHandle(hp);
819 errno = oerrno;
820 return 0;
822 if (GetLastError() != ERROR_FILE_NOT_FOUND)
823 break;
824 if (path == (const char*)buf || !execrate(path, buf, sizeof(buf), 1))
826 errno = ENOENT;
827 return -1;
829 path = (const char*)buf;
831 #else
832 if (_access(path, 0))
833 #if _win32_botch_access
835 if (errno != ENOENT || !execrate(path, buf, sizeof(buf), 1) || _access(buf, 0))
836 return -1;
837 path = (const char*)buf;
839 #else
840 return -1;
841 #endif
842 drive = 'C':
843 #endif
846 * rename to a `deleted' path just in case the file is open
847 * otherwise directory readers may choke on phantom entries
850 base = ((getuid() & 0xffff) << 16) | (time(NiL) & 0xffff);
851 suffix = (getpid() & 0xfff) + count++;
852 snprintf(tmp, sizeof(tmp), deleted, drive, base, suffix);
853 if (!_rename(path, tmp))
855 path = (const char*)tmp;
856 goto try_delete;
858 if (errno != ENOTDIR && errno != ENOENT)
859 goto try_unlink;
860 tmp[DELETED_DIR_2] = 0;
861 if (_access(tmp, 0))
863 mask = umask(0);
864 tmp[DELETED_DIR_1] = 0;
865 if (_access(tmp, 0) && _mkdir(tmp, S_IRWXU|S_IRWXG|S_IRWXO))
867 umask(mask);
868 goto try_unlink;
870 tmp[DELETED_DIR_1] = '\\';
871 r = _mkdir(tmp, S_IRWXU|S_IRWXG|S_IRWXO);
872 umask(mask);
873 if (r)
874 goto try_unlink;
875 errno = 0;
877 tmp[DELETED_DIR_2] = '\\';
878 if (!errno && !_rename(path, tmp))
880 path = (const char*)tmp;
881 goto try_delete;
883 #if !__CYGWIN__
884 if (errno == ENOENT)
886 #if !_win32_botch_access
887 if (execrate(path, buf, sizeof(buf), 1) && !_rename(buf, tmp))
888 path = (const char*)tmp;
889 #endif
890 goto try_unlink;
892 #endif
893 stop = suffix;
896 snprintf(tmp, sizeof(tmp), deleted, drive, base, suffix);
897 if (!_rename(path, tmp))
899 path = (const char*)tmp;
900 goto try_delete;
902 if (++suffix > 0xfff)
903 suffix = 0;
904 } while (suffix != stop);
905 try_delete:
906 #if __CYGWIN__
907 hp = CreateFile(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL);
908 if (hp != INVALID_HANDLE_VALUE)
910 CloseHandle(hp);
911 errno = oerrno;
912 return 0;
914 #endif
915 try_unlink:
916 errno = oerrno;
917 return _unlink(path);
920 #endif
922 #if _win32_botch_utime
924 #if __CYGWIN__
927 * cygwin refuses to set st_ctime for some operations
928 * this rejects that refusal
931 static void
932 ctime_now(const char* path)
934 HANDLE hp;
935 SYSTEMTIME st;
936 FILETIME ct;
937 WIN32_FIND_DATA ff;
938 struct stat fs;
939 int oerrno;
940 char tmp[MAX_PATH];
942 if (_stat(path, &fs) || (fs.st_mode & S_IWUSR) || _chmod(path, (fs.st_mode | S_IWUSR) & S_IPERM))
943 fs.st_mode = 0;
944 cygwin_conv_to_win32_path(path, tmp);
945 hp = CreateFile(tmp, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
946 if (hp && hp != INVALID_HANDLE_VALUE)
948 GetSystemTime(&st);
949 SystemTimeToFileTime(&st, &ct);
950 SetFileTime(hp, &ct, 0, 0);
951 CloseHandle(hp);
953 if (fs.st_mode)
954 _chmod(path, fs.st_mode & S_IPERM);
955 errno = oerrno;
958 #else
960 #define ctime_now(p)
962 #endif
964 extern int
965 utimes(const char* path, const struct timeval* ut)
967 int r;
968 int oerrno;
969 char buf[PATH_MAX];
971 oerrno = errno;
972 if ((r = _utimes(path, ut)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
974 errno = oerrno;
975 r = _utimes(path = buf, ut);
977 if (!r)
978 ctime_now(path);
979 return r;
982 extern int
983 utime(const char* path, const struct utimbuf* ut)
985 int r;
986 int oerrno;
987 char buf[PATH_MAX];
989 oerrno = errno;
990 if ((r = _utime(path, ut)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
992 errno = oerrno;
993 r = _utime(path = buf, ut);
995 if (!r)
996 ctime_now(path);
997 return r;
1000 #endif
1002 #endif
1005 * some systems (sun) miss a few functions required by their
1006 * own bsd-like macros
1009 #if !_lib_bzero || defined(bzero)
1011 #undef bzero
1013 void
1014 bzero(void* b, size_t n)
1016 memset(b, 0, n);
1019 #endif
1021 #if !_lib_getpagesize || defined(getpagesize)
1023 #ifndef OMITTED
1024 #define OMITTED 1
1025 #endif
1027 #undef getpagesize
1029 #ifdef _SC_PAGESIZE
1030 #undef _AST_PAGESIZE
1031 #define _AST_PAGESIZE (int)sysconf(_SC_PAGESIZE)
1032 #else
1033 #ifndef _AST_PAGESIZE
1034 #define _AST_PAGESIZE 4096
1035 #endif
1036 #endif
1039 getpagesize()
1041 return _AST_PAGESIZE;
1044 #endif
1046 #if __CYGWIN__ && defined(__IMPORT__) && defined(__EXPORT__)
1048 #ifndef OMITTED
1049 #define OMITTED 1
1050 #endif
1053 * a few _imp__FUNCTION symbols are needed to avoid
1054 * static link multiple definitions
1057 #ifndef strtod
1058 __EXPORT__ double (*_imp__strtod)(const char*, char**) = strtod;
1059 #endif
1061 #endif
1063 #ifndef OMITTED
1065 NoN(omitted)
1067 #endif