From 4775f33e1c0b976d79bfe4918cafea88b5376592 Mon Sep 17 00:00:00 2001 From: Nils Durner Date: Mon, 22 Nov 2010 20:15:29 +0000 Subject: [PATCH] named pipes --- src/include/gnunet_disk_lib.h | 17 +++++ src/util/disk.c | 133 +++++++++++++++++++++++++++++----- src/util/disk.h | 9 ++- src/util/network.c | 56 ++++++++------ 4 files changed, 174 insertions(+), 41 deletions(-) diff --git a/src/include/gnunet_disk_lib.h b/src/include/gnunet_disk_lib.h index 6eb666049..a59d10ed0 100644 --- a/src/include/gnunet_disk_lib.h +++ b/src/include/gnunet_disk_lib.h @@ -642,6 +642,23 @@ int GNUNET_DISK_file_unmap (struct GNUNET_DISK_MapHandle *h); */ int GNUNET_DISK_file_sync (const struct GNUNET_DISK_FileHandle *h); +/** + * Creates a named pipe/FIFO + * @param fn name of the named pipe + * @param flags open flags + * @param perm access permissions + * @return pipe handle on success, NULL on error + */ +struct GNUNET_DISK_FileHandle *GNUNET_DISK_npipe_open (const char *fn, + enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm); + +/** + * Closes a named pipe/FIFO + * @param pipe named pipe + * @return GNUNET_OK on success, GNUNET_SYSERR otherwise + */ +int GNUNET_DISK_npipe_close (struct GNUNET_DISK_FileHandle *pipe); + #if 0 /* keep Emacsens' auto-indent happy */ { #endif diff --git a/src/util/disk.c b/src/util/disk.c index 307c4535b..c25782a42 100644 --- a/src/util/disk.c +++ b/src/util/disk.c @@ -101,6 +101,34 @@ struct GetFileSizeData }; +int translate_unix_perms(enum GNUNET_DISK_AccessPermissions perm) +{ + int mode; + + mode = 0; + if (perm & GNUNET_DISK_PERM_USER_READ) + mode |= S_IRUSR; + if (perm & GNUNET_DISK_PERM_USER_WRITE) + mode |= S_IWUSR; + if (perm & GNUNET_DISK_PERM_USER_EXEC) + mode |= S_IXUSR; + if (perm & GNUNET_DISK_PERM_GROUP_READ) + mode |= S_IRGRP; + if (perm & GNUNET_DISK_PERM_GROUP_WRITE) + mode |= S_IWGRP; + if (perm & GNUNET_DISK_PERM_GROUP_EXEC) + mode |= S_IXGRP; + if (perm & GNUNET_DISK_PERM_OTHER_READ) + mode |= S_IROTH; + if (perm & GNUNET_DISK_PERM_OTHER_WRITE) + mode |= S_IWOTH; + if (perm & GNUNET_DISK_PERM_OTHER_EXEC) + mode |= S_IXOTH; + + return mode; +} + + /** * Iterate over all files in the given directory and * accumulate their size. @@ -1259,24 +1287,7 @@ GNUNET_DISK_file_open (const char *fn, { (void) GNUNET_DISK_directory_create_for_file (expfn); oflags |= O_CREAT; - if (perm & GNUNET_DISK_PERM_USER_READ) - mode |= S_IRUSR; - if (perm & GNUNET_DISK_PERM_USER_WRITE) - mode |= S_IWUSR; - if (perm & GNUNET_DISK_PERM_USER_EXEC) - mode |= S_IXUSR; - if (perm & GNUNET_DISK_PERM_GROUP_READ) - mode |= S_IRGRP; - if (perm & GNUNET_DISK_PERM_GROUP_WRITE) - mode |= S_IWGRP; - if (perm & GNUNET_DISK_PERM_GROUP_EXEC) - mode |= S_IXGRP; - if (perm & GNUNET_DISK_PERM_OTHER_READ) - mode |= S_IROTH; - if (perm & GNUNET_DISK_PERM_OTHER_WRITE) - mode |= S_IWOTH; - if (perm & GNUNET_DISK_PERM_OTHER_EXEC) - mode |= S_IXOTH; + mode = translate_unix_perms(perm); } fd = open (expfn, oflags | O_LARGEFILE, mode); @@ -1347,6 +1358,7 @@ GNUNET_DISK_file_open (const char *fn, ret = GNUNET_malloc (sizeof (struct GNUNET_DISK_FileHandle)); #ifdef MINGW ret->h = h; + ret->type = GNUNET_DISK_FILE; #else ret->fd = fd; #endif @@ -1748,6 +1760,8 @@ GNUNET_DISK_pipe (int blocking, int inherit_read, int inherit_write) SetNamedPipeHandleState (p->fd[1]->h, &mode, NULL, NULL); /* this always fails on Windows 95, so we don't care about error handling */ } + p->fd[0]->type = GNUNET_PIPE; + p->fd[1]->type = GNUNET_PIPE; #endif return p; } @@ -1862,6 +1876,89 @@ GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p) } +/** + * Creates a named pipe/FIFO + * @param fn name of the named pipe + * @param flags open flags + * @param perm access permissions + * @return pipe handle on success, NULL on error + */ +struct GNUNET_DISK_FileHandle * +GNUNET_DISK_npipe_open (const char *fn, + enum GNUNET_DISK_OpenFlags flags, + enum GNUNET_DISK_AccessPermissions perm) +{ + struct GNUNET_DISK_FileHandle *ret; + +#ifdef MINGW + HANDLE h; + 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; + + GNUNET_asprintf(&name, "\\\\.\\pipe\\pipename\\%s", fn); + h = CreateNamedPipe (fn, openMode | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 2, 1, 1, 0, NULL); + GNUNET_free(name); + if (h == NULL) + { + SetErrnoFromWinError(GetLastError()); + return NULL; + } + + ret = GNUNET_malloc(sizeof(*ret)); + ret->h = h; + + return ret; +#else + int fd; + + if (mkfifo(fn, translate_unix_perms(perm)) == -1) + { + if (errno == EEXISTS && flags & GNUNET_DISK_OPEN_FAILIFEXISTS) + return NULL; + } + + flags ~= GNUNET_DISK_OPEN_FAILIFEXISTS; + return GNUNET_DISK_file_open(fn, flags, perm); +#endif +} + +/** + * Closes a named pipe/FIFO + * @param pipe named pipe + * @return GNUNET_OK on success, GNUNET_SYSERR otherwise + */ +int +GNUNET_DISK_npipe_close (struct GNUNET_DISK_FileHandle *pipe) +{ +#ifndef MINGW + return close(pipe->fd) == 0 ? GNUNET_OK : GNUNET_SYSERR; +#else + BOOL ret; + + ret = CloseHandle(pipe->h); + if (!ret) + { + SetErrnoFromWinError(GetLastError()); + return GNUNET_SYSERR; + } + else + return GNUNET_OK; +#endif +} + + /** * Get the handle to a particular pipe end * diff --git a/src/util/disk.h b/src/util/disk.h index 3d52b9ec8..093d70492 100644 --- a/src/util/disk.h +++ b/src/util/disk.h @@ -40,8 +40,13 @@ struct GNUNET_DISK_FileHandle * File handle under W32. */ HANDLE h; - -#else /* */ + + /** + * Type + */ + enum {GNUNET_DISK_FILE, GNUNET_PIPE} type; +#else + /** * File handle on other OSes. */ diff --git a/src/util/network.c b/src/util/network.c index 58d67ed19..452f28706 100644 --- a/src/util/network.c +++ b/src/util/network.c @@ -1137,28 +1137,38 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, GNUNET_CONTAINER_slist_next (i)) { - HANDLE h; + struct GNUNET_DISK_FileHandle *fh; DWORD dwBytes; - h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL); - if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL)) + fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL); + if (fh->type == GNUNET_PIPE) { - retcode = -1; - SetErrnoFromWinError (GetLastError ()); + if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) + { + retcode = -1; + SetErrnoFromWinError (GetLastError ()); -#if DEBUG_NETWORK - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "PeekNamedPipe"); + #if DEBUG_NETWORK + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "PeekNamedPipe"); -#endif - goto select_loop_end; - } - else if (dwBytes) + #endif + goto select_loop_end; + } + else if (dwBytes) + { + GNUNET_CONTAINER_slist_add (handles_read, + GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, + fh, sizeof (struct GNUNET_DISK_FileHandle)); + retcode++; + } + } + else { + /* Should we wait for more bytes to read here (in case of previous EOF)? */ GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, - &h, sizeof (HANDLE)); - retcode++; + fh, sizeof (struct GNUNET_DISK_FileHandle)); } } GNUNET_CONTAINER_slist_iter_destroy (i); @@ -1174,16 +1184,20 @@ GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, GNUNET_CONTAINER_slist_next (i)) { - HANDLE h; + struct GNUNET_DISK_FileHandle *fh; DWORD dwBytes; - h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL); - if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL)) + fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL); + if (fh->type == GNUNET_PIPE) { - GNUNET_CONTAINER_slist_add (handles_except, - GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, - &h, sizeof (HANDLE)); - retcode++; + if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL)) + + { + GNUNET_CONTAINER_slist_add (handles_except, + GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, + fh, sizeof (struct GNUNET_DISK_FileHandle)); + retcode++; + } } } GNUNET_CONTAINER_slist_iter_destroy (i); -- 2.25.1