diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 06:23:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 06:23:09 +0000 |
commit | 30d479c28c831a0d4f1fdb54a9e346b0fc176be1 (patch) | |
tree | aa35d7414ce9f1326abf6f723f6dfa5b0aa08b1d /file_io/netware | |
parent | Initial commit. (diff) | |
download | apr-30d479c28c831a0d4f1fdb54a9e346b0fc176be1.tar.xz apr-30d479c28c831a0d4f1fdb54a9e346b0fc176be1.zip |
Adding upstream version 1.7.2.upstream/1.7.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | file_io/netware/filepath.c | 4 | ||||
-rw-r--r-- | file_io/netware/filestat.c | 417 | ||||
-rw-r--r-- | file_io/netware/filesys.c | 106 | ||||
-rw-r--r-- | file_io/netware/flock.c | 39 | ||||
-rw-r--r-- | file_io/netware/mktemp.c | 64 | ||||
-rw-r--r-- | file_io/netware/pipe.c | 239 |
6 files changed, 869 insertions, 0 deletions
diff --git a/file_io/netware/filepath.c b/file_io/netware/filepath.c new file mode 100644 index 0000000..e4bb3f3 --- /dev/null +++ b/file_io/netware/filepath.c @@ -0,0 +1,4 @@ +/* NetWare & Win32 have much in common with regards to file names (both are + * DOSish) so it makes sense to share some code + */ +#include "../win32/filepath.c" diff --git a/file_io/netware/filestat.c b/file_io/netware/filestat.c new file mode 100644 index 0000000..6627951 --- /dev/null +++ b/file_io/netware/filestat.c @@ -0,0 +1,417 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "fsio.h" +#include "nks/dirio.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_errno.h" +#include "apr_hash.h" +#include "apr_thread_rwlock.h" + +#ifdef HAVE_UTIME_H +#include <utime.h> +#endif + +#define APR_HAS_PSA + +static apr_filetype_e filetype_from_mode(mode_t mode) +{ + apr_filetype_e type = APR_NOFILE; + + if (S_ISREG(mode)) + type = APR_REG; + else if (S_ISDIR(mode)) + type = APR_DIR; + else if (S_ISCHR(mode)) + type = APR_CHR; + else if (S_ISBLK(mode)) + type = APR_BLK; + else if (S_ISFIFO(mode)) + type = APR_PIPE; + else if (S_ISLNK(mode)) + type = APR_LNK; + else if (S_ISSOCK(mode)) + type = APR_SOCK; + else + type = APR_UNKFILE; + return type; +} + +static void fill_out_finfo(apr_finfo_t *finfo, struct stat *info, + apr_int32_t wanted) +{ + finfo->valid = APR_FINFO_MIN | APR_FINFO_IDENT | APR_FINFO_NLINK + | APR_FINFO_OWNER | APR_FINFO_PROT; + + finfo->protection = apr_unix_mode2perms(info->st_mode); + finfo->filetype = filetype_from_mode(info->st_mode); + finfo->user = info->st_uid; + finfo->group = info->st_gid; + finfo->size = info->st_size; + finfo->inode = info->st_ino; + finfo->device = info->st_dev; + finfo->nlink = info->st_nlink; + + apr_time_ansi_put(&finfo->atime, info->st_atime.tv_sec); + apr_time_ansi_put(&finfo->mtime, info->st_mtime.tv_sec); + apr_time_ansi_put(&finfo->ctime, info->st_ctime.tv_sec); + +#ifdef HAVE_STRUCT_STAT_ST_BLOCKS +#ifdef DEV_BSIZE + finfo->csize = (apr_off_t)info->st_blocks * (apr_off_t)DEV_BSIZE; +#else + finfo->csize = (apr_off_t)info->st_blocks * (apr_off_t)512; +#endif + finfo->valid |= APR_FINFO_CSIZE; +#endif +} + +apr_status_t apr_file_info_get_locked(apr_finfo_t *finfo, apr_int32_t wanted, + apr_file_t *thefile) +{ + struct_stat info; + + if (thefile->buffered) { + apr_status_t rv = apr_file_flush_locked(thefile); + if (rv != APR_SUCCESS) + return rv; + } + + if (fstat(thefile->filedes, &info) == 0) { + finfo->pool = thefile->pool; + finfo->fname = thefile->fname; + fill_out_finfo(finfo, &info, wanted); + return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS; + } + else { + return errno; + } +} + +APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, + apr_int32_t wanted, + apr_file_t *thefile) +{ + struct stat info; + + if (thefile->buffered) { + /* XXX: flush here is not mutex protected */ + apr_status_t rv = apr_file_flush(thefile); + if (rv != APR_SUCCESS) + return rv; + } + + if (fstat(thefile->filedes, &info) == 0) { + finfo->pool = thefile->pool; + finfo->fname = thefile->fname; + fill_out_finfo(finfo, &info, wanted); + return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS; + } + else { + return errno; + } +} + +APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, + apr_fileperms_t perms) +{ + mode_t mode = apr_unix_perms2mode(perms); + + if (chmod(fname, mode) == -1) + return errno; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname, + apr_fileattrs_t attributes, + apr_fileattrs_t attr_mask, + apr_pool_t *pool) +{ + apr_status_t status; + apr_finfo_t finfo; + + /* Don't do anything if we can't handle the requested attributes */ + if (!(attr_mask & (APR_FILE_ATTR_READONLY + | APR_FILE_ATTR_EXECUTABLE))) + return APR_SUCCESS; + + status = apr_stat(&finfo, fname, APR_FINFO_PROT, pool); + if (status) + return status; + + /* ### TODO: should added bits be umask'd? */ + if (attr_mask & APR_FILE_ATTR_READONLY) + { + if (attributes & APR_FILE_ATTR_READONLY) + { + finfo.protection &= ~APR_UWRITE; + finfo.protection &= ~APR_GWRITE; + finfo.protection &= ~APR_WWRITE; + } + else + { + /* ### umask this! */ + finfo.protection |= APR_UWRITE; + finfo.protection |= APR_GWRITE; + finfo.protection |= APR_WWRITE; + } + } + + if (attr_mask & APR_FILE_ATTR_EXECUTABLE) + { + if (attributes & APR_FILE_ATTR_EXECUTABLE) + { + /* ### umask this! */ + finfo.protection |= APR_UEXECUTE; + finfo.protection |= APR_GEXECUTE; + finfo.protection |= APR_WEXECUTE; + } + else + { + finfo.protection &= ~APR_UEXECUTE; + finfo.protection &= ~APR_GEXECUTE; + finfo.protection &= ~APR_WEXECUTE; + } + } + + return apr_file_perms_set(fname, finfo.protection); +} + +#ifndef APR_HAS_PSA +static apr_status_t stat_cache_cleanup(void *data) +{ + apr_pool_t *p = (apr_pool_t *)getGlobalPool(); + apr_hash_index_t *hi; + apr_hash_t *statCache = (apr_hash_t*)data; + char *key; + apr_ssize_t keylen; + NXPathCtx_t pathctx; + + for (hi = apr_hash_first(p, statCache); hi; hi = apr_hash_next(hi)) { + apr_hash_this(hi, (const void**)&key, &keylen, (void**)&pathctx); + + if (pathctx) { + NXFreePathContext(pathctx); + } + } + + return APR_SUCCESS; +} + +int cstat (NXPathCtx_t ctx, char *path, struct stat *buf, unsigned long requestmap, apr_pool_t *p) +{ + apr_pool_t *gPool = (apr_pool_t *)getGlobalPool(); + apr_hash_t *statCache = NULL; + apr_thread_rwlock_t *rwlock = NULL; + + NXPathCtx_t pathctx = 0; + char *ptr = NULL, *tr; + int len = 0, x; + char *ppath; + char *pinfo; + + if (ctx == 1) { + + /* If there isn't a global pool then just stat the file + and return */ + if (!gPool) { + char poolname[50]; + + if (apr_pool_create(&gPool, NULL) != APR_SUCCESS) { + return getstat(ctx, path, buf, requestmap); + } + + setGlobalPool(gPool); + apr_pool_tag(gPool, apr_pstrdup(gPool, "cstat_mem_pool")); + + statCache = apr_hash_make(gPool); + apr_pool_userdata_set ((void*)statCache, "STAT_CACHE", stat_cache_cleanup, gPool); + + apr_thread_rwlock_create(&rwlock, gPool); + apr_pool_userdata_set ((void*)rwlock, "STAT_CACHE_LOCK", apr_pool_cleanup_null, gPool); + } + else { + apr_pool_userdata_get((void**)&statCache, "STAT_CACHE", gPool); + apr_pool_userdata_get((void**)&rwlock, "STAT_CACHE_LOCK", gPool); + } + + if (!gPool || !statCache || !rwlock) { + return getstat(ctx, path, buf, requestmap); + } + + for (x = 0,tr = path;*tr != '\0';tr++,x++) { + if (*tr == '\\' || *tr == '/') { + ptr = tr; + len = x; + } + if (*tr == ':') { + ptr = "\\"; + len = x; + } + } + + if (ptr) { + ppath = apr_pstrndup (p, path, len); + strlwr(ppath); + if (ptr[1] != '\0') { + ptr++; + } + /* If the path ended in a trailing slash then our result path + will be a single slash. To avoid stat'ing the root with a + slash, we need to make sure we stat the current directory + with a dot */ + if (((*ptr == '/') || (*ptr == '\\')) && (*(ptr+1) == '\0')) { + pinfo = apr_pstrdup (p, "."); + } + else { + pinfo = apr_pstrdup (p, ptr); + } + } + + /* If we have a statCache then try to pull the information + from the cache. Otherwise just stat the file and return.*/ + if (statCache) { + apr_thread_rwlock_rdlock(rwlock); + pathctx = (NXPathCtx_t) apr_hash_get(statCache, ppath, APR_HASH_KEY_STRING); + apr_thread_rwlock_unlock(rwlock); + if (pathctx) { + return getstat(pathctx, pinfo, buf, requestmap); + } + else { + int err; + + err = NXCreatePathContext(0, ppath, 0, NULL, &pathctx); + if (!err) { + apr_thread_rwlock_wrlock(rwlock); + apr_hash_set(statCache, apr_pstrdup(gPool,ppath) , APR_HASH_KEY_STRING, (void*)pathctx); + apr_thread_rwlock_unlock(rwlock); + return getstat(pathctx, pinfo, buf, requestmap); + } + } + } + } + return getstat(ctx, path, buf, requestmap); +} +#endif + +APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, + const char *fname, + apr_int32_t wanted, apr_pool_t *pool) +{ + struct stat info; + int srv; + NXPathCtx_t pathCtx = 0; + + getcwdpath(NULL, &pathCtx, CTX_ACTUAL_CWD); +#ifdef APR_HAS_PSA + srv = getstat(pathCtx, (char*)fname, &info, ST_STAT_BITS|ST_NAME_BIT); +#else + srv = cstat(pathCtx, (char*)fname, &info, ST_STAT_BITS|ST_NAME_BIT, pool); +#endif + errno = srv; + + if (srv == 0) { + finfo->pool = pool; + finfo->fname = fname; + fill_out_finfo(finfo, &info, wanted); + if (wanted & APR_FINFO_LINK) + wanted &= ~APR_FINFO_LINK; + if (wanted & APR_FINFO_NAME) { + finfo->name = apr_pstrdup(pool, info.st_name); + finfo->valid |= APR_FINFO_NAME; + } + return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS; + } + else { +#if !defined(ENOENT) || !defined(ENOTDIR) +#error ENOENT || ENOTDIR not defined; please see the +#error comments at this line in the source for a workaround. + /* + * If ENOENT || ENOTDIR is not defined in one of the your OS's + * include files, APR cannot report a good reason why the stat() + * of the file failed; there are cases where it can fail even though + * the file exists. This opens holes in Apache, for example, because + * it becomes possible for someone to get a directory listing of a + * directory even though there is an index (eg. index.html) file in + * it. If you do not have a problem with this, delete the above + * #error lines and start the compile again. If you need to do this, + * please submit a bug report to http://www.apache.org/bug_report.html + * letting us know that you needed to do this. Please be sure to + * include the operating system you are using. + */ + /* WARNING: All errors will be handled as not found + */ +#if !defined(ENOENT) + return APR_ENOENT; +#else + /* WARNING: All errors but not found will be handled as not directory + */ + if (errno != ENOENT) + return APR_ENOENT; + else + return errno; +#endif +#else /* All was defined well, report the usual: */ + return errno; +#endif + } +} + +APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname, + apr_time_t mtime, + apr_pool_t *pool) +{ + apr_status_t status; + apr_finfo_t finfo; + + status = apr_stat(&finfo, fname, APR_FINFO_ATIME, pool); + if (status) { + return status; + } + +#ifdef HAVE_UTIMES + { + struct timeval tvp[2]; + + tvp[0].tv_sec = apr_time_sec(finfo.atime); + tvp[0].tv_usec = apr_time_usec(finfo.atime); + tvp[1].tv_sec = apr_time_sec(mtime); + tvp[1].tv_usec = apr_time_usec(mtime); + + if (utimes(fname, tvp) == -1) { + return errno; + } + } +#elif defined(HAVE_UTIME) + { + struct utimbuf buf; + + buf.actime = (time_t) (finfo.atime / APR_USEC_PER_SEC); + buf.modtime = (time_t) (mtime / APR_USEC_PER_SEC); + + if (utime(fname, &buf) == -1) { + return errno; + } + } +#else + return APR_ENOTIMPL; +#endif + + return APR_SUCCESS; +} diff --git a/file_io/netware/filesys.c b/file_io/netware/filesys.c new file mode 100644 index 0000000..05c44ce --- /dev/null +++ b/file_io/netware/filesys.c @@ -0,0 +1,106 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_arch_file_io.h" +#include "apr_strings.h" + +apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p) +{ +/* See the Windows code to figure out what to do here. + It probably checks to make sure that the root exists + and case it correctly according to the file system. +*/ + *rootpath = apr_pstrdup(p, root); + return APR_SUCCESS; +} + +apr_status_t filepath_has_drive(const char *rootpath, int only, apr_pool_t *p) +{ + char *s; + + if (rootpath) { + s = strchr (rootpath, ':'); + if (only) + /* Test if the path only has a drive/volume and nothing else + */ + return (s && (s != rootpath) && !s[1]); + else + /* Test if the path includes a drive/volume + */ + return (s && (s != rootpath)); + } + return 0; +} + +apr_status_t filepath_compare_drive(const char *path1, const char *path2, apr_pool_t *p) +{ + char *s1, *s2; + + if (path1 && path2) { + s1 = strchr (path1, ':'); + s2 = strchr (path2, ':'); + + /* Make sure that they both have a drive/volume delimiter + and are the same size. Then see if they match. + */ + if (s1 && s2 && ((s1-path1) == (s2-path2))) { + return strnicmp (s1, s2, s1-path1); + } + } + return -1; +} + +APR_DECLARE(apr_status_t) apr_filepath_get(char **rootpath, apr_int32_t flags, + apr_pool_t *p) +{ + char path[APR_PATH_MAX]; + char *ptr; + + /* use getcwdpath to make sure that we get the volume name*/ + if (!getcwdpath(path, NULL, 0)) { + if (errno == ERANGE) + return APR_ENAMETOOLONG; + else + return errno; + } + /* Strip off the server name if there is one*/ + ptr = strpbrk(path, "\\/:"); + if (!ptr) { + return APR_ENOENT; + } + if (*ptr == ':') { + ptr = path; + } + *rootpath = apr_pstrdup(p, ptr); + if (!(flags & APR_FILEPATH_NATIVE)) { + for (ptr = *rootpath; *ptr; ++ptr) { + if (*ptr == '\\') + *ptr = '/'; + } + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_filepath_set(const char *rootpath, + apr_pool_t *p) +{ + if (chdir2(rootpath) != 0) + return errno; + return APR_SUCCESS; +} + + diff --git a/file_io/netware/flock.c b/file_io/netware/flock.c new file mode 100644 index 0000000..c083a0e --- /dev/null +++ b/file_io/netware/flock.c @@ -0,0 +1,39 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <nks/fsio.h> +#include "apr_arch_file_io.h" + + +apr_status_t apr_file_lock(apr_file_t *thefile, int type) +{ + int fc; + + fc = (type & APR_FLOCK_NONBLOCK) ? NX_RANGE_LOCK_TRYLOCK : NX_RANGE_LOCK_CHECK; + + if(NXFileRangeLock(thefile->filedes,fc, 0, 0) == -1) + return errno; + + return APR_SUCCESS; +} + +apr_status_t apr_file_unlock(apr_file_t *thefile) +{ + if(NXFileRangeUnlock(thefile->filedes,NX_RANGE_LOCK_CANCEL,0 , 0) == -1) + return errno; + + return APR_SUCCESS; +} diff --git a/file_io/netware/mktemp.c b/file_io/netware/mktemp.c new file mode 100644 index 0000000..4f78226 --- /dev/null +++ b/file_io/netware/mktemp.c @@ -0,0 +1,64 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#include "apr_file_io.h" /* prototype of apr_mkstemp() */ +#include "apr_strings.h" /* prototype of apr_mkstemp() */ +#include "apr_arch_file_io.h" /* prototype of apr_mkstemp() */ +#include "apr_portable.h" /* for apr_os_file_put() */ +#include "apr_arch_inherit.h" + +#include <stdlib.h> /* for mkstemp() - Single Unix */ + +APR_DECLARE(apr_status_t) apr_file_mktemp(apr_file_t **fp, char *template, apr_int32_t flags, apr_pool_t *p) +{ + int fd; + apr_status_t rv; + + flags = (!flags) ? APR_FOPEN_CREATE | APR_FOPEN_READ | APR_FOPEN_WRITE | + APR_FOPEN_DELONCLOSE : flags & ~APR_FOPEN_EXCL; + + fd = mkstemp(template); + if (fd == -1) { + return errno; + } + /* We need to reopen the file to get rid of the o_excl flag. + * Otherwise file locking will not allow the file to be shared. + */ + close(fd); + if ((rv = apr_file_open(fp, template, flags|APR_FOPEN_NOCLEANUP, + APR_UREAD | APR_UWRITE, p)) == APR_SUCCESS) { + + + if (!(flags & APR_FOPEN_NOCLEANUP)) { + int flags; + + if ((flags = fcntl((*fp)->filedes, F_GETFD)) == -1) + return errno; + + flags |= FD_CLOEXEC; + if (fcntl((*fp)->filedes, F_SETFD, flags) == -1) + return errno; + + apr_pool_cleanup_register((*fp)->pool, (void *)(*fp), + apr_unix_file_cleanup, + apr_unix_child_file_cleanup); + } + } + + return rv; +} + diff --git a/file_io/netware/pipe.c b/file_io/netware/pipe.c new file mode 100644 index 0000000..26e09d7 --- /dev/null +++ b/file_io/netware/pipe.c @@ -0,0 +1,239 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <nks/fsio.h> +#include <nks/errno.h> + +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_arch_inherit.h" + +static apr_status_t pipeblock(apr_file_t *thepipe) +{ +#ifdef USE_FLAGS + unsigned long flags; + + if (fcntl(thepipe->filedes, F_GETFL, &flags) != -1) + { + flags &= ~FNDELAY; + fcntl(thepipe->filedes, F_SETFL, flags); + } +#else + errno = 0; + fcntl(thepipe->filedes, F_SETFL, 0); +#endif + + if (errno) + return errno; + + thepipe->blocking = BLK_ON; + return APR_SUCCESS; +} + +static apr_status_t pipenonblock(apr_file_t *thepipe) +{ +#ifdef USE_FLAGS + unsigned long flags; + + errno = 0; + if (fcntl(thepipe->filedes, F_GETFL, &flags) != -1) + { + flags |= FNDELAY; + fcntl(thepipe->filedes, F_SETFL, flags); + } +#else + errno = 0; + fcntl(thepipe->filedes, F_SETFL, FNDELAY); +#endif + + if (errno) + return errno; + + thepipe->blocking = BLK_OFF; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout) +{ + if (thepipe->is_pipe == 1) { + thepipe->timeout = timeout; + if (timeout >= 0) { + if (thepipe->blocking != BLK_OFF) { /* blocking or unknown state */ + return pipenonblock(thepipe); + } + } + else { + if (thepipe->blocking != BLK_ON) { /* non-blocking or unknown state */ + return pipeblock(thepipe); + } + } + return APR_SUCCESS; + } + return APR_EINVAL; +} + +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout) +{ + if (thepipe->is_pipe == 1) { + *timeout = thepipe->timeout; + return APR_SUCCESS; + } + return APR_EINVAL; +} + +APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file, + apr_os_file_t *thefile, + int register_cleanup, + apr_pool_t *pool) +{ + int *dafile = thefile; + + (*file) = apr_pcalloc(pool, sizeof(apr_file_t)); + (*file)->pool = pool; + (*file)->eof_hit = 0; + (*file)->is_pipe = 1; + (*file)->blocking = BLK_UNKNOWN; /* app needs to make a timeout call */ + (*file)->timeout = -1; + (*file)->ungetchar = -1; /* no char avail */ + (*file)->filedes = *dafile; + if (!register_cleanup) { + (*file)->flags = APR_FOPEN_NOCLEANUP; + } + (*file)->buffered = 0; +#if APR_HAS_THREADS + (*file)->thlock = NULL; +#endif + if (register_cleanup) { + apr_pool_cleanup_register((*file)->pool, (void *)(*file), + apr_unix_file_cleanup, + apr_pool_cleanup_null); + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_pool_t *pool) +{ + return apr_os_pipe_put_ex(file, thefile, 0, pool); +} + +static apr_status_t file_pipe_create(apr_file_t **in, apr_file_t **out, + apr_pool_t *pool_in, apr_pool_t *pool_out) +{ + int filedes[2]; + + if (pipe(filedes) == -1) { + return errno; + } + + (*in) = (apr_file_t *)apr_pcalloc(pool_in, sizeof(apr_file_t)); + (*out) = (apr_file_t *)apr_pcalloc(pool_out, sizeof(apr_file_t)); + + (*in)->pool = pool_in; + (*out)->pool = pool_out; + (*in)->filedes = filedes[0]; + (*out)->filedes = filedes[1]; + (*in)->flags = APR_INHERIT; + (*out)->flags = APR_INHERIT; + (*in)->is_pipe = + (*out)->is_pipe = 1; + (*out)->fname = + (*in)->fname = NULL; + (*in)->buffered = + (*out)->buffered = 0; + (*in)->blocking = + (*out)->blocking = BLK_ON; + (*in)->timeout = + (*out)->timeout = -1; + (*in)->ungetchar = -1; + (*in)->thlock = + (*out)->thlock = NULL; + (void) apr_pollset_create(&(*in)->pollset, 1, pool_in, 0); + (void) apr_pollset_create(&(*out)->pollset, 1, pool_out, 0); + + apr_pool_cleanup_register((*in)->pool, (void *)(*in), apr_unix_file_cleanup, + apr_pool_cleanup_null); + apr_pool_cleanup_register((*out)->pool, (void *)(*out), apr_unix_file_cleanup, + apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +static void file_pipe_block(apr_file_t **in, apr_file_t **out, + apr_int32_t blocking) +{ + switch (blocking) { + case APR_FULL_BLOCK: + break; + case APR_READ_BLOCK: + apr_file_pipe_timeout_set(*out, 0); + break; + case APR_WRITE_BLOCK: + apr_file_pipe_timeout_set(*in, 0); + break; + default: + apr_file_pipe_timeout_set(*out, 0); + apr_file_pipe_timeout_set(*in, 0); + break; + } +} + +APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, apr_file_t **out, apr_pool_t *pool) +{ + return file_pipe_create(in, out, pool, pool); +} + +APR_DECLARE(apr_status_t) apr_file_pipe_create_ex(apr_file_t **in, + apr_file_t **out, + apr_int32_t blocking, + apr_pool_t *pool) +{ + apr_status_t status; + + if ((status = file_pipe_create(in, out, pool, pool)) != APR_SUCCESS) { + return status; + } + + file_pipe_block(in, out, blocking); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_pipe_create_pools(apr_file_t **in, + apr_file_t **out, apr_int32_t blocking, apr_pool_t *pool_in, apr_pool_t *pool_out) +{ + apr_status_t status; + + if ((status = file_pipe_create(in, out, pool_in, pool_out)) != APR_SUCCESS) { + return status; + } + + file_pipe_block(in, out, blocking); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, + apr_fileperms_t perm, apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + + + |