diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 6203e825a..b301fc913 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,19 @@ +Sun Jul 9 01:19:06 2000 Christopher Faylor + + * cygwin.din: Export _getmode and getmode to allow querying of binary + state of an fd. + * external.cc (cygwin_internal): Add handling of perfile_table setting. + * fhandler.cc (perfile_table): New global. + (fhandler_base::get_default_fmode): New method to return a file's + default mode based on its name. + (fhandler_base::open): Use get_default_mode method to determine a + file's mode. Record file mode in file flags. + * fhandler.h (fhandler_base): Declare get_default_fmode + * syscalls.cc (getmode): New function. + * sys/cygwin.h (__cygwin_perfile): New structure. + (cygwin_getinfo_types): Move outside of WINVER conditional. + (per_process): Move inside of WINVER conditional. + Sat Jul 8 00:15:01 2000 Christopher Faylor * external.cc (cygwin_internal): Export __cygwin_user_data. diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index 22c113724..5c9139ccf 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -335,6 +335,8 @@ getlogin _getlogin = getlogin getmntent _getmntent = getmntent +getmode +_getmode = getmode get_osfhandle _get_osfhandle = get_osfhandle getpagesize diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index 6ebd8e36d..e626cf5ef 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -103,6 +103,10 @@ cygwin_internal (cygwin_getinfo_types t, ...) case CW_USER_DATA: return (DWORD) &__cygwin_user_data; + case CW_PERFILE: + perfile_table = va_arg (arg, struct __cygwin_perfile *); + return 0; + default: return (DWORD) -1; } diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index c68ac0d04..579de96ab 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -18,6 +18,8 @@ static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */ static char fhandler_disk_dummy_name[] = "some disk file"; +struct __cygwin_perfile *perfile_table = NULL; + DWORD binmode; int @@ -249,6 +251,27 @@ fhandler_base::raw_write (const void *ptr, size_t len) return bytes_written; } +#define ACCFLAGS(x) (x & (O_RDONLY | O_WRONLY | O_RDWR)) +int +fhandler_base::get_default_fmode (int flags) +{ + if (perfile_table) + { + size_t nlen = strlen (get_name ()); + unsigned accflags = ACCFLAGS (flags); + for (__cygwin_perfile *pf = perfile_table; pf->name; pf++) + { + size_t pflen = strlen (pf->name); + const char *stem = get_name () + nlen - pflen; + if (pflen > nlen || (stem != get_name () && !isdirsep (stem[-1]))) + continue; + else if (strcasematch (stem, pf->name) && ACCFLAGS (pf->flags) == accflags) + return pf->flags & ~(O_RDONLY | O_WRONLY | O_RDWR); + } + } + return __fmode; +} + /* Open system call handler function. Path is now already checked for symlinks */ int @@ -262,8 +285,6 @@ fhandler_base::open (int flags, mode_t mode) syscall_printf ("(%s, %p)", get_win32_name (), flags); - set_flags (flags); - if (get_win32_name () == NULL) { set_errno (ENOENT); @@ -352,17 +373,23 @@ fhandler_base::open (int flags, mode_t mode) rpos_ = 0; rsize_ = -1; int bin; - if (flags & (O_BINARY | O_TEXT)) - bin = flags & O_TEXT ? 0 : O_BINARY; - else if (__fmode & O_BINARY) + int fmode; + if ((bin = flags & (O_BINARY | O_TEXT))) + /* nothing to do */; + else if ((fmode = get_default_fmode (flags)) & O_BINARY) bin = O_BINARY; - else if (__fmode & O_TEXT) + else if (fmode & O_TEXT) bin = O_TEXT; else if (get_device () == FH_DISK) bin = get_w_binary () || get_r_binary (); else bin = binmode || get_w_binary () || get_r_binary (); + if (bin & O_TEXT) + bin = 0; + + set_flags (flags | (bin ? O_BINARY : O_TEXT)); + set_r_binary (bin); set_w_binary (bin); syscall_printf ("filemode set to %s", bin ? "binary" : "text"); diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 802fd2ac2..7ce116efd 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -107,6 +107,7 @@ enum #define FHSTATOFF 0 extern const char *windows_device_names[]; +extern struct __cygwin_perfile *perfile_table; #define __fmode (*(user_data->fmode_ptr)) class select_record; @@ -182,6 +183,8 @@ public: void set_w_binary (int b) { FHCONDSETF (b, WBINARY); FHSETF (WBINSET); } void set_r_binary (int b) { FHCONDSETF (b, RBINARY); FHSETF (RBINSET); } + int get_default_fmode (int flags); + int get_r_no_interrupt () { return FHISSETF (NOEINTR); } void set_r_no_interrupt (int b) { FHCONDSETF (b, NOEINTR); } diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 64141e58e..4dfa2b194 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -114,6 +114,7 @@ details. */ 23: Export new dll_crt0 interface and cygwin_user_data for use with crt0 startup code. 24: Export poll and _poll. + 25: Export getmode and _getmode. */ #define CYGWIN_VERSION_API_MAJOR 0 diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h index c6ac543a4..d2cf9482f 100644 --- a/winsup/cygwin/include/sys/cygwin.h +++ b/winsup/cygwin/include/sys/cygwin.h @@ -36,6 +36,59 @@ extern void cygwin_premain1 (int argc, char **argv); extern void cygwin_premain2 (int argc, char **argv); extern void cygwin_premain3 (int argc, char **argv); +struct __cygwin_perfile +{ + char *name; + unsigned flags; +}; + +#ifdef _PATH_PASSWD +extern HANDLE cygwin_logon_user (const struct passwd *, const char *); +#endif + +/* External interface stuff */ + +typedef enum + { + CW_LOCK_PINFO, + CW_UNLOCK_PINFO, + CW_GETTHREADNAME, + CW_GETPINFO, + CW_SETPINFO, + CW_SETTHREADNAME, + CW_GETVERSIONINFO, + CW_READ_V1_MOUNT_TABLES, + CW_USER_DATA, + CW_PERFILE + } cygwin_getinfo_types; + +#define CW_NEXTPID 0x80000000 // or with pid to get next one + +/* Flags associated with process_state */ +enum +{ + PID_NOT_IN_USE = 0x0000, // Free entry. + PID_IN_USE = 0x0001, // Entry in use. + PID_ZOMBIE = 0x0002, // Child exited: no parent wait. + PID_STOPPED = 0x0004, // Waiting for SIGCONT. + PID_TTYIN = 0x0008, // Waiting for terminal input. + PID_TTYOU = 0x0010, // Waiting for terminal output. + PID_ORPHANED = 0x0020, // Member of an orphaned process group. + PID_ACTIVE = 0x0040, // Pid accepts signals. + PID_CYGPARENT = 0x0080, // Set if parent was a cygwin app. + PID_SPLIT_HEAP = 0x0100, // Set if the heap has been split, + // which means we can't fork again. + PID_CLEAR = 0x0200, // Flag that pid should be cleared from parent's + // wait list + PID_SOCKETS_USED = 0x0400, // Set if process uses Winsock. + PID_INITIALIZING = 0x0800, // Set until ready to receive signals. + PID_USETTY = 0x1000, // Setting this enables or disables cygwin's + // tty support. This is inherited by + // all execed or forked processes. + PID_REPARENT = 0x2000 // child has execed +}; + +#ifdef WINVER /* This lives in the app and is initialized before jumping into the DLL. It should only contain stuff which the user's process needs to see, or which is needed before the user pointer is initialized, or is needed to @@ -126,11 +179,6 @@ struct per_process }; #define per_process_overwrite ((unsigned) &(((struct per_process *) NULL)->resourcelocks)) -#ifdef _PATH_PASSWD -extern HANDLE cygwin_logon_user (const struct passwd *, const char *); -#endif - -#ifdef WINVER extern void cygwin_set_impersonation_token (const HANDLE); /* included if is included */ @@ -139,21 +187,6 @@ extern int cygwin_attach_handle_to_fd (char *, int, HANDLE, mode_t, DWORD); #include -/* External interface stuff */ - -typedef enum - { - CW_LOCK_PINFO, - CW_UNLOCK_PINFO, - CW_GETTHREADNAME, - CW_GETPINFO, - CW_SETPINFO, - CW_SETTHREADNAME, - CW_GETVERSIONINFO, - CW_READ_V1_MOUNT_TABLES, - CW_USER_DATA - } cygwin_getinfo_types; - struct external_pinfo { pid_t pid; @@ -182,32 +215,6 @@ struct external_pinfo DWORD cygwin_internal (cygwin_getinfo_types, ...); #endif /*WINVER*/ -#define CW_NEXTPID 0x80000000 // or with pid to get next one - -/* Flags associated with process_state */ -enum -{ - PID_NOT_IN_USE = 0x0000, // Free entry. - PID_IN_USE = 0x0001, // Entry in use. - PID_ZOMBIE = 0x0002, // Child exited: no parent wait. - PID_STOPPED = 0x0004, // Waiting for SIGCONT. - PID_TTYIN = 0x0008, // Waiting for terminal input. - PID_TTYOU = 0x0010, // Waiting for terminal output. - PID_ORPHANED = 0x0020, // Member of an orphaned process group. - PID_ACTIVE = 0x0040, // Pid accepts signals. - PID_CYGPARENT = 0x0080, // Set if parent was a cygwin app. - PID_SPLIT_HEAP = 0x0100, // Set if the heap has been split, - // which means we can't fork again. - PID_CLEAR = 0x0200, // Flag that pid should be cleared from parent's - // wait list - PID_SOCKETS_USED = 0x0400, // Set if process uses Winsock. - PID_INITIALIZING = 0x0800, // Set until ready to receive signals. - PID_USETTY = 0x1000, // Setting this enables or disables cygwin's - // tty support. This is inherited by - // all execed or forked processes. - PID_REPARENT = 0x2000 // child has execed -}; - #ifdef __cplusplus }; #endif diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index b0251bffc..9594a4931 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1494,11 +1494,22 @@ setmode_helper (FILE *f) return 0; } +extern "C" int +getmode (int fd) +{ + if (dtable.not_open (fd)) + { + set_errno (EBADF); + return -1; + } + + return dtable[fd]->get_flags () & (O_BINARY | O_TEXT); +} + /* Set a file descriptor into text or binary mode, returning the previous mode. */ -extern "C" -int +extern "C" int setmode (int fd, int mode) { if (dtable.not_open (fd))