X-Git-Url: http://git.chise.org/gitweb/?p=chise%2Fxemacs-chise.git.1;a=blobdiff_plain;f=src%2Fnt.c;h=1e26fbbe1bf5971121d1ce48be0413da65d881bb;hp=1afa11a86cda031ea248149530c550cd4d977c3f;hb=62c9a41dc0be325de11e1e57032d0063fe54f331;hpb=3062d425fac0473eb5aa2efc0bb002f6ce0cb028 diff --git a/src/nt.c b/src/nt.c index 1afa11a..1e26fbb 100644 --- a/src/nt.c +++ b/src/nt.c @@ -1,4 +1,4 @@ -/* Utility and Unix shadow routines for XEmacs on Windows NT. +/* Utility and Unix shadow routines for XEmacs on MS Windows. Copyright (C) 1994, 1995 Free Software Foundation, Inc. This file is part of XEmacs. @@ -28,6 +28,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #define getwd _getwd #include "lisp.h" #undef getwd +#include "buffer.h" #include "systime.h" #include "syssignal.h" @@ -246,12 +247,12 @@ init_user_info (void) if (getenv ("HOME") == NULL) putenv ("HOME=c:/"); #endif - if (getenv ("SHELL") == NULL) - putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd"); - /* Set dir and shell from environment variables. */ + /* Set dir from environment variables. */ strcpy (the_passwd.pw_dir, (char *)get_home_directory()); - strcpy (the_passwd.pw_shell, getenv ("SHELL")); + /* We used to set pw_shell here, but the order is wrong (SHELL gets + init in callproc.c, called later in the init process) and pw_shell + is not used anywhere. */ } /* Normalize filename by converting all path separators to @@ -505,7 +506,7 @@ request_sigio (void) } #endif /* 0 */ -#define REG_ROOT "SOFTWARE\\GNU\\XEmacs" +#define REG_ROOT "SOFTWARE\\XEmacs\\XEmacs" LPBYTE nt_get_resource (char *key, LPDWORD lpdwtype) @@ -628,16 +629,16 @@ init_environment (void) renaming or deleting directories. (We also don't call chdir when running subprocesses for the same reason.) */ if (!GetCurrentDirectory (MAXPATHLEN, startup_dir)) - abort (); + ABORT (); { char *p; char modname[MAX_PATH]; if (!GetModuleFileName (NULL, modname, MAX_PATH)) - abort (); + ABORT (); if ((p = strrchr (modname, '\\')) == NULL) - abort (); + ABORT (); *p = 0; SetCurrentDirectory (modname); @@ -1177,12 +1178,11 @@ sys_rename (const char * oldname, const char * newname) #endif /* 0 */ static FILETIME utc_base_ft; +static long double utc_base; static int init = 0; #if 0 -static long double utc_base; - time_t convert_time (FILETIME ft) { @@ -1216,11 +1216,6 @@ convert_time (FILETIME ft) } #else -#if defined(MINGW) && CYGWIN_VERSION_DLL_MAJOR <= 21 -#define LowPart u.LowPart -#define HighPart u.HighPart -#endif - static LARGE_INTEGER utc_base_li; time_t @@ -1361,7 +1356,7 @@ generate_inode_val (const char * name) doesn't resolve aliasing due to subst commands, or recognize hard links. */ if (!win32_get_long_filename ((char *)name, fullname, MAX_PATH)) - abort (); + ABORT (); parse_root (fullname, &p); /* Normal Win32 filesystems are still case insensitive. */ @@ -1454,9 +1449,9 @@ mswindows_fstat (int desc, struct stat * buf) /* determine rwx permissions */ if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) - permission = _S_IREAD; + permission = _S_IREAD | _S_IEXEC; else - permission = _S_IREAD | _S_IWRITE; + permission = _S_IREAD | _S_IEXEC |_S_IWRITE; if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) permission |= _S_IEXEC; @@ -1479,6 +1474,7 @@ mswindows_stat (const char * path, struct stat * buf) int permission; int len; int rootdir = FALSE; + int errm; if (path == NULL || buf == NULL) { @@ -1501,13 +1497,16 @@ mswindows_stat (const char * path, struct stat * buf) rootdir = (path >= name + len - 1 && (IS_DIRECTORY_SEP (*path) || *path == 0)); name = strcpy ((char *)alloca (len + 2), name); - + errm = SetErrorMode (SEM_FAILCRITICALERRORS + | SEM_NOOPENFILEERRORBOX); if (rootdir) { if (!IS_DIRECTORY_SEP (name[len-1])) strcat (name, "\\"); + if (GetDriveType (name) < 2) { + SetErrorMode (errm); errno = ENOENT; return -1; } @@ -1537,14 +1536,15 @@ mswindows_stat (const char * path, struct stat * buf) } else { - fh = FindFirstFile (name, &wfd); - if (fh == INVALID_HANDLE_VALUE) - { - errno = ENOENT; - return -1; + fh = FindFirstFile (name, &wfd); + if (fh == INVALID_HANDLE_VALUE) + { + SetErrorMode (errm); + errno = ENOENT; + return -1; + } + FindClose (fh); } - FindClose (fh); - } } if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) @@ -1590,6 +1590,7 @@ mswindows_stat (const char * path, struct stat * buf) } else { + SetErrorMode (errm); errno = EACCES; return -1; } @@ -1602,6 +1603,8 @@ mswindows_stat (const char * path, struct stat * buf) fake_inode = 0; } + SetErrorMode (errm); + #if 0 /* Not sure if there is any point in this. */ if (!NILP (Vwin32_generate_fake_inodes)) @@ -1635,22 +1638,12 @@ mswindows_stat (const char * path, struct stat * buf) /* determine rwx permissions */ if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) - permission = _S_IREAD; + permission = _S_IREAD | _S_IEXEC; else - permission = _S_IREAD | _S_IWRITE; + permission = _S_IREAD | _S_IEXEC |_S_IWRITE; if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) permission |= _S_IEXEC; - else - { - char * p = strrchr (name, '.'); - if (p != NULL && - (stricmp (p, ".exe") == 0 || - stricmp (p, ".com") == 0 || - stricmp (p, ".bat") == 0 || - stricmp (p, ".cmd") == 0)) - permission |= _S_IEXEC; - } buf->st_mode |= permission | (permission >> 3) | (permission >> 6); @@ -1829,7 +1822,8 @@ unsigned signal_block_mask = 0; /* Signal pending mask: bit set to 1 means sig is pending */ unsigned signal_pending_mask = 0; -mswindows_sighandler mswindows_sigset (int nsig, mswindows_sighandler handler) +mswindows_sighandler +mswindows_sigset (int nsig, mswindows_sighandler handler) { /* We delegate some signals to the system function */ if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT) @@ -1849,40 +1843,43 @@ mswindows_sighandler mswindows_sigset (int nsig, mswindows_sighandler handler) } } -int mswindows_sighold (int nsig) +int +mswindows_sighold (int nsig) { if (nsig < 0 || nsig > SIG_MAX) return errno = EINVAL; - signal_block_mask |= sigmask(nsig); + signal_block_mask |= sigmask (nsig); return 0; } -int mswindows_sigrelse (int nsig) +int +mswindows_sigrelse (int nsig) { if (nsig < 0 || nsig > SIG_MAX) return errno = EINVAL; - signal_block_mask &= ~sigmask(nsig); + signal_block_mask &= ~sigmask (nsig); - if (signal_pending_mask & sigmask(nsig)) + if (signal_pending_mask & sigmask (nsig)) mswindows_raise (nsig); return 0; } -int mswindows_sigpause (int nsig) +int +mswindows_sigpause (int nsig) { - /* This is currently not called, because the only - call to sigpause inside XEmacs is with SIGCHLD - parameter. Just in case, we put an assert here, - so anyone who will add a call to sigpause will - be surprised (or surprise someone else...) */ + /* This is currently not called, because the only call to sigpause + inside XEmacs is with SIGCHLD parameter. Just in case, we put an + assert here, so anyone adds a call to sigpause will be surprised + (or surprise someone else...) */ assert (0); return 0; } -int mswindows_raise (int nsig) +int +mswindows_raise (int nsig) { /* We delegate some raises to the system routine */ if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT) @@ -1892,9 +1889,9 @@ int mswindows_raise (int nsig) return errno = EINVAL; /* If the signal is blocked, remember to issue later */ - if (signal_block_mask & sigmask(nsig)) + if (signal_block_mask & sigmask (nsig)) { - signal_pending_mask |= sigmask(nsig); + signal_pending_mask |= sigmask (nsig); return 0; } @@ -1903,7 +1900,7 @@ int mswindows_raise (int nsig) if (signal_handlers[nsig] != SIG_DFL) { - (*signal_handlers[nsig])(nsig); + (*signal_handlers[nsig]) (nsig); return 0; } @@ -1915,122 +1912,6 @@ int mswindows_raise (int nsig) return 0; } -/*--------------------------------------------------------------------*/ -/* Async timers */ -/*--------------------------------------------------------------------*/ - -/* We emulate two timers, one for SIGALRM, another for SIGPROF. - - itimerproc() function has an implementation limitation: it does - not allow to set *both* interval and period. If an attempt is - made to set both, and then they are unequal, the function - asserts. - - Minimum timer resolution on Win32 systems varies, and is greater - than or equal than 1 ms. The resolution is always wrapped not to - attempt to get below the system defined limit. - */ - -/* Timer precision, denominator of one fraction: for 100 ms - interval, request 10 ms precision - */ -const int timer_prec = 10; - -/* Last itimervals, as set by calls to setitimer */ -static struct itimerval it_alarm; -static struct itimerval it_prof; - -/* Timer IDs as returned by MM */ -MMRESULT tid_alarm = 0; -MMRESULT tid_prof = 0; - -static void CALLBACK timer_proc (UINT uID, UINT uMsg, DWORD dwUser, - DWORD dw1, DWORD dw2) -{ - /* Just raise a signal indicated by dwUser parameter */ - mswindows_raise (dwUser); -} - -/* Divide time in ms specified by IT by DENOM. Return 1 ms - if division results in zero */ -static UINT period (const struct itimerval* it, UINT denom) -{ - static TIMECAPS time_caps; - - UINT res; - const struct timeval* tv = - (it->it_value.tv_sec == 0 && it->it_value.tv_usec == 0) - ? &it->it_interval : &it->it_value; - - /* Zero means stop timer */ - if (tv->tv_sec == 0 && tv->tv_usec == 0) - return 0; - - /* Convert to ms and divide by denom */ - res = (tv->tv_sec * 1000 + (tv->tv_usec + 500) / 1000) / denom; - - /* Converge to minimum timer resolution */ - if (time_caps.wPeriodMin == 0) - timeGetDevCaps (&time_caps, sizeof(time_caps)); - - if (res < time_caps.wPeriodMin) - res = time_caps.wPeriodMin; - - return res; -} - -static int setitimer_helper (const struct itimerval* itnew, - struct itimerval* itold, struct itimerval* itcurrent, - MMRESULT* tid, DWORD sigkind) -{ - UINT delay, resolution, event_type; - - /* First stop the old timer */ - if (*tid) - { - timeKillEvent (*tid); - timeEndPeriod (period (itcurrent, timer_prec)); - *tid = 0; - } - - /* Return old itimerval if requested */ - if (itold) - *itold = *itcurrent; - - *itcurrent = *itnew; - - /* Determine if to start new timer */ - delay = period (itnew, 1); - if (delay) - { - resolution = period (itnew, timer_prec); - event_type = (itnew->it_value.tv_sec == 0 && itnew->it_value.tv_usec == 0) - ? TIME_ONESHOT : TIME_PERIODIC; - timeBeginPeriod (resolution); - *tid = timeSetEvent (delay, resolution, timer_proc, sigkind, event_type); - } - - return !delay || *tid; -} - -int setitimer (int kind, const struct itimerval* itnew, - struct itimerval* itold) -{ - /* In this version, both interval and value are allowed - only if they are equal. */ - assert ((itnew->it_value.tv_sec == 0 && itnew->it_value.tv_usec == 0) - || (itnew->it_interval.tv_sec == 0 && itnew->it_interval.tv_usec == 0) - || (itnew->it_value.tv_sec == itnew->it_interval.tv_sec && - itnew->it_value.tv_usec == itnew->it_interval.tv_usec)); - - if (kind == ITIMER_REAL) - return setitimer_helper (itnew, itold, &it_alarm, &tid_alarm, SIGALRM); - else if (kind == ITIMER_PROF) - return setitimer_helper (itnew, itold, &it_prof, &tid_prof, SIGPROF); - else - return errno = EINVAL; -} - /*--------------------------------------------------------------------*/ /* Memory-mapped files */ @@ -2242,13 +2123,90 @@ mswindows_executable_type (const char * filename, int * is_dos_app, close_file_data (&executable); } +static void +convert_from_time_t (time_t time, FILETIME * pft) +{ + long double tmp; + + if (!init) + { + /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */ + SYSTEMTIME st; + + st.wYear = 1970; + st.wMonth = 1; + st.wDay = 1; + st.wHour = 0; + st.wMinute = 0; + st.wSecond = 0; + st.wMilliseconds = 0; + + SystemTimeToFileTime (&st, &utc_base_ft); + utc_base = (long double) utc_base_ft.dwHighDateTime + * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime; + init = 1; + } + + /* time in 100ns units since 1-Jan-1601 */ + tmp = (long double) time * 1e7 + utc_base; + pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024)); + pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * + pft->dwHighDateTime); +} + +int +mswindows_utime (Lisp_Object path, struct utimbuf *times) +{ + struct utimbuf deftime; +#if 0 + HANDLE fh; +#endif + static FILETIME mtime; + static FILETIME atime; + Extbyte *filename; + + if (times == NULL) + { + deftime.modtime = deftime.actime = time (NULL); + times = &deftime; + } + + LISP_STRING_TO_EXTERNAL (path, filename, Qmswindows_tstr); + /* APA: SetFileTime fails to set mtime correctly (always 1-Jan-1970) */ +#if 0 + /* Need write access to set times. */ + fh = CreateFile (filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, OPEN_EXISTING, 0, NULL); + if (fh) + { + convert_from_time_t (times->actime, &atime); + convert_from_time_t (times->modtime, &mtime); + if (!SetFileTime (fh, NULL, &atime, &mtime)) + { + CloseHandle (fh); + errno = EACCES; + return -1; + } + CloseHandle (fh); + } + else + { + errno = EINVAL; + return -1; + } + return 0; +#else + return utime (filename, times); +#endif +} + /* Close the system structures associated with the given file. */ void close_file_data (file_data *p_file) { - UnmapViewOfFile (p_file->file_base); - CloseHandle (p_file->file_mapping); - CloseHandle (p_file->file); + UnmapViewOfFile (p_file->file_base); + CloseHandle (p_file->file_mapping); + CloseHandle (p_file->file); } void