Mail Archives: cygwin/2001/09/29/00:15:56
------=_NextPart_000_0272_01C148F1.170E5CE0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
----- Original Message -----
From: "friedman_hill ernest j" <ejfried AT california DOT sandia DOT gov>
To: <cygwin AT cygwin DOT com>
Sent: Saturday, September 29, 2001 8:16 AM
Subject: Re: qmail-1.03: any volunteers?!
>
> Here's the begining of a simple mkfifo implementation for Cygwin. I
Maybe I'm dense... but where is it? I can't see a patch or a url
reference in your email. I've also written a fifo implemention, feature
complete except for a distressing tendency to die on fork, which I
haven't looked at since february this year (and since then I've learnt a
_lot_ more about fork()'s guts. Therefore I think I'm in a position to
perform peer review for your "simple" implementation (Note: I have no
idea what you are implying by referring to it as simple). I assume you
mean somewhat featureless, as opposed to "very small and clear code".
Please correct my assumption!).
> did this about a year ago. I went so far as to get the paperwork
> approved to let me sign this over to Cygnus. I tried to get some help
> from this list on how to integrate it with Cygwin, but was met with
I don't recall this. So I did a search under "ejfried" of the cygwin and
cygwin-developers list archives...
I found http://sources.redhat.com/ml/cygwin/2001-02/msg00931.html which
was a reference to ORBS trouble, and Chris not wanting to discuss a fifo
implementation in private - which IMO is absolutely good common sense.
Mailing lists for developers are essential to keep a project syncronised
and working well, without too much duplicate effort being spent. I
certainly didn't see any
> sufficiently rude and unhelpful responses
to your emails - even though you apparently wrote your responses
off-list! (see for example a reply to an email from you, but your email
is no on the list archive...
http://sources.redhat.com/ml/cygwin/2000-09/msg00447.html).
> that I abandoned the project
> (I suspect this happens to quite a few folks who are interested in
> contributing, but don't have the free time to devote to untangling the
> Cygwin "kernel" source themselves. But I digress...)
Possibly. There are dedicated resources for developers - the developer
list, the cygwin internal documentation. See the recent thread on magic
dir listing for example. It certainly is a shame you ended up abandoning
it - I could have saved myself a bunch of time.
> You can't use Windows named pipes to implement UNIX fifos -- the
> semantics are just too different.
Aren't they just :].
> Anyway, anyone who would like to try their hand at implementing fifos
> may feel free to use this as a starting point.
I would be interested in comparing it with mine. Could you please post
the URL?
I've attached a (somewhat rusty) patch kit for my implementation. It's
currently broken - I started a little, errrm, virtual function bomb
approach when I didn't really grok what happens with HANDLEs and fork().
(As I mentioned, no time yet to revisit). Theres also a bunch of crud in
there from other partial projects. This working dir jsut recently got
put aside, and I've been cleaning things up.. not soon enough to make
life easy for anyone reviewing this (yet).
I have done a quick and dirty touchup to the patch however. As a result
you need to add fhandler_fifo.cc to Makefile.in. Lastly fifo.patch was
generated in the winsup dir.
Rob
------=_NextPart_000_0272_01C148F1.170E5CE0
Content-Type: application/octet-stream;
name="fhandler_fifo.cc"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="fhandler_fifo.cc"
/* fhandler.cc. See console.cc for fhandler_console functions.=0A=
=0A=
Copyright 1996, 1997, 1998, 1999, 2000, 2001 Cygnus Solutions.=0A=
=0A=
This file is part of Cygwin.=0A=
=0A=
This software is a copyrighted work licensed under the terms of the=0A=
Cygwin license. Please consult the file "CYGWIN_LICENSE" for=0A=
details. */=0A=
=0A=
#include "winsup.h"=0A=
#include <sys/fcntl.h>=0A=
#include <errno.h>=0A=
#include <unistd.h>=0A=
#include <stdlib.h>=0A=
#include "fhandler.h"=0A=
#include "dtable.h"=0A=
#include "cygheap.h"=0A=
#include <sys/cygwin.h>=0A=
#include <signal.h>=0A=
#include "cygerrno.h"=0A=
#include "perprocess.h"=0A=
#include "path.h"=0A=
#include "shared_info.h"=0A=
#include "host_dependent.h"=0A=
#include "security.h"=0A=
#include <stdio.h>=0A=
=0A=
=0A=
static char fhandler_fifo_dummy_name[] =3D "some fifo";=0A=
=0A=
/**********************************************************************/=0A=
/* fhandler_fifo */=0A=
=0A=
/* Observed behaviour of fifo's on un*x.=0A=
*=0A=
* First reader or writer blocks.=0A=
* pipe reads return EOF when last writer quits=0A=
* pipe writes return -1 and error EPIPE when the last reader quits.=0A=
*/=0A=
=0A=
fhandler_fifo::fhandler_fifo (const char *name):=0A=
fhandler_base (FH_FIFO, name)=0A=
{=0A=
set_cb (sizeof *this);=0A=
set_no_free_names ();=0A=
set_need_fork_fixup ();=0A=
unix_path_name =3D win32_path_name =3D fhandler_fifo_dummy_name;=0A=
}=0A=
=0A=
int=0A=
fhandler_fifo::open (const char *path, int flags, mode_t mode)=0A=
{=0A=
syscall_printf ("(%s, %p)", path, flags);=0A=
=0A=
/* O_NOSYMLINK is an internal flag for implementing lstat, nothing =
more. */=0A=
path_conv real_path (path, (flags & O_NOSYMLINK) ?=0A=
PC_SYM_NOFOLLOW : PC_SYM_FOLLOW);=0A=
=0A=
if (real_path.error &&=0A=
(flags & O_NOSYMLINK || real_path.error !=3D ENOENT=0A=
|| !(flags & O_CREAT)))=0A=
{=0A=
set_errno (real_path.error);=0A=
syscall_printf ("0 =3D fhandler_fifo::open (%s, %p)", path, flags);=0A=
return 0;=0A=
}=0A=
=0A=
set_name (path, real_path.get_win32 ());=0A=
set_no_free_names (0);=0A=
return open (real_path, flags, mode);=0A=
}=0A=
=0A=
int=0A=
fhandler_fifo::open (path_conv & real_path, int flags, mode_t mode)=0A=
{=0A=
if (get_win32_name () =3D=3D fhandler_fifo_dummy_name)=0A=
{=0A=
win32_path_name =3D real_path.get_win32 ();=0A=
set_no_free_names ();=0A=
}=0A=
=0A=
if (real_path.isbinary ())=0A=
{=0A=
set_r_binary (1);=0A=
set_w_binary (1);=0A=
}=0A=
=0A=
set_has_acls (real_path.has_acls ());=0A=
=0A=
if (real_path.file_attributes () !=3D (DWORD) - 1=0A=
&& (real_path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY))=0A=
{=0A=
set_errno (EPIPE);=0A=
syscall_printf=0A=
("fhandler_fifo::open attempt to open a directory as a FIFO\n");=0A=
}=0A=
=0A=
system_printf ("FIFO opening : %s\n", real_path.get_win32 ());=0A=
const char *path =3D get_name ();=0A=
=0A=
/* insert OS test here - build security descriptor for NT */=0A=
/* and GLOBAL\ prefix for terminal serices */=0A=
=0A=
=0A=
=0A=
if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) =3D=3D O_RDONLY)=0A=
{=0A=
// fifoaccess =3D FILE_MAP_READ;=0A=
reader =3D 1;=0A=
writer =3D 0;=0A=
}=0A=
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) =3D=3D O_WRONLY)=0A=
{=0A=
// fifoaccess =3D FILE_MAP_WRITE;=0A=
reader =3D 0;=0A=
writer =3D 1;=0A=
}=0A=
else=0A=
{=0A=
// fifoaccess =3D FILE_MAP_WRITE;=0A=
reader =3D 1;=0A=
writer =3D 1;=0A=
}=0A=
=0A=
set_flags(flags);=0A=
=0A=
=0A=
unsigned int created =3D 0;=0A=
SYSTEM_INFO sysinfo;=0A=
size_t buffer_offset;=0A=
=0A=
// todo enter the FIFO global mutex=0A=
=0A=
// if os=3Dnt4 ts or win2k or above add "Global\" as a prefix.=0A=
=0A=
// setup our names=0A=
snprintf (filemapname, MAX_PATH, "FIFOFM%s", path);=0A=
snprintf (rrname, MAX_PATH, "FIFORR%s", path);=0A=
snprintf (rmname, MAX_PATH, "FIFORM%s", path);=0A=
snprintf (wmname, MAX_PATH, "FIFOWM%s", path);=0A=
snprintf (dmname, MAX_PATH, "FIFODM%s", path);=0A=
snprintf (wdname, MAX_PATH, "FIFOWD%s", path);=0A=
snprintf (rsname, MAX_PATH, "FIFORS%s", path);=0A=
snprintf (wsname, MAX_PATH, "FIFOWS%s", path);=0A=
=0A=
GetSystemInfo (&sysinfo);=0A=
if (sysinfo.dwAllocationGranularity >=3D sizeof (class fifoshared))=0A=
buffer_offset =3D sysinfo.dwAllocationGranularity;=0A=
else=0A=
buffer_offset =3D=0A=
sysinfo.dwAllocationGranularity * (1 +=0A=
sizeof (class fifoshared) /=0A=
sysinfo.dwAllocationGranularity);=0A=
=0A=
// FIXME: we need two file map objects. One for the header (r/w for =
every allowed user=0A=
// and one for data transfer (access only r or w as per file access =
rights=0A=
filemap =3D CreateFileMapping (INVALID_HANDLE_VALUE, // system =
pagefile.=0A=
/* default security - FIXME set allowed access from file permissions */=0A=
&sec_none,=0A=
// and set this appropriately.=0A=
PAGE_READWRITE, // protection=0A=
0x00000000, 0x00100000 + buffer_offset, // 1 Mb data, =0A=
filemapname // object name=0A=
);=0A=
=0A=
/* This is not quite what we need to test the file access permissions, =
but it's a =0A=
* starting point.*/=0A=
#if 0=0A=
HANDLE thehandle;=0A=
thehandle =3D CreateFile (win32_path_name_, access_,=0A=
FILE_SHARE_READ | FILE_SHARE_WRITE,=0A=
&sec_all_nih, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,=0A=
NULL);=0A=
=0A=
is_open =3D 1;=0A=
=0A=
return 1; /*success */=0A=
#endif=0A=
=0A=
=0A=
if (filemap =3D=3D NULL)=0A=
{=0A=
system_printf ("failed to open mapping: %d\n", GetLastError ());=0A=
=0A=
}=0A=
else=0A=
{=0A=
if (GetLastError () !=3D ERROR_ALREADY_EXISTS)=0A=
created =3D 1;=0A=
/* FIXME: FOR all the create routines: use the security descriptor =
created above */=0A=
readreadyevent =3D CreateEvent (&sec_none, // SD =0A=
FALSE, // reset type=0A=
FALSE, // initial state=0A=
rrname // object name=0A=
);=0A=
=0A=
if (readreadyevent =3D=3D NULL)=0A=
{=0A=
system_printf ("failed to open event : %d\n", GetLastError ());=0A=
//close the filemap=0A=
}=0A=
=0A=
writingmutex =3D CreateMutex (&sec_none, // SD=0A=
FALSE, // initial owner=0A=
wmname // object name=0A=
);=0A=
=0A=
if (writingmutex =3D=3D NULL)=0A=
{=0A=
system_printf ("failed to open write mutex : %d\n",=0A=
GetLastError ());=0A=
//close the event and the filemap=0A=
}=0A=
=0A=
readmutex =3D CreateMutex (&sec_none, // SD=0A=
FALSE, // initial owner=0A=
rmname // object name=0A=
);=0A=
=0A=
if (readmutex =3D=3D NULL)=0A=
{=0A=
system_printf ("failed to open read mutex : %d\n", GetLastError ());=0A=
//close the event and the filemap andt eh write mutex=0A=
}=0A=
=0A=
datamutex =3D CreateMutex (&sec_none, // SD=0A=
FALSE, // initial owner=0A=
dmname // object name=0A=
);=0A=
=0A=
if (datamutex =3D=3D NULL)=0A=
{=0A=
system_printf ("failed to open read mutex : %d\n", GetLastError ());=0A=
//close the event and the filemap andt eh write mutex=0A=
}=0A=
=0A=
writedoneevent =3D CreateEvent (&sec_none, // SD =0A=
FALSE, // reset type=0A=
FALSE, // initial state=0A=
wdname // object name=0A=
);=0A=
=0A=
if (readreadyevent =3D=3D NULL)=0A=
{=0A=
system_printf ("failed to open event : %d\n", GetLastError ());=0A=
//close the event and the filemap and both mutexs=0A=
}=0A=
=0A=
guts =3D=0A=
(class fifoshared *) MapViewOfFile (filemap, FILE_MAP_WRITE, 0, 0, 0);=0A=
=0A=
if (guts =3D=3D NULL)=0A=
{=0A=
system_printf ("failed to map fifo file to memory: %d\n",=0A=
GetLastError ());=0A=
//close both event and the filemap and both mutexs=0A=
}=0A=
=0A=
// FIXME: SEH for read and writes?=0A=
=0A=
if (created)=0A=
{=0A=
if (reader)=0A=
guts->readers =3D 1;=0A=
else=0A=
guts->readers =3D 0;=0A=
if (writer)=0A=
guts->writers =3D 1;=0A=
else=0A=
guts->writers =3D 0;=0A=
guts->buffer_offset =3D buffer_offset;=0A=
guts->buffer_length =3D 0x00100000; //1 Mb=0A=
guts->data_length =3D 0; // how much data is ready to be read (starts =
at=0A=
guts->data_offset =3D 0; // data_offset=0A=
guts->pipeactive =3D 0; // 0 =3D pipe waiting for an open=0A=
}=0A=
else=0A=
{=0A=
if (guts->buffer_offset !=3D buffer_offset)=0A=
{=0A=
system_printf=0A=
("incorrect data offset - check for multiple cygwin dll's \n");=0A=
//close both event and the filemap and both mutexs and free the =
mapped view=0A=
}=0A=
if (reader)=0A=
guts->readers++;=0A=
if (writer)=0A=
guts->writers++;=0A=
}=0A=
=0A=
// FIX ME set the file map read/write to the requested access.=0A=
filedata =3D=0A=
MapViewOfFile (filemap, FILE_MAP_WRITE, 0, guts->buffer_offset,=0A=
guts->buffer_length);=0A=
=0A=
if (filedata =3D=3D NULL)=0A=
{=0A=
system_printf ("failed to map fifo data file to memory: %d\n",=0A=
GetLastError ());=0A=
//close both event and the filemap and both mutexs and the first =
file view=0A=
}=0A=
=0A=
=0A=
}=0A=
=0A=
system_printf("FIFO opened\n");=0A=
// FIXME free the FIFO mutex;=0A=
return 1;=0A=
=0A=
=0A=
#if 0=0A=
/* We don't care about the _actual_ file. Maybe we should for locking =
purposes? */=0A=
int res =3D this->fhandler_base::open (flags, mode);=0A=
=0A=
if (!res)=0A=
goto out;=0A=
=0A=
/* This is for file systems known for having a buggy CreateFile call=0A=
which might return a valid HANDLE without having actually opened=0A=
the file.=0A=
The only known file system to date is the SUN NFS Solstice Client =
3.1=0A=
which returns a valid handle when trying to open a file in a non=0A=
existant directory. */=0A=
if (real_path.has_buggy_open ()=0A=
&& GetFileAttributes (win32_path_name_) =3D=3D (DWORD) - 1)=0A=
{=0A=
debug_printf ("Buggy open detected.");=0A=
close ();=0A=
set_errno (ENOENT);=0A=
return 0;=0A=
}=0A=
=0A=
extern BOOL allow_ntea;=0A=
=0A=
if (real_path.isdisk ()=0A=
&& (real_path.exec_state () =3D=3D dont_know_if_executable)=0A=
&& !allow_ntea && (!allow_ntsec || !real_path.has_acls ()))=0A=
{=0A=
DWORD done;=0A=
char magic[3];=0A=
/* FIXME should we use /etc/magic ? */=0A=
magic[0] =3D magic[1] =3D magic[2] =3D '\0';=0A=
ReadFile (get_handle (), magic, 3, &done, 0);=0A=
if (has_exec_chars (magic, done))=0A=
real_path.set_exec ();=0A=
if (!(flags & O_APPEND))=0A=
SetFilePointer (get_handle (), 0, 0, FILE_BEGIN);=0A=
}=0A=
=0A=
if (flags & O_APPEND)=0A=
SetFilePointer (get_handle (), 0, 0, FILE_END);=0A=
=0A=
set_symlink_p (real_path.issymlink ());=0A=
set_execable_p (real_path.exec_state ());=0A=
set_socket_p (real_path.issocket ());=0A=
=0A=
out:=0A=
syscall_printf ("%d =3D fhandler_fifo::open (%s, %p)", res,=0A=
get_win32_name (), flags);=0A=
return res;=0A=
#endif=0A=
}=0A=
=0A=
=0A=
int=0A=
fhandler_fifo::close ()=0A=
{=0A=
int rv =3D 0;=0A=
// FIXME Get the FIFO mutex=0A=
if (!filemap)=0A=
return 0; // what for already closed files?=0A=
else=0A=
{=0A=
if (reader)=0A=
guts->readers--;=0A=
if (writer)=0A=
guts->writers--;=0A=
if (!(guts->readers) || !(guts->writers))=0A=
{=0A=
guts->pipeactive =3D 2; // 2 =3D closed;=0A=
system_printf ("last reader or writer closed the pipe\n");=0A=
system_printf ("Telling the current blocked writers");=0A=
PulseEvent (readreadyevent);=0A=
system_printf ("... and readers\n");=0A=
PulseEvent (writedoneevent);=0A=
}=0A=
system_printf ("on close: readers %d\n", guts->readers);=0A=
system_printf ("on close: writers %d\n", guts->writers);=0A=
if (!CloseHandle (filemap))=0A=
rv =3D -1; /* what error !?!?! */=0A=
filemap=3DNULL;=0A=
if (!CloseHandle (readreadyevent))=0A=
rv =3D -1; /* what error !?!?! */=0A=
readreadyevent=3DNULL;=0A=
if (!CloseHandle (writingmutex))=0A=
rv =3D -1; /* what error !?!?! */=0A=
writingmutex=3DNULL;=0A=
if (!CloseHandle (readmutex))=0A=
rv =3D -1; /* what error !?!?! */=0A=
readmutex=3DNULL;=0A=
if (!CloseHandle (datamutex))=0A=
rv =3D -1; /* what error !?!?! */=0A=
datamutex=3DNULL;=0A=
if (!CloseHandle (writedoneevent))=0A=
rv =3D -1; /* what error !?!?! */=0A=
writedoneevent=3DNULL;=0A=
if (!UnmapViewOfFile (filedata))=0A=
rv =3D -1; /* what error !?!?! */=0A=
filedata=3DNULL;=0A=
if (!UnmapViewOfFile (guts))=0A=
rv =3D -1; /* what error !?!?! */=0A=
guts=3DNULL;=0A=
}=0A=
=0A=
=0A=
// FIXME free the FIFO mutex.=0A=
=0A=
=0A=
#if 0=0A=
int res;=0A=
if ((res =3D this->fhandler_base::close ()) =3D=3D 0)=0A=
cygwin_shared->delqueue.process_queue ();=0A=
return res;=0A=
#endif=0A=
return rv; /* Success. Failure is -1 */=0A=
}=0A=
=0A=
=0A=
int=0A=
fhandler_fifo::dup (fhandler_base * child)=0A=
{=0A=
fhandler_fifo *fhc =3D (fhandler_fifo *) child;=0A=
=0A=
if (!fhc->open (get_name (), get_flags (), 0))=0A=
system_printf ("error opening fifo, %E");=0A=
=0A=
=0A=
#if 0=0A=
fhandler_dev_clipboard *fhc =3D (fhandler_dev_clipboard *) child;=0A=
=0A=
if (!fhc->open (get_name (), get_flags (), 0))=0A=
system_printf ("error opening clipboard, %E");=0A=
=0A=
fhc->membuffer =3D membuffer;=0A=
fhc->pos =3D pos;=0A=
fhc->msize =3D msize;=0A=
#endif=0A=
return 0;=0A=
}=0A=
=0A=
/* -1 =3D error. 0=3D EOF. + =3D bytes read */=0A=
int=0A=
fhandler_fifo::write (const void *buf, size_t len)=0A=
{=0A=
unsigned int t;=0A=
size_t current_length;=0A=
size_t current_offset;=0A=
// FIXME: did we open with write permissions?=0A=
// FIXME: is the fd open? can it get this far if it's closed?=0A=
// FIXME: is len > max_positive_int ? =0A=
syscall_printf ("fhandler_fifo::write %x, %d\n",=0A=
buf,len);=0A=
t =3D WaitForSingleObject (writingmutex, INFINITE // time-out interval=0A=
);=0A=
if (t =3D=3D WAIT_OBJECT_0)=0A=
{=0A=
syscall_printf ("fhandler_fifo::write we have the write mutex %d =
\n", GetLastError ());=0A=
current_length =3D 0;=0A=
current_offset =3D 0;=0A=
t =3D WaitForSingleObject (datamutex, INFINITE);=0A=
if (t !=3D WAIT_OBJECT_0)=0A=
{=0A=
/* an error of some sort */=0A=
system_printf=0A=
("Error getting the datamutex - bad exit on the pipe...?? %d %d \n",=0A=
t, GetLastError ());=0A=
}=0A=
while (current_offset < len)=0A=
{=0A=
syscall_printf ("fhandler_fifo::write is there any queued data ? ");=0A=
while (guts->data_length && guts->pipeactive < 2)=0A=
{=0A=
system_printf ("fhandler_fifo::write %d bytes still in the =
pipe\n",=0A=
guts->data_length);=0A=
if (guts->pipeactive > 1)=0A=
{=0A=
syscall_printf ("fhandler_fifo::write and the pipe has been =
closed\n");=0A=
ReleaseMutex (datamutex);=0A=
ReleaseMutex (writingmutex);=0A=
set_errno(EPIPE);=0A=
return -1;=0A=
}=0A=
if (get_flags() & O_NONBLOCK)=0A=
{=0A=
syscall_printf("fhandler_fifo::write returning due to O_NONBLOCK\n");=0A=
set_errno(EAGAIN);=0A=
ReleaseMutex (datamutex);=0A=
return -1;=0A=
}=0A=
t =3D=0A=
SignalObjectAndWait (datamutex, readreadyevent,=0A=
INFINITE, FALSE);=0A=
if (t =3D=3D WAIT_OBJECT_0)=0A=
{=0A=
// system_printf (" // a read has occured rv %d lasterr =
%d\n", t,=0A=
// GetLastError ());=0A=
}=0A=
else if (t =3D=3D WAIT_ABANDONED)=0A=
{=0A=
system_printf ("********* wait timed out! | !?!\n");=0A=
}=0A=
else if (t =3D=3D WAIT_FAILED)=0A=
{=0A=
system_printf ("**********wait failed rv - %d lasterr %d\n",=0A=
t, GetLastError ());=0A=
}=0A=
else=0A=
{=0A=
system_printf=0A=
("************unexpected return value - %d lasterr %d\n",=0A=
t, GetLastError ());=0A=
}=0A=
t =3D WaitForSingleObject (datamutex, INFINITE);=0A=
if (t !=3D WAIT_OBJECT_0)=0A=
{=0A=
system_printf=0A=
("**************/* abandoned mutex - bad exit on the pipe...?? %d =
%d \n",=0A=
t, GetLastError ());=0A=
}=0A=
}=0A=
syscall_printf ("fhandler_fifo::write no data in the pipe.\n");=0A=
if (guts->pipeactive > 1)=0A=
{=0A=
// system_printf=0A=
// (" ****but the last reader has quit and the pipe has =
been closed\n");=0A=
ReleaseMutex (datamutex);=0A=
// system_printf (" released the datamutex, rv %d, =
getlasterror %d\n", t,=0A=
// GetLastError ());=0A=
ReleaseMutex (writingmutex);=0A=
set_errno( EPIPE);=0A=
return -1;=0A=
}=0A=
syscall_printf=0A=
("fhandler_fifo::write there are either readers waiting, or this is =
the first write. \n");=0A=
// send up to 1 Mb of data. - FIXME: return an error on nonblocking =
writes of more than 1 Mb=0A=
=0A=
// system_printf ("writing\n");=0A=
current_length =3D len - current_offset;=0A=
if (current_length > 0x00100000)=0A=
current_length =3D 0x00100000;=0A=
memcpy (filedata, (char *) buf + current_offset, current_length);=0A=
guts->data_offset =3D 0;=0A=
guts->data_length =3D current_length;=0A=
current_offset +=3D current_length;=0A=
current_length =3D 0;=0A=
if (current_offset =3D=3D len)=0A=
guts->eow =3D 1;=0A=
else=0A=
guts->eow =3D 0;=0A=
=0A=
syscall_printf=0A=
("fhandler_fifo::write data written, telling any current reader, =
and waiting for a read to occur\n");=0A=
// for non blocking, don't wait for them to get the data=0A=
if (!(get_flags() & O_NONBLOCK))=0A=
{=0A=
t =3D ReleaseMutex (datamutex);=0A=
// system_printf (" released datamutex, rv %d, getlasterror %d\n", t,=0A=
// GetLastError ());=0A=
t =3D=0A=
SignalObjectAndWait (writedoneevent, readreadyevent, INFINITE, =
FALSE);=0A=
// system_printf (" we have the datamutex\n");=0A=
if (t !=3D WAIT_OBJECT_0)=0A=
{=0A=
system_printf ("error waiting on readreadyevent\n");=0A=
}=0A=
t =3D WaitForSingleObject (datamutex, INFINITE);=0A=
if (t !=3D WAIT_OBJECT_0)=0A=
{=0A=
system_printf=0A=
("**************/* abandoned mutex - bad exit on the =
pipe...?? %d %d \n",=0A=
t, GetLastError ());=0A=
} =0A=
}=0A=
else =0A=
{=0A=
syscall_printf("skippedwaiting for read confirmationdue to =
O_NONBLOCK\n");=0A=
PulseEvent(writedoneevent);=0A=
}=0A=
}=0A=
t =3D ReleaseMutex (datamutex);=0A=
system_printf (" released the datamutex, rv %d, getlasterror =
%d\n", t,=0A=
GetLastError ());=0A=
system_printf ("releasing write mutex\n");=0A=
ReleaseMutex (writingmutex);=0A=
return current_offset;=0A=
}=0A=
else if (t =3D=3D WAIT_ABANDONED_0)=0A=
{=0A=
system_printf ("**** mutex was abandoned. \n");=0A=
ReleaseMutex (writingmutex);=0A=
// return fifowrite (data, buf, len);=0A=
}=0A=
else=0A=
{=0A=
system_printf ("*******/* we don't timeout */ rv=3D%d err=3D =
%d\n", t,=0A=
GetLastError ());=0A=
return 0;=0A=
}=0A=
=0A=
=0A=
return 0;=0A=
}=0A=
=0A=
=0A=
=0A=
int=0A=
fhandler_fifo::read (void *ptr, size_t len)=0A=
{=0A=
unsigned int t;=0A=
size_t current_length, current_offset=3D0;=0A=
if (!filemap)=0A=
{=0A=
set_errno(EBADF);=0A=
return -1;=0A=
}=0A=
if (guts->pipeactive > 1)=0A=
return 0;=0A=
=0A=
system_printf("reading a maximum of %d bytes, nonblocking =3D =
%d\n",len, get_flags() & O_NONBLOCK);=0A=
=0A=
// system_printf (" /* wait for the read mutex */\n");=0A=
t =3D WaitForSingleObject (readmutex, // handle to object=0A=
INFINITE // time-out interval=0A=
);=0A=
#if 0=0A=
if (guts->pipeactive > 1)=0A=
{=0A=
system_printf ("// the pipe has been closed\n");=0A=
system_printf (" // current pipe status. ml=3D%d dl=3D%d, =
eow=3D%d\n",=0A=
len, guts->data_length, guts->eow);=0A=
//seterno EPIPE;=0A=
ReleaseMutex (readmutex);=0A=
return 0;=0A=
}=0A=
#endif=0A=
if (t =3D=3D WAIT_OBJECT_0)=0A=
{=0A=
// system_printf ("got the read mutex %d\n", t);=0A=
current_length =3D 0;=0A=
current_offset =3D 0;=0A=
t =3D WaitForSingleObject (datamutex, INFINITE);=0A=
/* system_printf (" // got the data mutex. co=3D%d ml=3D%d dl=3D%d, =
eow=3D%d\n",=0A=
current_offset, len, guts->data_length,=0A=
guts->eow); */=0A=
while (current_offset < len=0A=
&& !((guts->eow) && guts->data_length =3D=3D 0))=0A=
{=0A=
// system_printf (" is there data waiting?");=0A=
while (!guts->data_length)=0A=
{=0A=
// system_printf ("..no..");=0A=
// there is no data in the pipe=0A=
if (get_flags() & O_NONBLOCK)=0A=
{=0A=
set_errno(EAGAIN);=0A=
system_printf ("NO data, not blocking\n");=0A=
ReleaseMutex (datamutex);=0A=
ReleaseMutex (readmutex);=0A=
return -1;=0A=
}=0A=
// is the pipe open?=0A=
if (guts->pipeactive > 1)=0A=
{=0A=
system_printf ("amd the pipe has been closed\n");=0A=
/* Note: the first writer blocks, so we _know_ that there was a writer.=0A=
* EPIPE is not generated here - just EOF=0A=
*/=0A=
ReleaseMutex (datamutex);=0A=
ReleaseMutex (readmutex);=0A=
return current_offset;=0A=
}=0A=
t =3D=0A=
SignalObjectAndWait (datamutex, writedoneevent,=0A=
INFINITE, FALSE);=0A=
// a write has occured=0A=
t =3D WaitForSingleObject (datamutex, INFINITE);=0A=
if (t !=3D WAIT_OBJECT_0)=0A=
{=0A=
system_printf=0A=
("Error obtaining mutex - possibly an abandoned mutex - bad exit =
on the pipe... */\n");=0A=
}=0A=
}=0A=
=0A=
// system_printf ("..yes %d bytes of data waiting\n",=0A=
// guts->data_length);=0A=
// system_printf ("reading");=0A=
current_length =3D guts->data_length;=0A=
if (current_length + current_offset > len)=0A=
current_length =3D len - current_offset;=0A=
=0A=
memcpy ((char *) ptr + current_offset,=0A=
(char *) filedata + guts->data_offset, current_length);=0A=
=0A=
current_offset +=3D current_length;=0A=
=0A=
if (!guts->pipeactive)=0A=
guts->pipeactive =3D 1; // an io has completed=0A=
// system_printf=0A=
// ("...signalling acceptance of %d bytes of data...\n",=0A=
// current_length);=0A=
guts->data_length -=3D current_length;=0A=
guts->data_offset +=3D current_length;=0A=
=0A=
PulseEvent (readreadyevent);=0A=
}=0A=
if (guts->data_length =3D=3D 0)=0A=
guts->eow =3D 0;=0A=
ReleaseMutex (datamutex);=0A=
=0A=
// read complete=0A=
ReleaseMutex (readmutex);=0A=
=0A=
=0A=
}=0A=
else if (t =3D=3D WAIT_ABANDONED)=0A=
{=0A=
system_printf ("abandoned mutex found \n");=0A=
}=0A=
else=0A=
{=0A=
system_printf=0A=
(" we don't have the mutex - should never ever happen (no timeout was =
set\n");=0A=
}=0A=
return current_offset;=0A=
}=0A=
=0A=
off_t=0A=
fhandler_fifo::lseek (off_t offset, int whence)=0A=
{=0A=
// for a pipe, you can't seek into the stream you can only rewind.=0A=
// FIXME: should this be fixing the pipe for _every_ read and writer? =
or just us.=0A=
if (!filemap)=0A=
{=0A=
set_errno(EBADF);=0A=
return -1;=0A=
}=0A=
WaitForSingleObject (datamutex, INFINITE);=0A=
guts->pipeactive=3D0;=0A=
ReleaseMutex(datamutex);=0A=
return 0;=0A=
=0A=
}=0A=
=0A=
void fhandler_fifo::fixup_after_fork (HANDLE parent)=0A=
{=0A=
system_printf("fhandler_fifo::fixup_after_fork name =3D '%s', =
filemapname=3D'%s'\n",get_name(),filemapname);=0A=
open(get_name(), get_flags(), 0);=0A=
}=0A=
------=_NextPart_000_0272_01C148F1.170E5CE0
Content-Type: application/octet-stream;
name="fifo.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="fifo.patch"
Index: cygwin/dtable.cc=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /cvs/src/src/winsup/cygwin/dtable.cc,v=0A=
retrieving revision 1.54=0A=
diff -u -p -r1.54 dtable.cc=0A=
--- dtable.cc 2001/09/24 21:50:44 1.54=0A=
+++ dtable.cc 2001/09/29 04:08:56=0A=
@@ -234,6 +234,7 @@ dtable::build_fhandler (int fd, const ch=0A=
DWORD devn;=0A=
fhandler_base *fh;=0A=
=0A=
+ /* This checks for "virtual" files */=0A=
if (!pc)=0A=
devn =3D get_device_number (name, unit);=0A=
else=0A=
@@ -251,7 +252,68 @@ dtable::build_fhandler (int fd, const ch=0A=
DCB dcb;=0A=
=0A=
if (handle =3D=3D NULL)=0A=
- devn =3D FH_DISK;=0A=
+ {=0A=
+ DWORD done;=0A=
+ char magic[3];=0A=
+ DWORD lsize, hsize;=0A=
+=0A=
+ debug_printf("checking for special files with path %s\n",name);=0A=
+ /* Check for special files. Special files have certain lengths to =
optimise when=0A=
+ * we do these checks. Currently the fixed length is 3 bytes.=0A=
+ * We do the checks before creating the fhandler object in case=0A=
+ * We need to alter our handling of the file =0A=
+ */=0A=
+=0A=
+ /* get the win32 path */=0A=
+ path_conv win32_path (name, PC_SYM_FOLLOW | PC_FULL);=0A=
+ if (win32_path.error)=0A=
+ {=0A=
+ system_printf("dtable::build_fhandler: Attempt to convert unix to =
win32 path failed with %s\n",name);=0A=
+ set_errno(win32_path.error);=0A=
+ /* Does any code use this function without testing for NULL? */=0A=
+ return NULL;=0A=
+ }=0A=
+=0A=
+ DWORD atts;=0A=
+ atts =3D win32_path.file_attributes ();=0A=
+ if (!(atts !=3D 0xffffffff && atts & FILE_ATTRIBUTE_DIRECTORY))=0A=
+ {=0A=
+=0A=
+ HANDLE h =3D CreateFile (win32_path.get_win32(), GENERIC_READ,=0A=
+ FILE_SHARE_READ,=0A=
+ NULL , OPEN_EXISTING,=0A=
+ FILE_ATTRIBUTE_NORMAL,0);=0A=
+=0A=
+ if (h !=3D INVALID_HANDLE_VALUE)=0A=
+ {=0A=
+ lsize =3D GetFileSize (h , &hsize);=0A=
+ if (lsize =3D=3D INVALID_FILE_SIZE && GetLastError () !=3D =
NO_ERROR)=0A=
+ {=0A=
+ /* FIXME: we've 'opened' the file but can't get file size?!? */;=0A=
+ system_printf("no file size!\n");=0A=
+ }=0A=
+ else=0A=
+ if (hsize=3D=3D0 && lsize=3D=3D3)=0A=
+ /* Candidate special file */=0A=
+ {=0A=
+ =0A=
+ /* FIXME should we use /etc/magic ? */=0A=
+ magic[0] =3D magic[1] =3D magic[2] =3D '\0';=0A=
+ ReadFile (h, magic, 3, &done, 0);=0A=
+ if ((magic[0] =3D=3D 'A' && magic[1] =3D=3D 'B') &&=0A=
+ (magic[2] =3D=3D 'C'))=0A=
+ {=0A=
+ /* FIFO */=0A=
+ devn =3D FH_FIFO;=0A=
+ debug_printf("FIFO magic found\n");=0A=
+ }=0A=
+ }/* file size 3 */=0A=
+ CloseHandle(h);=0A=
+=0A=
+ } /* not a valid file - probably a non-existant file */=0A=
+ } /* not a directory */=0A=
+ if (devn=3D=3DFH_BAD) devn =3D FH_DISK ;=0A=
+ } /* NULL handle */=0A=
else if (GetNumberOfConsoleInputEvents (handle, (DWORD *) &cinfo))=0A=
devn =3D FH_CONIN;=0A=
else if (GetConsoleScreenBufferInfo (handle, &cinfo))=0A=
@@ -336,6 +398,9 @@ dtable::build_fhandler (int fd, DWORD de=0A=
break;=0A=
case FH_CLIPBOARD:=0A=
fh =3D new (buf) fhandler_dev_clipboard (name);=0A=
+ break;=0A=
+ case FH_FIFO:=0A=
+ fh =3D new (buf) fhandler_fifo (NULL);=0A=
break;=0A=
case FH_OSS_DSP:=0A=
fh =3D new (buf) fhandler_dev_dsp (name);=0A=
Index: cygwin/fhandler.h=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /cvs/src/src/winsup/cygwin/fhandler.h,v=0A=
retrieving revision 1.83=0A=
diff -u -p -r1.83 fhandler.h=0A=
--- fhandler.h 2001/09/24 21:50:44 1.83=0A=
+++ fhandler.h 2001/09/29 04:08:57=0A=
@@ -25,6 +25,7 @@ details. */=0A=
fhandler_dev_zero Faked=0A=
=0A=
fhandler_dev_raw (fhandler_raw.cc)=0A=
+ fhandler_fifo (fhandler_fifo.cc)=0A=
fhandler_dev_floppy (fhandler_floppy.cc)=0A=
fhandler_dev_tape (fhandler_tape.cc)=0A=
=0A=
@@ -67,6 +68,7 @@ enum=0A=
* EOF, zero filling if so. */=0A=
FH_NOFRNAME =3D 0x00800000, /* Set if shouldn't free unix_path_name =
and=0A=
windows_path_name_ on destruction. */=0A=
+// FH_FIFO =3D 0x08000000, /* File is FIFO */=0A=
FH_NOEINTR =3D 0x01000000, /* Set if I/O should be uninterruptible. */=0A=
FH_FFIXUP =3D 0x02000000, /* Set if need to fixup after fork. */=0A=
FH_LOCAL =3D 0x04000000, /* File is unix domain socket */=0A=
@@ -104,9 +106,10 @@ enum=0A=
FH_RANDOM =3D 0x00000015, /* is a random device */=0A=
FH_MEM =3D 0x00000016, /* is a mem device */=0A=
FH_CLIPBOARD =3D 0x00000017, /* is a clipbaord device */=0A=
- FH_OSS_DSP =3D 0x00000018, /* is a dsp audio device */=0A=
+ FH_OSS_DSP =3D 0x00000018, /* is a dsp audio device */=0A=
+ FH_FIFO =3D 0x00000019, /* is a fifo special file */=0A=
=0A=
- FH_NDEV =3D 0x00000019, /* Maximum number of devices */=0A=
+ FH_NDEV =3D 0x0000001a, /* Maximum number of devices */=0A=
FH_DEVMASK =3D 0x00000fff, /* devices live here */=0A=
FH_BAD =3D 0xffffffff=0A=
};=0A=
@@ -498,6 +501,73 @@ public:=0A=
=0A=
void fixup_after_fork (HANDLE);=0A=
void fixup_after_exec (HANDLE);=0A=
+};=0A=
+=0A=
+class fifoshared=0A=
+{=0A=
+ public:=0A=
+ size_t data_offset;=0A=
+ unsigned int readers, writers;=0A=
+ /*set to 1 when the writer has written the last of it's buffer */=0A=
+ unsigned char eow; =0A=
+ size_t buffer_length;=0A=
+ size_t buffer_offset;=0A=
+ size_t data_length;=0A=
+ unsigned int pipeactive;=0A=
+};=0A=
+=0A=
+class fhandler_fifo: public fhandler_base=0A=
+{=0A=
+private:=0A=
+ int is_open;=0A=
+ int reader, writer;=0A=
+=0A=
+ HANDLE filemap;=0A=
+ HANDLE readreadyevent;=0A=
+ HANDLE writingmutex;=0A=
+ HANDLE writedoneevent;=0A=
+ HANDLE readmutex;=0A=
+ HANDLE datamutex;=0A=
+ void *filedata;=0A=
+ unsigned int fifoaccess;=0A=
+ /* this may mean that multiple fifos at the max path length with =
similar prefixes =0A=
+ * collide. WIN32 limits us here, so the answer is don't do that! =
aka. Tough. */=0A=
+ char filemapname[MAX_PATH];=0A=
+ char rrname[MAX_PATH];=0A=
+ char rmname[MAX_PATH];=0A=
+ char wmname[MAX_PATH];=0A=
+ char wdname[MAX_PATH];=0A=
+ char rsname[MAX_PATH];=0A=
+ char wsname[MAX_PATH];=0A=
+ char dmname[MAX_PATH];=0A=
+ class fifoshared *guts;=0A=
+=0A=
+public:=0A=
+ fhandler_fifo (const char *name);=0A=
+=0A=
+ int open (const char *path, int flags, mode_t mode =3D 0);=0A=
+ int open (path_conv& real_path, int flags, mode_t mode);=0A=
+ int dup (fhandler_base *child);=0A=
+ off_t lseek (off_t offset, int whence);=0A=
+ int close ();=0A=
+=0A=
+ virtual int read (void *ptr, size_t len);=0A=
+ virtual int write (const void *ptr, size_t len);=0A=
+=0A=
+// virtual void fixup_before_fork_exec (DWORD);=0A=
+ void fixup_after_fork (HANDLE);=0A=
+ void fixup_after_exec (HANDLE parent) { fixup_after_fork (parent); }=0A=
+=0A=
+ // I need the fixup_after_fork stuff=0A=
+=0A=
+// int lock (int, struct flock *);=0A=
+// int fstat (struct stat *buf);=0A=
+=0A=
+// HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, =
off_t off);=0A=
+// int munmap (HANDLE h, caddr_t addr, size_t len);=0A=
+// int msync (HANDLE h, caddr_t addr, size_t len, int flags);=0A=
+// BOOL fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset,=0A=
+// DWORD size, void *address);=0A=
};=0A=
=0A=
class fhandler_dev_floppy: public fhandler_dev_raw=0A=
Index: cygwin/syscalls.cc=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v=0A=
retrieving revision 1.149=0A=
diff -u -p -r1.149 syscalls.cc=0A=
--- syscalls.cc 2001/09/24 21:50:44 1.149=0A=
+++ syscalls.cc 2001/09/29 04:09:01=0A=
@@ -2008,6 +2009,40 @@ regfree ()=0A=
return 0;=0A=
}=0A=
=0A=
+extern "C" int =0A=
+mkfifo ( const char *pathname, mode_t mode )=0A=
+{=0A=
+ /* overview: create a regular file at the location given.=0A=
+ then write a magic number to it marking it as a FIFO */=0A=
+ // FIXME: don't overwrite an existing file=0A=
+ FILE *tempfile;=0A=
+ // FIXME: check for valid pathnames=0A=
+ if ((tempfile=3Dfopen(pathname,"r"))!=3DNULL)=0A=
+ {=0A=
+ /* the file already exists */=0A=
+ syscall_printf("mkfifo: Attempt to create a fifo over an existing =
file detected\n");=0A=
+ fclose(tempfile);=0A=
+ set_errno(EEXIST);=0A=
+ return -1;=0A=
+ }=0A=
+ if ((tempfile=3Dfopen(pathname,"w"))=3D=3DNULL)=0A=
+ {=0A=
+ system_printf("error opening %s\n",pathname);=0A=
+ set_errno (EIO);=0A=
+ return -1;=0A=
+ }=0A=
+ if (fprintf(tempfile,"ABC")!=3D3)=0A=
+ {=0A=
+ system_printf("error writing to %s\n",pathname);=0A=
+ fclose(tempfile);=0A=
+ set_errno (EIO);=0A=
+ return -1;=0A=
+ }=0A=
+ fclose(tempfile);=0A=
+ return 0;=0A=
+}=0A=
+=0A=
+=0A=
/* mknod was the call to create directories before the introduction=0A=
of mkdir in 4.2BSD and SVR3. Use of mknod required superuser privs=0A=
so the mkdir command had to be setuid root.=0A=
@@ -2017,13 +2052,11 @@ regfree ()=0A=
extern "C" int=0A=
mknod (const char *_path, mode_t mode, dev_t dev)=0A=
{=0A=
- set_errno (ENOSYS);=0A=
- return -1;=0A=
-}=0A=
-=0A=
-extern "C" int=0A=
-mkfifo (const char *_path, mode_t mode)=0A=
-{=0A=
+ if (mode & S_IFIFO)=0A=
+ {=0A=
+ return mkfifo (_path, mode | (!S_IFIFO));=0A=
+ }=0A=
+ else=0A=
set_errno (ENOSYS);=0A=
return -1;=0A=
}=0A=
------=_NextPart_000_0272_01C148F1.170E5CE0
Content-Type: text/plain; charset=us-ascii
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Bug reporting: http://cygwin.com/bugs.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
------=_NextPart_000_0272_01C148F1.170E5CE0--
- Raw text -