summaryrefslogtreecommitdiffstats
path: root/file_io/os2
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:23:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 06:23:09 +0000
commit30d479c28c831a0d4f1fdb54a9e346b0fc176be1 (patch)
treeaa35d7414ce9f1326abf6f723f6dfa5b0aa08b1d /file_io/os2
parentInitial commit. (diff)
downloadapr-upstream/1.7.2.tar.xz
apr-upstream/1.7.2.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/os2/buffer.c59
-rw-r--r--file_io/os2/copy.c1
-rw-r--r--file_io/os2/dir.c167
-rw-r--r--file_io/os2/dir_make_recurse.c90
-rw-r--r--file_io/os2/fileacc.c18
-rw-r--r--file_io/os2/filedup.c124
-rw-r--r--file_io/os2/filepath.c16
-rw-r--r--file_io/os2/filepath_util.c1
-rw-r--r--file_io/os2/filestat.c241
-rw-r--r--file_io/os2/filesys.c148
-rw-r--r--file_io/os2/flock.c37
-rw-r--r--file_io/os2/fullrw.c1
-rw-r--r--file_io/os2/maperrorcode.c95
-rw-r--r--file_io/os2/mktemp.c1
-rw-r--r--file_io/os2/open.c304
-rw-r--r--file_io/os2/pipe.c236
-rw-r--r--file_io/os2/readwrite.c388
-rw-r--r--file_io/os2/seek.c120
-rw-r--r--file_io/os2/tempdir.c1
19 files changed, 2048 insertions, 0 deletions
diff --git a/file_io/os2/buffer.c b/file_io/os2/buffer.c
new file mode 100644
index 0000000..34e4e63
--- /dev/null
+++ b/file_io/os2/buffer.c
@@ -0,0 +1,59 @@
+/* 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 "apr_thread_mutex.h"
+
+APR_DECLARE(apr_status_t) apr_file_buffer_set(apr_file_t *file,
+ char * buffer,
+ apr_size_t bufsize)
+{
+ apr_status_t rv;
+
+ apr_thread_mutex_lock(file->mutex);
+
+ if(file->buffered) {
+ /* Flush the existing buffer */
+ rv = apr_file_flush(file);
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(file->mutex);
+ return rv;
+ }
+ }
+
+ file->buffer = buffer;
+ file->bufsize = bufsize;
+ file->buffered = 1;
+ file->bufpos = 0;
+ file->direction = 0;
+ file->dataRead = 0;
+
+ if (file->bufsize == 0) {
+ /* Setting the buffer size to zero is equivalent to turning
+ * buffering off.
+ */
+ file->buffered = 0;
+ }
+
+ apr_thread_mutex_unlock(file->mutex);
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_size_t) apr_file_buffer_size_get(apr_file_t *file)
+{
+ return file->bufsize;
+}
diff --git a/file_io/os2/copy.c b/file_io/os2/copy.c
new file mode 100644
index 0000000..f4ce010
--- /dev/null
+++ b/file_io/os2/copy.c
@@ -0,0 +1 @@
+#include "../unix/copy.c"
diff --git a/file_io/os2/dir.c b/file_io/os2/dir.c
new file mode 100644
index 0000000..3b08355
--- /dev/null
+++ b/file_io/os2/dir.c
@@ -0,0 +1,167 @@
+/* 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 "apr_file_io.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include <string.h>
+
+static apr_status_t dir_cleanup(void *thedir)
+{
+ apr_dir_t *dir = thedir;
+ return apr_dir_close(dir);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_dir_open(apr_dir_t **new, const char *dirname, apr_pool_t *pool)
+{
+ apr_dir_t *thedir = (apr_dir_t *)apr_palloc(pool, sizeof(apr_dir_t));
+
+ if (thedir == NULL)
+ return APR_ENOMEM;
+
+ thedir->pool = pool;
+ thedir->dirname = apr_pstrdup(pool, dirname);
+
+ if (thedir->dirname == NULL)
+ return APR_ENOMEM;
+
+ thedir->handle = 0;
+ thedir->validentry = FALSE;
+ *new = thedir;
+ apr_pool_cleanup_register(pool, thedir, dir_cleanup, apr_pool_cleanup_null);
+ return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *thedir)
+{
+ int rv = 0;
+
+ if (thedir->handle) {
+ rv = DosFindClose(thedir->handle);
+
+ if (rv == 0) {
+ thedir->handle = 0;
+ }
+ }
+
+ return APR_FROM_OS_ERROR(rv);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted,
+ apr_dir_t *thedir)
+{
+ int rv;
+ ULONG entries = 1;
+
+ if (thedir->handle == 0) {
+ thedir->handle = HDIR_CREATE;
+ rv = DosFindFirst(apr_pstrcat(thedir->pool, thedir->dirname, "/*", NULL), &thedir->handle,
+ FILE_ARCHIVED|FILE_DIRECTORY|FILE_SYSTEM|FILE_HIDDEN|FILE_READONLY,
+ &thedir->entry, sizeof(thedir->entry), &entries, FIL_STANDARD);
+ } else {
+ rv = DosFindNext(thedir->handle, &thedir->entry, sizeof(thedir->entry), &entries);
+ }
+
+ finfo->pool = thedir->pool;
+ finfo->fname = NULL;
+ finfo->valid = 0;
+
+ if (rv == 0 && entries == 1) {
+ thedir->validentry = TRUE;
+
+ /* We passed a name off the stack that has popped */
+ finfo->fname = NULL;
+ finfo->size = thedir->entry.cbFile;
+ finfo->csize = thedir->entry.cbFileAlloc;
+
+ /* Only directories & regular files show up in directory listings */
+ finfo->filetype = (thedir->entry.attrFile & FILE_DIRECTORY) ? APR_DIR : APR_REG;
+
+ apr_os2_time_to_apr_time(&finfo->mtime, thedir->entry.fdateLastWrite,
+ thedir->entry.ftimeLastWrite);
+ apr_os2_time_to_apr_time(&finfo->atime, thedir->entry.fdateLastAccess,
+ thedir->entry.ftimeLastAccess);
+ apr_os2_time_to_apr_time(&finfo->ctime, thedir->entry.fdateCreation,
+ thedir->entry.ftimeCreation);
+
+ finfo->name = thedir->entry.achName;
+ finfo->valid = APR_FINFO_NAME | APR_FINFO_MTIME | APR_FINFO_ATIME |
+ APR_FINFO_CTIME | APR_FINFO_TYPE | APR_FINFO_SIZE |
+ APR_FINFO_CSIZE;
+
+ return APR_SUCCESS;
+ }
+
+ thedir->validentry = FALSE;
+
+ if (rv)
+ return APR_FROM_OS_ERROR(rv);
+
+ return APR_ENOENT;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *thedir)
+{
+ return apr_dir_close(thedir);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_dir_make(const char *path, apr_fileperms_t perm, apr_pool_t *pool)
+{
+ return APR_FROM_OS_ERROR(DosCreateDir(path, NULL));
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_dir_remove(const char *path, apr_pool_t *pool)
+{
+ return APR_FROM_OS_ERROR(DosDeleteDir(path));
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_os_dir_get(apr_os_dir_t **thedir, apr_dir_t *dir)
+{
+ if (dir == NULL) {
+ return APR_ENODIR;
+ }
+ *thedir = &dir->handle;
+ return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_os_dir_put(apr_dir_t **dir, apr_os_dir_t *thedir,
+ apr_pool_t *pool)
+{
+ if ((*dir) == NULL) {
+ (*dir) = (apr_dir_t *)apr_pcalloc(pool, sizeof(apr_dir_t));
+ (*dir)->pool = pool;
+ }
+ (*dir)->handle = *thedir;
+ return APR_SUCCESS;
+}
diff --git a/file_io/os2/dir_make_recurse.c b/file_io/os2/dir_make_recurse.c
new file mode 100644
index 0000000..602a621
--- /dev/null
+++ b/file_io/os2/dir_make_recurse.c
@@ -0,0 +1,90 @@
+/* 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_file_io.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include <string.h>
+
+#define IS_SEP(c) (c == '/' || c == '\\')
+
+/* Remove trailing separators that don't affect the meaning of PATH. */
+static const char *path_canonicalize(const char *path, apr_pool_t *pool)
+{
+ /* At some point this could eliminate redundant components. For
+ * now, it just makes sure there is no trailing slash. */
+ apr_size_t len = strlen(path);
+ apr_size_t orig_len = len;
+
+ while ((len > 0) && IS_SEP(path[len - 1])) {
+ len--;
+ }
+
+ if (len != orig_len) {
+ return apr_pstrndup(pool, path, len);
+ }
+ else {
+ return path;
+ }
+}
+
+
+
+/* Remove one component off the end of PATH. */
+static char *path_remove_last_component(const char *path, apr_pool_t *pool)
+{
+ const char *newpath = path_canonicalize(path, pool);
+ int i;
+
+ for (i = strlen(newpath) - 1; i >= 0; i--) {
+ if (IS_SEP(path[i])) {
+ break;
+ }
+ }
+
+ return apr_pstrndup(pool, path, (i < 0) ? 0 : i);
+}
+
+
+
+apr_status_t apr_dir_make_recursive(const char *path, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ apr_status_t apr_err = APR_SUCCESS;
+
+ apr_err = apr_dir_make(path, perm, pool); /* Try to make PATH right out */
+
+ if (APR_STATUS_IS_ENOENT(apr_err)) { /* Missing an intermediate dir */
+ char *dir;
+
+ dir = path_remove_last_component(path, pool);
+ apr_err = apr_dir_make_recursive(dir, perm, pool);
+
+ if (!apr_err) {
+ apr_err = apr_dir_make(path, perm, pool);
+ }
+ }
+
+ /*
+ * It's OK if PATH exists. Timing issues can lead to the second
+ * apr_dir_make being called on existing dir, therefore this check
+ * has to come last.
+ */
+ if (APR_STATUS_IS_EEXIST(apr_err))
+ return APR_SUCCESS;
+
+ return apr_err;
+}
diff --git a/file_io/os2/fileacc.c b/file_io/os2/fileacc.c
new file mode 100644
index 0000000..b5c1afd
--- /dev/null
+++ b/file_io/os2/fileacc.c
@@ -0,0 +1,18 @@
+/* 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 "../unix/fileacc.c"
+
diff --git a/file_io/os2/filedup.c b/file_io/os2/filedup.c
new file mode 100644
index 0000000..86f06f3
--- /dev/null
+++ b/file_io/os2/filedup.c
@@ -0,0 +1,124 @@
+/* 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 "apr_file_io.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include <string.h>
+#include "apr_arch_inherit.h"
+
+static apr_status_t file_dup(apr_file_t **new_file, apr_file_t *old_file, apr_pool_t *p)
+{
+ int rv;
+ apr_file_t *dup_file;
+
+ if (*new_file == NULL) {
+ dup_file = (apr_file_t *)apr_palloc(p, sizeof(apr_file_t));
+
+ if (dup_file == NULL) {
+ return APR_ENOMEM;
+ }
+
+ dup_file->filedes = -1;
+ } else {
+ dup_file = *new_file;
+ }
+
+ dup_file->pool = p;
+ rv = DosDupHandle(old_file->filedes, &dup_file->filedes);
+
+ if (rv) {
+ return APR_FROM_OS_ERROR(rv);
+ }
+
+ dup_file->fname = apr_pstrdup(dup_file->pool, old_file->fname);
+ dup_file->buffered = old_file->buffered;
+ dup_file->isopen = old_file->isopen;
+ dup_file->flags = old_file->flags & ~APR_INHERIT;
+ /* TODO - dup pipes correctly */
+ dup_file->pipe = old_file->pipe;
+
+ if (*new_file == NULL) {
+ apr_pool_cleanup_register(dup_file->pool, dup_file, apr_file_cleanup,
+ apr_pool_cleanup_null);
+ *new_file = dup_file;
+ }
+
+ return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_dup(apr_file_t **new_file, apr_file_t *old_file, apr_pool_t *p)
+{
+ if (*new_file) {
+ apr_file_close(*new_file);
+ (*new_file)->filedes = -1;
+ }
+
+ return file_dup(new_file, old_file, p);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_dup2(apr_file_t *new_file, apr_file_t *old_file, apr_pool_t *p)
+{
+ return file_dup(&new_file, old_file, p);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file,
+ apr_file_t *old_file,
+ apr_pool_t *p)
+{
+ *new_file = (apr_file_t *)apr_pmemdup(p, old_file, sizeof(apr_file_t));
+ (*new_file)->pool = p;
+
+ if (old_file->buffered) {
+ (*new_file)->buffer = apr_palloc(p, old_file->bufsize);
+ (*new_file)->bufsize = old_file->bufsize;
+
+ if (old_file->direction == 1) {
+ memcpy((*new_file)->buffer, old_file->buffer, old_file->bufpos);
+ }
+ else {
+ memcpy((*new_file)->buffer, old_file->buffer, old_file->dataRead);
+ }
+
+ if (old_file->mutex) {
+ apr_thread_mutex_create(&((*new_file)->mutex),
+ APR_THREAD_MUTEX_DEFAULT, p);
+ apr_thread_mutex_destroy(old_file->mutex);
+ }
+ }
+
+ if (old_file->fname) {
+ (*new_file)->fname = apr_pstrdup(p, old_file->fname);
+ }
+
+ if (!(old_file->flags & APR_FOPEN_NOCLEANUP)) {
+ apr_pool_cleanup_kill(old_file->pool, (void *)old_file,
+ apr_file_cleanup);
+ apr_pool_cleanup_register(p, (void *)(*new_file),
+ apr_file_cleanup,
+ apr_file_cleanup);
+ }
+
+ old_file->filedes = -1;
+ return APR_SUCCESS;
+}
diff --git a/file_io/os2/filepath.c b/file_io/os2/filepath.c
new file mode 100644
index 0000000..9422faa
--- /dev/null
+++ b/file_io/os2/filepath.c
@@ -0,0 +1,16 @@
+/* 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 "../win32/filepath.c"
diff --git a/file_io/os2/filepath_util.c b/file_io/os2/filepath_util.c
new file mode 100644
index 0000000..a89c173
--- /dev/null
+++ b/file_io/os2/filepath_util.c
@@ -0,0 +1 @@
+#include "../unix/filepath_util.c"
diff --git a/file_io/os2/filestat.c b/file_io/os2/filestat.c
new file mode 100644
index 0000000..cd163e4
--- /dev/null
+++ b/file_io/os2/filestat.c
@@ -0,0 +1,241 @@
+/* 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.
+ */
+
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include "apr_arch_file_io.h"
+#include "apr_file_io.h"
+#include "apr_lib.h"
+#include <sys/time.h>
+#include "apr_strings.h"
+
+
+static void FS3_to_finfo(apr_finfo_t *finfo, FILESTATUS3 *fstatus)
+{
+ finfo->protection = (fstatus->attrFile & FILE_READONLY) ? 0x555 : 0x777;
+
+ if (fstatus->attrFile & FILE_DIRECTORY)
+ finfo->filetype = APR_DIR;
+ else
+ finfo->filetype = APR_REG;
+ /* XXX: No other possible types from FS3? */
+
+ finfo->user = 0;
+ finfo->group = 0;
+ finfo->inode = 0;
+ finfo->device = 0;
+ finfo->size = fstatus->cbFile;
+ finfo->csize = fstatus->cbFileAlloc;
+ apr_os2_time_to_apr_time(&finfo->atime, fstatus->fdateLastAccess,
+ fstatus->ftimeLastAccess );
+ apr_os2_time_to_apr_time(&finfo->mtime, fstatus->fdateLastWrite,
+ fstatus->ftimeLastWrite );
+ apr_os2_time_to_apr_time(&finfo->ctime, fstatus->fdateCreation,
+ fstatus->ftimeCreation );
+ finfo->valid = APR_FINFO_TYPE | APR_FINFO_PROT | APR_FINFO_SIZE
+ | APR_FINFO_CSIZE | APR_FINFO_MTIME
+ | APR_FINFO_CTIME | APR_FINFO_ATIME | APR_FINFO_LINK;
+}
+
+
+
+static apr_status_t handle_type(apr_filetype_e *ftype, HFILE file)
+{
+ ULONG filetype, fileattr, rc;
+
+ rc = DosQueryHType(file, &filetype, &fileattr);
+
+ if (rc == 0) {
+ switch (filetype & 0xff) {
+ case 0:
+ *ftype = APR_REG;
+ break;
+
+ case 1:
+ *ftype = APR_CHR;
+ break;
+
+ case 2:
+ *ftype = APR_PIPE;
+ break;
+
+ default:
+ /* Brian, is this correct???
+ */
+ *ftype = APR_UNKFILE;
+ break;
+ }
+
+ return APR_SUCCESS;
+ }
+ return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, apr_int32_t wanted,
+ apr_file_t *thefile)
+{
+ ULONG rc;
+ FILESTATUS3 fstatus;
+
+ if (thefile->isopen) {
+ if (thefile->buffered) {
+ /* XXX: flush here is not mutex protected */
+ apr_status_t rv = apr_file_flush(thefile);
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ }
+
+ rc = DosQueryFileInfo(thefile->filedes, FIL_STANDARD, &fstatus, sizeof(fstatus));
+ }
+ else
+ rc = DosQueryPathInfo(thefile->fname, FIL_STANDARD, &fstatus, sizeof(fstatus));
+
+ if (rc == 0) {
+ FS3_to_finfo(finfo, &fstatus);
+ finfo->fname = thefile->fname;
+
+ if (finfo->filetype == APR_REG) {
+ if (thefile->isopen) {
+ return handle_type(&finfo->filetype, thefile->filedes);
+ }
+ } else {
+ return APR_SUCCESS;
+ }
+ }
+
+ finfo->protection = 0;
+ finfo->filetype = APR_NOFILE;
+ return APR_FROM_OS_ERROR(rc);
+}
+
+APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, apr_fileperms_t perms)
+{
+ return APR_ENOTIMPL;
+}
+
+
+APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, const char *fname,
+ apr_int32_t wanted, apr_pool_t *cont)
+{
+ ULONG rc;
+ FILESTATUS3 fstatus;
+
+ finfo->protection = 0;
+ finfo->filetype = APR_NOFILE;
+ finfo->name = NULL;
+ rc = DosQueryPathInfo(fname, FIL_STANDARD, &fstatus, sizeof(fstatus));
+
+ if (rc == 0) {
+ FS3_to_finfo(finfo, &fstatus);
+ finfo->fname = fname;
+
+ if (wanted & APR_FINFO_NAME) {
+ ULONG count = 1;
+ HDIR hDir = HDIR_SYSTEM;
+ FILEFINDBUF3 ffb;
+ rc = DosFindFirst(fname, &hDir,
+ FILE_DIRECTORY|FILE_HIDDEN|FILE_SYSTEM|FILE_ARCHIVED,
+ &ffb, sizeof(ffb), &count, FIL_STANDARD);
+ if (rc == 0 && count == 1) {
+ finfo->name = apr_pstrdup(cont, ffb.achName);
+ finfo->valid |= APR_FINFO_NAME;
+ }
+ }
+ } else if (rc == ERROR_INVALID_ACCESS) {
+ memset(finfo, 0, sizeof(apr_finfo_t));
+ finfo->valid = APR_FINFO_TYPE | APR_FINFO_PROT;
+ finfo->protection = 0666;
+ finfo->filetype = APR_CHR;
+
+ if (wanted & APR_FINFO_NAME) {
+ finfo->name = apr_pstrdup(cont, fname);
+ finfo->valid |= APR_FINFO_NAME;
+ }
+ } else {
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ return (wanted & ~finfo->valid) ? APR_INCOMPLETE : 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 *cont)
+{
+ FILESTATUS3 fs3;
+ ULONG rc;
+
+ /* Don't do anything if we can't handle the requested attributes */
+ if (!(attr_mask & (APR_FILE_ATTR_READONLY
+ | APR_FILE_ATTR_HIDDEN)))
+ return APR_SUCCESS;
+
+ rc = DosQueryPathInfo(fname, FIL_STANDARD, &fs3, sizeof(fs3));
+ if (rc == 0) {
+ ULONG old_attr = fs3.attrFile;
+
+ if (attr_mask & APR_FILE_ATTR_READONLY)
+ {
+ if (attributes & APR_FILE_ATTR_READONLY) {
+ fs3.attrFile |= FILE_READONLY;
+ } else {
+ fs3.attrFile &= ~FILE_READONLY;
+ }
+ }
+
+ if (attr_mask & APR_FILE_ATTR_HIDDEN)
+ {
+ if (attributes & APR_FILE_ATTR_HIDDEN) {
+ fs3.attrFile |= FILE_HIDDEN;
+ } else {
+ fs3.attrFile &= ~FILE_HIDDEN;
+ }
+ }
+
+ if (fs3.attrFile != old_attr) {
+ rc = DosSetPathInfo(fname, FIL_STANDARD, &fs3, sizeof(fs3), 0);
+ }
+ }
+
+ return APR_FROM_OS_ERROR(rc);
+}
+
+
+/* ### Somebody please write this! */
+APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname,
+ apr_time_t mtime,
+ apr_pool_t *pool)
+{
+ FILESTATUS3 fs3;
+ ULONG rc;
+ rc = DosQueryPathInfo(fname, FIL_STANDARD, &fs3, sizeof(fs3));
+
+ if (rc) {
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ apr_apr_time_to_os2_time(&fs3.fdateLastWrite, &fs3.ftimeLastWrite, mtime);
+
+ rc = DosSetPathInfo(fname, FIL_STANDARD, &fs3, sizeof(fs3), 0);
+ return APR_FROM_OS_ERROR(rc);
+}
diff --git a/file_io/os2/filesys.c b/file_io/os2/filesys.c
new file mode 100644
index 0000000..ae43bc0
--- /dev/null
+++ b/file_io/os2/filesys.c
@@ -0,0 +1,148 @@
+/* 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"
+#include "apr_lib.h"
+#include <ctype.h>
+
+/* OS/2 Exceptions:
+ *
+ * Note that trailing spaces and trailing periods are never recorded
+ * in the file system.
+ *
+ * Leading spaces and periods are accepted, however.
+ * The * ? < > codes all have wildcard side effects
+ * The " / \ : are exclusively component separator tokens
+ * The system doesn't accept | for any (known) purpose
+ * Oddly, \x7f _is_ acceptable ;)
+ */
+
+const char c_is_fnchar[256] =
+{/* Reject all ctrl codes... */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ /* " * / : < > ? */
+ 1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,0, 1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0,
+ /* \ */
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,
+ /* | */
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,
+ /* High bit codes are accepted */
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
+};
+
+
+#define IS_SLASH(c) (c == '/' || c == '\\')
+
+
+apr_status_t filepath_root_test(char *path, apr_pool_t *p)
+{
+ char drive = apr_toupper(path[0]);
+
+ if (drive >= 'A' && drive <= 'Z' && path[1] == ':' && IS_SLASH(path[2]))
+ return APR_SUCCESS;
+
+ return APR_EBADPATH;
+}
+
+
+apr_status_t filepath_drive_get(char **rootpath, char drive,
+ apr_int32_t flags, apr_pool_t *p)
+{
+ char path[APR_PATH_MAX];
+ char *pos;
+ ULONG rc;
+ ULONG bufsize = sizeof(path) - 3;
+
+ path[0] = drive;
+ path[1] = ':';
+ path[2] = '/';
+
+ rc = DosQueryCurrentDir(apr_toupper(drive) - 'A', path+3, &bufsize);
+
+ if (rc) {
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ if (!(flags & APR_FILEPATH_NATIVE)) {
+ for (pos=path; *pos; pos++) {
+ if (*pos == '\\')
+ *pos = '/';
+ }
+ }
+
+ *rootpath = apr_pstrdup(p, path);
+ return APR_SUCCESS;
+}
+
+
+apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p)
+{
+ if (root[0] && apr_islower(root[0]) && root[1] == ':') {
+ *rootpath = apr_pstrdup(p, root);
+ (*rootpath)[0] = apr_toupper((*rootpath)[0]);
+ }
+ else {
+ *rootpath = root;
+ }
+ return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_filepath_get(char **defpath, apr_int32_t flags,
+ apr_pool_t *p)
+{
+ char path[APR_PATH_MAX];
+ ULONG drive;
+ ULONG drivemap;
+ ULONG rv, pathlen = sizeof(path) - 3;
+ char *pos;
+
+ DosQueryCurrentDisk(&drive, &drivemap);
+ path[0] = '@' + drive;
+ strcpy(path+1, ":\\");
+ rv = DosQueryCurrentDir(drive, path+3, &pathlen);
+
+ *defpath = apr_pstrdup(p, path);
+
+ if (!(flags & APR_FILEPATH_NATIVE)) {
+ for (pos=*defpath; *pos; pos++) {
+ if (*pos == '\\')
+ *pos = '/';
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_filepath_set(const char *path, apr_pool_t *p)
+{
+ ULONG rv = 0;
+
+ if (path[1] == ':')
+ rv = DosSetDefaultDisk(apr_toupper(path[0]) - '@');
+
+ if (rv == 0)
+ rv = DosSetCurrentDir(path);
+
+ return APR_FROM_OS_ERROR(rv);
+}
diff --git a/file_io/os2/flock.c b/file_io/os2/flock.c
new file mode 100644
index 0000000..ec94022
--- /dev/null
+++ b/file_io/os2/flock.c
@@ -0,0 +1,37 @@
+/* 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"
+
+APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type)
+{
+ FILELOCK lockrange = { 0, 0x7fffffff };
+ ULONG rc;
+
+ rc = DosSetFileLocks(thefile->filedes, NULL, &lockrange,
+ (type & APR_FLOCK_NONBLOCK) ? 0 : (ULONG)-1,
+ (type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED);
+ return APR_FROM_OS_ERROR(rc);
+}
+
+APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile)
+{
+ FILELOCK unlockrange = { 0, 0x7fffffff };
+ ULONG rc;
+
+ rc = DosSetFileLocks(thefile->filedes, &unlockrange, NULL, 0, 0);
+ return APR_FROM_OS_ERROR(rc);
+}
diff --git a/file_io/os2/fullrw.c b/file_io/os2/fullrw.c
new file mode 100644
index 0000000..cf62948
--- /dev/null
+++ b/file_io/os2/fullrw.c
@@ -0,0 +1 @@
+#include "../unix/fullrw.c"
diff --git a/file_io/os2/maperrorcode.c b/file_io/os2/maperrorcode.c
new file mode 100644
index 0000000..282338b
--- /dev/null
+++ b/file_io/os2/maperrorcode.c
@@ -0,0 +1,95 @@
+/* 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.
+ */
+
+#define INCL_DOSERRORS
+#include "apr_arch_file_io.h"
+#include "apr_file_io.h"
+#include <errno.h>
+#include <string.h>
+#include "apr_errno.h"
+
+static int errormap[][2] = {
+ { NO_ERROR, APR_SUCCESS },
+ { ERROR_FILE_NOT_FOUND, APR_ENOENT },
+ { ERROR_PATH_NOT_FOUND, APR_ENOENT },
+ { ERROR_TOO_MANY_OPEN_FILES, APR_EMFILE },
+ { ERROR_ACCESS_DENIED, APR_EACCES },
+ { ERROR_SHARING_VIOLATION, APR_EACCES },
+ { ERROR_INVALID_PARAMETER, APR_EINVAL },
+ { ERROR_OPEN_FAILED, APR_ENOENT },
+ { ERROR_DISK_FULL, APR_ENOSPC },
+ { ERROR_FILENAME_EXCED_RANGE, APR_ENAMETOOLONG },
+ { ERROR_INVALID_FUNCTION, APR_EINVAL },
+ { ERROR_INVALID_HANDLE, APR_EBADF },
+ { ERROR_NEGATIVE_SEEK, APR_ESPIPE },
+ { ERROR_NO_SIGNAL_SENT, ESRCH },
+ { ERROR_NO_DATA, APR_EAGAIN },
+ { SOCEINTR, EINTR },
+ { SOCEWOULDBLOCK, EWOULDBLOCK },
+ { SOCEINPROGRESS, EINPROGRESS },
+ { SOCEALREADY, EALREADY },
+ { SOCENOTSOCK, ENOTSOCK },
+ { SOCEDESTADDRREQ, EDESTADDRREQ },
+ { SOCEMSGSIZE, EMSGSIZE },
+ { SOCEPROTOTYPE, EPROTOTYPE },
+ { SOCENOPROTOOPT, ENOPROTOOPT },
+ { SOCEPROTONOSUPPORT, EPROTONOSUPPORT },
+ { SOCESOCKTNOSUPPORT, ESOCKTNOSUPPORT },
+ { SOCEOPNOTSUPP, EOPNOTSUPP },
+ { SOCEPFNOSUPPORT, EPFNOSUPPORT },
+ { SOCEAFNOSUPPORT, EAFNOSUPPORT },
+ { SOCEADDRINUSE, EADDRINUSE },
+ { SOCEADDRNOTAVAIL, EADDRNOTAVAIL },
+ { SOCENETDOWN, ENETDOWN },
+ { SOCENETUNREACH, ENETUNREACH },
+ { SOCENETRESET, ENETRESET },
+ { SOCECONNABORTED, ECONNABORTED },
+ { SOCECONNRESET, ECONNRESET },
+ { SOCENOBUFS, ENOBUFS },
+ { SOCEISCONN, EISCONN },
+ { SOCENOTCONN, ENOTCONN },
+ { SOCESHUTDOWN, ESHUTDOWN },
+ { SOCETOOMANYREFS, ETOOMANYREFS },
+ { SOCETIMEDOUT, ETIMEDOUT },
+ { SOCECONNREFUSED, ECONNREFUSED },
+ { SOCELOOP, ELOOP },
+ { SOCENAMETOOLONG, ENAMETOOLONG },
+ { SOCEHOSTDOWN, EHOSTDOWN },
+ { SOCEHOSTUNREACH, EHOSTUNREACH },
+ { SOCENOTEMPTY, ENOTEMPTY },
+ { SOCEPIPE, EPIPE }
+};
+
+#define MAPSIZE (sizeof(errormap)/sizeof(errormap[0]))
+
+int apr_canonical_error(apr_status_t err)
+{
+ int rv = -1, index;
+
+ if (err < APR_OS_START_SYSERR)
+ return err;
+
+ err -= APR_OS_START_SYSERR;
+
+ for (index=0; index<MAPSIZE && errormap[index][0] != err; index++);
+
+ if (index<MAPSIZE)
+ rv = errormap[index][1];
+ else
+ fprintf(stderr, "apr_canonical_error: Unknown OS/2 error code %d\n", err );
+
+ return rv;
+}
diff --git a/file_io/os2/mktemp.c b/file_io/os2/mktemp.c
new file mode 100644
index 0000000..9e85236
--- /dev/null
+++ b/file_io/os2/mktemp.c
@@ -0,0 +1 @@
+#include "../unix/mktemp.c"
diff --git a/file_io/os2/open.c b/file_io/os2/open.c
new file mode 100644
index 0000000..12badd6
--- /dev/null
+++ b/file_io/os2/open.c
@@ -0,0 +1,304 @@
+/* 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 "apr_file_io.h"
+#include "apr_lib.h"
+#include "apr_portable.h"
+#include "apr_strings.h"
+#include "apr_arch_inherit.h"
+#include <string.h>
+
+apr_status_t apr_file_cleanup(void *thefile)
+{
+ apr_file_t *file = thefile;
+ return apr_file_close(file);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, const char *fname, apr_int32_t flag, apr_fileperms_t perm, apr_pool_t *pool)
+{
+ int oflags = 0;
+ int mflags = OPEN_FLAGS_FAIL_ON_ERROR|OPEN_SHARE_DENYNONE|OPEN_FLAGS_NOINHERIT;
+ int rv;
+ ULONG action;
+ apr_file_t *dafile = (apr_file_t *)apr_palloc(pool, sizeof(apr_file_t));
+
+ if (flag & APR_FOPEN_NONBLOCK) {
+ return APR_ENOTIMPL;
+ }
+
+ dafile->pool = pool;
+ dafile->isopen = FALSE;
+ dafile->eof_hit = FALSE;
+ dafile->buffer = NULL;
+ dafile->flags = flag;
+ dafile->blocking = BLK_ON;
+
+ if ((flag & APR_FOPEN_READ) && (flag & APR_FOPEN_WRITE)) {
+ mflags |= OPEN_ACCESS_READWRITE;
+ } else if (flag & APR_FOPEN_READ) {
+ mflags |= OPEN_ACCESS_READONLY;
+ } else if (flag & APR_FOPEN_WRITE) {
+ mflags |= OPEN_ACCESS_WRITEONLY;
+ } else {
+ dafile->filedes = -1;
+ return APR_EACCES;
+ }
+
+ dafile->buffered = (flag & APR_FOPEN_BUFFERED) > 0;
+
+ if (dafile->buffered) {
+ dafile->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
+ dafile->bufsize = APR_FILE_DEFAULT_BUFSIZE;
+ rv = apr_thread_mutex_create(&dafile->mutex, 0, pool);
+
+ if (rv)
+ return rv;
+ }
+
+ if (flag & APR_FOPEN_CREATE) {
+ oflags |= OPEN_ACTION_CREATE_IF_NEW;
+
+ if (!(flag & APR_FOPEN_EXCL) && !(flag & APR_FOPEN_TRUNCATE)) {
+ oflags |= OPEN_ACTION_OPEN_IF_EXISTS;
+ }
+ }
+
+ if ((flag & APR_FOPEN_EXCL) && !(flag & APR_FOPEN_CREATE))
+ return APR_EACCES;
+
+ if (flag & APR_FOPEN_TRUNCATE) {
+ oflags |= OPEN_ACTION_REPLACE_IF_EXISTS;
+ } else if ((oflags & 0xFF) == 0) {
+ oflags |= OPEN_ACTION_OPEN_IF_EXISTS;
+ }
+
+ rv = DosOpen(fname, &(dafile->filedes), &action, 0, 0, oflags, mflags, NULL);
+
+ if (rv == 0 && (flag & APR_FOPEN_APPEND)) {
+ ULONG newptr;
+ rv = DosSetFilePtr(dafile->filedes, 0, FILE_END, &newptr );
+
+ if (rv)
+ DosClose(dafile->filedes);
+ }
+
+ if (rv != 0)
+ return APR_FROM_OS_ERROR(rv);
+
+ dafile->isopen = TRUE;
+ dafile->fname = apr_pstrdup(pool, fname);
+ dafile->filePtr = 0;
+ dafile->bufpos = 0;
+ dafile->dataRead = 0;
+ dafile->direction = 0;
+ dafile->pipe = FALSE;
+
+ if (!(flag & APR_FOPEN_NOCLEANUP)) {
+ apr_pool_cleanup_register(dafile->pool, dafile, apr_file_cleanup, apr_file_cleanup);
+ }
+
+ *new = dafile;
+ return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file)
+{
+ ULONG rc;
+ apr_status_t status;
+
+ if (file && file->isopen) {
+ /* XXX: flush here is not mutex protected */
+ status = apr_file_flush(file);
+ rc = DosClose(file->filedes);
+
+ if (rc == 0) {
+ file->isopen = FALSE;
+
+ if (file->flags & APR_FOPEN_DELONCLOSE) {
+ status = APR_FROM_OS_ERROR(DosDelete(file->fname));
+ }
+ /* else we return the status of the flush attempt
+ * when all else succeeds
+ */
+ } else {
+ return APR_FROM_OS_ERROR(rc);
+ }
+ }
+
+ if (file->buffered)
+ apr_thread_mutex_destroy(file->mutex);
+
+ return status;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_remove(const char *path, apr_pool_t *pool)
+{
+ ULONG rc = DosDelete(path);
+ return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_rename(const char *from_path, const char *to_path,
+ apr_pool_t *p)
+{
+ ULONG rc = DosMove(from_path, to_path);
+
+ if (rc == ERROR_ACCESS_DENIED || rc == ERROR_ALREADY_EXISTS) {
+ rc = DosDelete(to_path);
+
+ if (rc == 0 || rc == ERROR_FILE_NOT_FOUND) {
+ rc = DosMove(from_path, to_path);
+ }
+ }
+
+ return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile, apr_file_t *file)
+{
+ *thefile = file->filedes;
+ return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file, apr_os_file_t *thefile, apr_int32_t flags, apr_pool_t *pool)
+{
+ apr_os_file_t *dafile = thefile;
+
+ (*file) = apr_palloc(pool, sizeof(apr_file_t));
+ (*file)->pool = pool;
+ (*file)->filedes = *dafile;
+ (*file)->isopen = TRUE;
+ (*file)->eof_hit = FALSE;
+ (*file)->flags = flags;
+ (*file)->pipe = FALSE;
+ (*file)->buffered = (flags & APR_FOPEN_BUFFERED) > 0;
+
+ if ((*file)->buffered) {
+ apr_status_t rv;
+
+ (*file)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
+ (*file)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
+ rv = apr_thread_mutex_create(&(*file)->mutex, 0, pool);
+
+ if (rv)
+ return rv;
+ }
+
+ return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_eof(apr_file_t *fptr)
+{
+ if (!fptr->isopen || fptr->eof_hit == 1) {
+ return APR_EOF;
+ }
+ return APR_SUCCESS;
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_open_flags_stderr(apr_file_t **thefile,
+ apr_int32_t flags,
+ apr_pool_t *pool)
+{
+ apr_os_file_t fd = 2;
+
+ return apr_os_file_put(thefile, &fd, flags | APR_FOPEN_WRITE, pool);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_open_flags_stdout(apr_file_t **thefile,
+ apr_int32_t flags,
+ apr_pool_t *pool)
+{
+ apr_os_file_t fd = 1;
+
+ return apr_os_file_put(thefile, &fd, flags | APR_FOPEN_WRITE, pool);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_open_flags_stdin(apr_file_t **thefile,
+ apr_int32_t flags,
+ apr_pool_t *pool)
+{
+ apr_os_file_t fd = 0;
+
+ return apr_os_file_put(thefile, &fd, flags | APR_FOPEN_READ, pool);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_open_stderr(apr_file_t **thefile, apr_pool_t *pool)
+{
+ return apr_file_open_flags_stderr(thefile, 0, pool);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_open_stdout(apr_file_t **thefile, apr_pool_t *pool)
+{
+ return apr_file_open_flags_stdout(thefile, 0, pool);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_open_stdin(apr_file_t **thefile, apr_pool_t *pool)
+{
+ return apr_file_open_flags_stdin(thefile, 0, pool);
+}
+
+APR_POOL_IMPLEMENT_ACCESSOR(file);
+
+
+
+APR_DECLARE(apr_status_t) apr_file_inherit_set(apr_file_t *thefile)
+{
+ int rv;
+ ULONG state;
+
+ rv = DosQueryFHState(thefile->filedes, &state);
+
+ if (rv == 0 && (state & OPEN_FLAGS_NOINHERIT) != 0) {
+ rv = DosSetFHState(thefile->filedes, state & ~OPEN_FLAGS_NOINHERIT);
+ }
+
+ return APR_FROM_OS_ERROR(rv);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_inherit_unset(apr_file_t *thefile)
+{
+ int rv;
+ ULONG state;
+
+ rv = DosQueryFHState(thefile->filedes, &state);
+
+ if (rv == 0 && (state & OPEN_FLAGS_NOINHERIT) == 0) {
+ rv = DosSetFHState(thefile->filedes, state | OPEN_FLAGS_NOINHERIT);
+ }
+
+ return APR_FROM_OS_ERROR(rv);
+}
diff --git a/file_io/os2/pipe.c b/file_io/os2/pipe.c
new file mode 100644
index 0000000..14f2b1a
--- /dev/null
+++ b/file_io/os2/pipe.c
@@ -0,0 +1,236 @@
+/* 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.
+ */
+
+#define INCL_DOSERRORS
+#include "apr_arch_file_io.h"
+#include "apr_file_io.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include <string.h>
+#include <process.h>
+
+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)
+{
+ ULONG filedes[2];
+ ULONG rc, action;
+ static int id = 0;
+ char pipename[50];
+
+ sprintf(pipename, "/pipe/%d.%d", getpid(), id++);
+ rc = DosCreateNPipe(pipename, filedes, NP_ACCESS_INBOUND, NP_NOWAIT|1, 4096, 4096, 0);
+
+ if (rc)
+ return APR_FROM_OS_ERROR(rc);
+
+ rc = DosConnectNPipe(filedes[0]);
+
+ if (rc && rc != ERROR_PIPE_NOT_CONNECTED) {
+ DosClose(filedes[0]);
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ rc = DosOpen (pipename, filedes+1, &action, 0, FILE_NORMAL,
+ OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
+ OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYREADWRITE,
+ NULL);
+
+ if (rc) {
+ DosClose(filedes[0]);
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ (*in) = (apr_file_t *)apr_palloc(pool_in, sizeof(apr_file_t));
+ rc = DosCreateEventSem(NULL, &(*in)->pipeSem, DC_SEM_SHARED, FALSE);
+
+ if (rc) {
+ DosClose(filedes[0]);
+ DosClose(filedes[1]);
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ rc = DosSetNPipeSem(filedes[0], (HSEM)(*in)->pipeSem, 1);
+
+ if (!rc) {
+ rc = DosSetNPHState(filedes[0], NP_WAIT);
+ }
+
+ if (rc) {
+ DosClose(filedes[0]);
+ DosClose(filedes[1]);
+ DosCloseEventSem((*in)->pipeSem);
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ (*in)->pool = pool_in;
+ (*in)->filedes = filedes[0];
+ (*in)->fname = apr_pstrdup(pool_in, pipename);
+ (*in)->isopen = TRUE;
+ (*in)->buffered = FALSE;
+ (*in)->flags = 0;
+ (*in)->pipe = 1;
+ (*in)->timeout = -1;
+ (*in)->blocking = BLK_ON;
+ apr_pool_cleanup_register(pool_in, *in, apr_file_cleanup,
+ apr_pool_cleanup_null);
+
+ (*out) = (apr_file_t *)apr_palloc(pool_out, sizeof(apr_file_t));
+ (*out)->pool = pool_out;
+ (*out)->filedes = filedes[1];
+ (*out)->fname = apr_pstrdup(pool_out, pipename);
+ (*out)->isopen = TRUE;
+ (*out)->buffered = FALSE;
+ (*out)->flags = 0;
+ (*out)->pipe = 1;
+ (*out)->timeout = -1;
+ (*out)->blocking = BLK_ON;
+ apr_pool_cleanup_register(pool_out, *out, apr_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)
+{
+ /* Not yet implemented, interface not suitable */
+ return APR_ENOTIMPL;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout)
+{
+ if (thepipe->pipe == 1) {
+ thepipe->timeout = timeout;
+
+ if (thepipe->timeout >= 0) {
+ if (thepipe->blocking != BLK_OFF) {
+ thepipe->blocking = BLK_OFF;
+ return APR_FROM_OS_ERROR(DosSetNPHState(thepipe->filedes, NP_NOWAIT));
+ }
+ }
+ else if (thepipe->timeout == -1) {
+ if (thepipe->blocking != BLK_ON) {
+ thepipe->blocking = BLK_ON;
+ return APR_FROM_OS_ERROR(DosSetNPHState(thepipe->filedes, NP_WAIT));
+ }
+ }
+ }
+ return APR_EINVAL;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout)
+{
+ if (thepipe->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)
+{
+ (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
+ (*file)->pool = pool;
+ (*file)->isopen = TRUE;
+ (*file)->pipe = 1;
+ (*file)->blocking = BLK_UNKNOWN; /* app needs to make a timeout call */
+ (*file)->timeout = -1;
+ (*file)->filedes = *thefile;
+
+ if (register_cleanup) {
+ apr_pool_cleanup_register(pool, *file, apr_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);
+}
diff --git a/file_io/os2/readwrite.c b/file_io/os2/readwrite.c
new file mode 100644
index 0000000..d00591d
--- /dev/null
+++ b/file_io/os2/readwrite.c
@@ -0,0 +1,388 @@
+/* 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.
+ */
+
+#define INCL_DOS
+#define INCL_DOSERRORS
+
+#include "apr_arch_file_io.h"
+#include "apr_file_io.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+
+#include <malloc.h>
+
+APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes)
+{
+ ULONG rc = 0;
+ ULONG bytesread;
+
+ if (!thefile->isopen) {
+ *nbytes = 0;
+ return APR_EBADF;
+ }
+
+ if (thefile->buffered) {
+ char *pos = (char *)buf;
+ ULONG blocksize;
+ ULONG size = *nbytes;
+
+ apr_thread_mutex_lock(thefile->mutex);
+
+ if (thefile->direction == 1) {
+ int rv = apr_file_flush(thefile);
+
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(thefile->mutex);
+ return rv;
+ }
+
+ thefile->bufpos = 0;
+ thefile->direction = 0;
+ thefile->dataRead = 0;
+ }
+
+ while (rc == 0 && size > 0) {
+ if (thefile->bufpos >= thefile->dataRead) {
+ ULONG bytesread;
+ rc = DosRead(thefile->filedes, thefile->buffer,
+ thefile->bufsize, &bytesread);
+
+ if (bytesread == 0) {
+ if (rc == 0)
+ thefile->eof_hit = TRUE;
+ break;
+ }
+
+ thefile->dataRead = bytesread;
+ thefile->filePtr += thefile->dataRead;
+ thefile->bufpos = 0;
+ }
+
+ blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;
+ memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
+ thefile->bufpos += blocksize;
+ pos += blocksize;
+ size -= blocksize;
+ }
+
+ *nbytes = rc == 0 ? pos - (char *)buf : 0;
+ apr_thread_mutex_unlock(thefile->mutex);
+
+ if (*nbytes == 0 && rc == 0 && thefile->eof_hit) {
+ return APR_EOF;
+ }
+
+ return APR_FROM_OS_ERROR(rc);
+ } else {
+ if (thefile->pipe)
+ DosResetEventSem(thefile->pipeSem, &rc);
+
+ rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
+
+ if (rc == ERROR_NO_DATA && thefile->timeout != 0) {
+ int rcwait = DosWaitEventSem(thefile->pipeSem, thefile->timeout >= 0 ? thefile->timeout / 1000 : SEM_INDEFINITE_WAIT);
+
+ if (rcwait == 0) {
+ rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
+ }
+ else if (rcwait == ERROR_TIMEOUT) {
+ *nbytes = 0;
+ return APR_TIMEUP;
+ }
+ }
+
+ if (rc) {
+ *nbytes = 0;
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ *nbytes = bytesread;
+
+ if (bytesread == 0) {
+ thefile->eof_hit = TRUE;
+ return APR_EOF;
+ }
+
+ return APR_SUCCESS;
+ }
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes)
+{
+ ULONG rc = 0;
+ ULONG byteswritten;
+
+ if (!thefile->isopen) {
+ *nbytes = 0;
+ return APR_EBADF;
+ }
+
+ if (thefile->buffered) {
+ char *pos = (char *)buf;
+ int blocksize;
+ int size = *nbytes;
+
+ apr_thread_mutex_lock(thefile->mutex);
+
+ if ( thefile->direction == 0 ) {
+ /* Position file pointer for writing at the offset we are logically reading from */
+ ULONG offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
+ if (offset != thefile->filePtr)
+ DosSetFilePtr(thefile->filedes, offset, FILE_BEGIN, &thefile->filePtr );
+ thefile->bufpos = thefile->dataRead = 0;
+ thefile->direction = 1;
+ }
+
+ while (rc == 0 && size > 0) {
+ if (thefile->bufpos == thefile->bufsize) /* write buffer is full */
+ /* XXX bug; - rc is double-transformed os->apr below */
+ rc = apr_file_flush(thefile);
+
+ blocksize = size > thefile->bufsize - thefile->bufpos ? thefile->bufsize - thefile->bufpos : size;
+ memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);
+ thefile->bufpos += blocksize;
+ pos += blocksize;
+ size -= blocksize;
+ }
+
+ apr_thread_mutex_unlock(thefile->mutex);
+ return APR_FROM_OS_ERROR(rc);
+ } else {
+ if (thefile->flags & APR_FOPEN_APPEND) {
+ FILELOCK all = { 0, 0x7fffffff };
+ ULONG newpos;
+ rc = DosSetFileLocks(thefile->filedes, NULL, &all, -1, 0);
+
+ if (rc == 0) {
+ rc = DosSetFilePtr(thefile->filedes, 0, FILE_END, &newpos);
+
+ if (rc == 0) {
+ rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
+ }
+
+ DosSetFileLocks(thefile->filedes, &all, NULL, -1, 0);
+ }
+ } else {
+ rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
+ }
+
+ if (rc) {
+ *nbytes = 0;
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ *nbytes = byteswritten;
+ return APR_SUCCESS;
+ }
+}
+
+
+
+#ifdef HAVE_WRITEV
+
+APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec, apr_size_t nvec, apr_size_t *nbytes)
+{
+ int bytes;
+
+ if (thefile->buffered) {
+ apr_status_t rv = apr_file_flush(thefile);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ }
+
+ if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
+ *nbytes = 0;
+ return errno;
+ }
+ else {
+ *nbytes = bytes;
+ return APR_SUCCESS;
+ }
+}
+#endif
+
+
+
+APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile)
+{
+ ULONG rc;
+ ULONG byteswritten;
+
+ if (!thefile->isopen) {
+ return APR_EBADF;
+ }
+
+ rc = DosWrite(thefile->filedes, &ch, 1, &byteswritten);
+
+ if (rc) {
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile)
+{
+ apr_off_t offset = -1;
+ return apr_file_seek(thefile, APR_CUR, &offset);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile)
+{
+ ULONG rc;
+ apr_size_t bytesread;
+
+ if (!thefile->isopen) {
+ return APR_EBADF;
+ }
+
+ bytesread = 1;
+ rc = apr_file_read(thefile, ch, &bytesread);
+
+ if (rc) {
+ return rc;
+ }
+
+ if (bytesread == 0) {
+ thefile->eof_hit = TRUE;
+ return APR_EOF;
+ }
+
+ return APR_SUCCESS;
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile)
+{
+ apr_size_t len;
+
+ len = strlen(str);
+ return apr_file_write(thefile, str, &len);
+}
+
+
+APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile)
+{
+ if (thefile->buffered) {
+ ULONG written = 0;
+ int rc = 0;
+
+ if (thefile->direction == 1 && thefile->bufpos) {
+ rc = DosWrite(thefile->filedes, thefile->buffer, thefile->bufpos, &written);
+ thefile->filePtr += written;
+
+ if (rc == 0)
+ thefile->bufpos = 0;
+ }
+
+ return APR_FROM_OS_ERROR(rc);
+ } else {
+ /* There isn't anything to do if we aren't buffering the output
+ * so just return success.
+ */
+ return APR_SUCCESS;
+ }
+}
+
+APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile)
+{
+ return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile)
+{
+ return APR_ENOTIMPL;
+}
+
+APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile)
+{
+ apr_size_t readlen;
+ apr_status_t rv = APR_SUCCESS;
+ int i;
+
+ for (i = 0; i < len-1; i++) {
+ readlen = 1;
+ rv = apr_file_read(thefile, str+i, &readlen);
+
+ if (rv != APR_SUCCESS) {
+ break;
+ }
+
+ if (readlen != 1) {
+ rv = APR_EOF;
+ break;
+ }
+
+ if (str[i] == '\n') {
+ i++;
+ break;
+ }
+ }
+ str[i] = 0;
+ if (i > 0) {
+ /* we stored chars; don't report EOF or any other errors;
+ * the app will find out about that on the next call
+ */
+ return APR_SUCCESS;
+ }
+ return rv;
+}
+
+
+
+APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr,
+ const char *format, ...)
+{
+ int cc;
+ va_list ap;
+ char *buf;
+ int len;
+
+ buf = malloc(HUGE_STRING_LEN);
+ if (buf == NULL) {
+ return 0;
+ }
+ va_start(ap, format);
+ len = apr_vsnprintf(buf, HUGE_STRING_LEN, format, ap);
+ cc = apr_file_puts(buf, fptr);
+ va_end(ap);
+ free(buf);
+ return (cc == APR_SUCCESS) ? len : -1;
+}
+
+
+
+apr_status_t apr_file_check_read(apr_file_t *fd)
+{
+ int rc;
+
+ if (!fd->pipe)
+ return APR_SUCCESS; /* Not a pipe, assume no waiting */
+
+ rc = DosWaitEventSem(fd->pipeSem, SEM_IMMEDIATE_RETURN);
+
+ if (rc == ERROR_TIMEOUT)
+ return APR_TIMEUP;
+
+ return APR_FROM_OS_ERROR(rc);
+}
diff --git a/file_io/os2/seek.c b/file_io/os2/seek.c
new file mode 100644
index 0000000..a8d13fe
--- /dev/null
+++ b/file_io/os2/seek.c
@@ -0,0 +1,120 @@
+/* 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 "apr_file_io.h"
+#include "apr_lib.h"
+#include <string.h>
+#include <io.h>
+
+
+static apr_status_t setptr(apr_file_t *thefile, unsigned long pos )
+{
+ long newbufpos;
+ ULONG rc;
+
+ if (thefile->direction == 1) {
+ /* XXX: flush here is not mutex protected */
+ apr_status_t rv = apr_file_flush(thefile);
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ thefile->bufpos = thefile->direction = thefile->dataRead = 0;
+ }
+
+ newbufpos = pos - (thefile->filePtr - thefile->dataRead);
+ if (newbufpos >= 0 && newbufpos <= thefile->dataRead) {
+ thefile->bufpos = newbufpos;
+ rc = 0;
+ } else {
+ rc = DosSetFilePtr(thefile->filedes, pos, FILE_BEGIN, &thefile->filePtr );
+
+ if ( !rc )
+ thefile->bufpos = thefile->dataRead = 0;
+ }
+
+ return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t where, apr_off_t *offset)
+{
+ if (!thefile->isopen) {
+ return APR_EBADF;
+ }
+
+ thefile->eof_hit = 0;
+
+ if (thefile->buffered) {
+ int rc = EINVAL;
+ apr_finfo_t finfo;
+
+ switch (where) {
+ case APR_SET:
+ rc = setptr(thefile, *offset);
+ break;
+
+ case APR_CUR:
+ rc = setptr(thefile, thefile->filePtr - thefile->dataRead + thefile->bufpos + *offset);
+ break;
+
+ case APR_END:
+ rc = apr_file_info_get(&finfo, APR_FINFO_NORM, thefile);
+ if (rc == APR_SUCCESS)
+ rc = setptr(thefile, finfo.size + *offset);
+ break;
+ }
+
+ *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
+ return rc;
+ } else {
+ switch (where) {
+ case APR_SET:
+ where = FILE_BEGIN;
+ break;
+
+ case APR_CUR:
+ where = FILE_CURRENT;
+ break;
+
+ case APR_END:
+ where = FILE_END;
+ break;
+ }
+
+ return APR_FROM_OS_ERROR(DosSetFilePtr(thefile->filedes, *offset, where, (ULONG *)offset));
+ }
+}
+
+
+
+APR_DECLARE(apr_status_t) apr_file_trunc(apr_file_t *fp, apr_off_t offset)
+{
+ int rc = DosSetFileSize(fp->filedes, offset);
+
+ if (rc != 0) {
+ return APR_FROM_OS_ERROR(rc);
+ }
+
+ if (fp->buffered) {
+ return setptr(fp, offset);
+ }
+
+ return APR_SUCCESS;
+}
diff --git a/file_io/os2/tempdir.c b/file_io/os2/tempdir.c
new file mode 100644
index 0000000..6823569
--- /dev/null
+++ b/file_io/os2/tempdir.c
@@ -0,0 +1 @@
+#include "../unix/tempdir.c"