diff options
author | bnicholes <bnicholes@13f79535-47bb-0310-9956-ffa450edef68> | 2002-02-22 15:51:49 +0000 |
---|---|---|
committer | bnicholes <bnicholes@13f79535-47bb-0310-9956-ffa450edef68> | 2002-02-22 15:51:49 +0000 |
commit | d5aea2347be49f68a5b30498634a60d256d73775 (patch) | |
tree | 928686f79a463c0afef972f7d2b23537290c5e80 /file_io | |
parent | a72082e7cbe4c09060b0b4898172f79f9db3e24a (diff) | |
download | libapr-d5aea2347be49f68a5b30498634a60d256d73775.tar.gz |
NetWare version of filestat.c
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@63054 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'file_io')
-rw-r--r-- | file_io/netware/filestat.c | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/file_io/netware/filestat.c b/file_io/netware/filestat.c new file mode 100644 index 000000000..2d0a74b63 --- /dev/null +++ b/file_io/netware/filestat.c @@ -0,0 +1,300 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000-2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" must + * not be used to endorse or promote products derived from this + * software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * nor may "Apache" appear in their name, without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + */ + +#include "fileio.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_errno.h" +#include "apr_hash.h" + +static apr_filetype_e filetype_from_mode(mode_t mode) +{ + apr_filetype_e type = APR_NOFILE; + + if (S_ISREG(mode)) + type = APR_REG; + if (S_ISDIR(mode)) + type = APR_DIR; + if (S_ISCHR(mode)) + type = APR_CHR; + if (S_ISBLK(mode)) + type = APR_BLK; + if (S_ISFIFO(mode)) + type = APR_PIPE; + if (S_ISLNK(mode)) + type = APR_LNK; + if (S_ISSOCK(mode)) + type = APR_SOCK; + 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; + 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_ansi_time_to_apr_time(&finfo->atime, info->st_atime); + apr_ansi_time_to_apr_time(&finfo->mtime, info->st_mtime); + apr_ansi_time_to_apr_time(&finfo->ctime, info->st_ctime); + /* ### needs to be revisited + * if (wanted & APR_FINFO_CSIZE) { + * finfo->csize = info->st_blocks * 512; + * finfo->valid |= APR_FINFO_CSIZE; + * } + */ +} + +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 (fstat(thefile->filedes, &info) == 0) { + finfo->cntxt = thefile->cntxt; + 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 *cont) +{ + apr_status_t status; + apr_finfo_t finfo; + + status = apr_stat(&finfo, fname, APR_FINFO_PROT, cont); + if (!APR_STATUS_IS_SUCCESS(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); +} + +typedef struct apr_stat_entry_t apr_stat_entry_t; + +struct apr_stat_entry_t { + struct stat info; + apr_time_t expire; +}; + +int cstat (const char *path, struct stat *buf) +{ + apr_hash_t *statCache = (apr_hash_t *)getStatCache(); + apr_pool_t *gPool = (apr_pool_t *)getGlobalPool(); + apr_stat_entry_t *stat_entry; + struct stat *info; + apr_time_t now = apr_time_now(); + char *key; + int ret; + int found = 0; + + if (!statCache && gPool) { + statCache = apr_hash_make(gPool); + setStatCache((void*)statCache); + } + + if (statCache) { + stat_entry = (apr_stat_entry_t*) apr_hash_get(statCache, path, APR_HASH_KEY_STRING); + if (stat_entry) { + if ((now - stat_entry->expire) > APR_USEC_PER_SEC) { + apr_hash_set(statCache, path, APR_HASH_KEY_STRING, NULL); + } + else { + memcpy (buf, &(stat_entry->info), sizeof(struct stat)); + found = 1; + } + } + + if (!found) { + ret = stat(path, buf); + if (ret == 0) { + key = apr_pstrdup (gPool, path); + stat_entry = apr_palloc (gPool, sizeof(apr_stat_entry_t)); + memcpy (&(stat_entry->info), buf, sizeof(struct stat)); + stat_entry->expire = now; + apr_hash_set(statCache, key, APR_HASH_KEY_STRING, stat_entry); + } + else + return ret; + } + } + else { + return stat(path, buf); + } + return 0; +} + +APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, + const char *fname, + apr_int32_t wanted, apr_pool_t *cont) +{ + struct stat info; + int srv; + + srv = cstat(fname, &info); + + if (srv == 0) { + finfo->cntxt = cont; + 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(cont, 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 + } +} + +/* Perhaps this becomes nothing but a macro? + */ +APR_DECLARE(apr_status_t) apr_lstat(apr_finfo_t *finfo, const char *fname, + apr_int32_t wanted, apr_pool_t *cont) +{ + return apr_stat(finfo, fname, wanted | APR_FINFO_LINK, cont); +} + |