-/* MinGW version of named pipe API */
-#ifdef MINGW
-/**
- * Creates a named pipe/FIFO and opens it
- *
- * @param fn pointer to the name of the named pipe or to NULL
- * @param flags open flags
- * @param perm access permissions
- * @return pipe handle on success, NULL on error
- */
-static struct GNUNET_DISK_FileHandle *
-npipe_create (char **fn, enum GNUNET_DISK_OpenFlags flags,
- enum GNUNET_DISK_AccessPermissions perm)
-{
- struct GNUNET_DISK_FileHandle *ret;
- HANDLE h = NULL;
- DWORD openMode;
- char *name;
-
- openMode = 0;
- if (flags & GNUNET_DISK_OPEN_READWRITE)
- openMode = PIPE_ACCESS_DUPLEX;
- else if (flags & GNUNET_DISK_OPEN_READ)
- openMode = PIPE_ACCESS_INBOUND;
- else if (flags & GNUNET_DISK_OPEN_WRITE)
- openMode = PIPE_ACCESS_OUTBOUND;
- if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)
- openMode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
-
- while (h == NULL)
- {
- DWORD error_code;
-
- name = NULL;
- if (*fn != NULL)
- {
- GNUNET_asprintf (&name, "\\\\.\\pipe\\%.246s", fn);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Trying to create an instance of named pipe `%s'\n", name);
- /* 1) This might work just fine with UTF-8 strings as it is.
- * 2) This is only used by GNUnet itself, and only with latin names.
- */
- h = CreateNamedPipe (name, openMode | FILE_FLAG_OVERLAPPED,
- PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0,
- NULL);
- }
- else
- {
- GNUNET_asprintf (fn, "\\\\.\\pipe\\gnunet-%llu",
- GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
- UINT64_MAX));
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying to create unique named pipe `%s'\n",
- *fn);
- h = CreateNamedPipe (*fn,
- openMode | FILE_FLAG_OVERLAPPED |
- FILE_FLAG_FIRST_PIPE_INSTANCE,
- PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0,
- NULL);
- }
- error_code = GetLastError ();
- if (name)
- GNUNET_free (name);
- /* don't re-set name to NULL yet */
- if (h == INVALID_HANDLE_VALUE)
- {
- SetErrnoFromWinError (error_code);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Pipe creation have failed because of %d, errno is %d\n", error_code,
- errno);
- if (name == NULL)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Pipe was to be unique, considering re-creation\n");
- GNUNET_free (*fn);
- *fn = NULL;
- if (error_code != ERROR_ACCESS_DENIED && error_code != ERROR_PIPE_BUSY)
- {
- return NULL;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Pipe name was not unique, trying again\n");
- h = NULL;
- }
- else
- return NULL;
- }
- }
- errno = 0;
-
- ret = GNUNET_malloc (sizeof (*ret));
- ret->h = h;
- ret->type = GNUNET_PIPE;
- ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED));
- ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED));
- ret->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
- ret->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
- return ret;
-}
-
-
-/**
- * Opens already existing named pipe/FIFO
- *
- * @param fn name of an existing named pipe
- * @param flags open flags
- * @return pipe handle on success, NULL on error
- */
-static struct GNUNET_DISK_FileHandle *
-npipe_open (const char *fn, enum GNUNET_DISK_OpenFlags flags)
-{
- struct GNUNET_DISK_FileHandle *ret;
- HANDLE h;
- DWORD openMode;
-
- openMode = 0;
- if (flags & GNUNET_DISK_OPEN_READWRITE)
- openMode = GENERIC_WRITE | GENERIC_READ;
- else if (flags & GNUNET_DISK_OPEN_READ)
- openMode = GENERIC_READ;
- else if (flags & GNUNET_DISK_OPEN_WRITE)
- openMode = GENERIC_WRITE;
-
- h = CreateFile (fn, openMode, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED | FILE_READ_ATTRIBUTES, NULL);
- if (h == INVALID_HANDLE_VALUE)
- {
- SetErrnoFromWinError (GetLastError ());
- return NULL;
- }
-
- ret = GNUNET_malloc (sizeof (*ret));
- ret->h = h;
- ret->type = GNUNET_PIPE;
- ret->oOverlapRead = GNUNET_malloc (sizeof (OVERLAPPED));
- ret->oOverlapWrite = GNUNET_malloc (sizeof (OVERLAPPED));
- ret->oOverlapRead->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
- ret->oOverlapWrite->hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
-
- return ret;
-}
-
-#else
-/* UNIX version of named-pipe API */
-
-/**
- * Clean up a named pipe and the directory it was placed in.
- *
- * @param fn name of the pipe
- */
-static void
-cleanup_npipe (const char *fn)
-{
- char *dn;
- char *dp;
-
- if (0 != unlink (fn))
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn);
- dn = GNUNET_strdup (fn);
- dp = dirname (dn);
- if (0 != rmdir (dp))
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "rmdir", dp);
- GNUNET_free (dn);
-}
-
-
-/**
- * Setup a named pipe.
- *
- * @param fn where to store the name of the new pipe,
- * if *fn is non-null, the name of the pipe to setup
- * @return GNUNET_OK on success
- */
-static int
-npipe_setup (char **fn)
-{
- if (NULL == *fn)
- {
- /* FIXME: hardwired '/tmp' path... is bad */
- char dir[] = "/tmp/gnunet-pipe-XXXXXX";
-
- if (NULL == mkdtemp (dir))
- {
- LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "mkdtemp");
- return GNUNET_SYSERR;
- }
- GNUNET_asprintf (fn, "%s/child-control", dir);
- }
- if (-1 == mkfifo (*fn, S_IRUSR | S_IWUSR))
- return GNUNET_SYSERR;
- return GNUNET_OK;
-}
-
-
-/**
- * Open an existing named pipe.
- *
- * @param fn name of the file
- * @param flags flags to use
- * @return NULL on error
- */
-static struct GNUNET_DISK_FileHandle *
-npipe_open (const char *fn,
- enum GNUNET_DISK_OpenFlags flags)
-{
- struct GNUNET_DISK_FileHandle *ret;
- int fd;
- struct timespec req;
- int i;
-
- /* 200 * 5ms = 1s at most */
- for (i=0;i<200;i++)
- {
- fd = open (fn, O_NONBLOCK | ((flags == GNUNET_DISK_OPEN_READ) ? O_RDONLY : O_WRONLY));
- if ( (-1 != fd) || (9 == i) || (flags == GNUNET_DISK_OPEN_READ))
- break;
- /* as this is for killing a child process via pipe and it is conceivable that
- the child process simply didn't finish starting yet, we do some sleeping
- (which is obviously usually not allowed). We can't select on the FD as
- 'open' fails, and we probably shouldn't just "ignore" the error, so wait
- and retry a few times is likely the best method; our process API doesn't
- support continuations, so we need to sleep directly... */
- req.tv_sec = 0;
- req.tv_nsec = 5000000; /* 5ms */
- (void) nanosleep (&req, NULL);
- }
- if (-1 == fd)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- (flags == GNUNET_DISK_OPEN_READ)
- ? _("Failed to open named pipe `%s' for reading: %s\n")
- : _("Failed to open named pipe `%s' for writing: %s\n"),
- fn,
- STRERROR (errno));
- return NULL;
- }
- ret = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle));
- ret->fd = fd;
- return ret;
-}
-#endif
-
-