[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] APR turn off readonly/executable, add apr_file_attrs_get

From: Philip Martin <philip_at_codematters.co.uk>
Date: 2002-02-02 21:34:44 CET

Greg Stein <gstein@lyra.org> writes:

> (btw, for completeness, we'd also want ways to turn off readonly and to the
> executable state)

Here's a patch that does that, and provides a way to query the
attributes. It also makes the permission setting by apr_file_attrs_set
respect the umask of the process. So when removing readonly, the world
write flag, for example, only gets set if the umask allows.

Index: file_io/unix/filestat.c
===================================================================
RCS file: /home/cvspublic/apr/file_io/unix/filestat.c,v
retrieving revision 1.49
diff -u -r1.49 filestat.c
--- file_io/unix/filestat.c 1 Feb 2002 01:40:38 -0000 1.49
+++ file_io/unix/filestat.c 2 Feb 2002 20:32:36 -0000
@@ -109,6 +109,42 @@
      */
 }
 
+/* This function is necessary because the APR mutex interface doesn't
+ * provide static mutex initialisation, i.e. there is nothing equivalent
+ * to PTHREAD_MUTEX_INITIALIZER. It's difficult to see how it could, given
+ * the need for a pool.
+ */
+static apr_thread_mutex_t *umask_mutex;
+apr_status_t apr_unix_setup_umask(apr_pool_t *cont)
+{
+ return apr_thread_mutex_create(&umask_mutex, APR_THREAD_MUTEX_DEFAULT, cont);
+}
+
+static apr_status_t get_umask(apr_fileperms_t *umask_perms, apr_pool_t *cont)
+{
+ apr_status_t status;
+ mode_t umask_raw;
+
+#ifdef APR_HAS_THREADS
+ status = apr_thread_mutex_lock(umask_mutex);
+ if (!APR_STATUS_IS_SUCCESS(status))
+ return status;
+#endif
+
+ umask_raw = umask(0);
+ umask(umask_raw);
+
+#ifdef APR_HAS_THREADS
+ status = apr_thread_mutex_unlock(umask_mutex);
+ if (!APR_STATUS_IS_SUCCESS(status))
+ return status;
+#endif
+
+ *umask_perms = apr_unix_mode2perms(umask_raw);
+
+ return APR_SUCCESS;
+}
+
 APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo,
                                             apr_int32_t wanted,
                                             apr_file_t *thefile)
@@ -142,26 +178,84 @@
 {
     apr_status_t status;
     apr_finfo_t finfo;
+ apr_fileperms_t mask;
+ apr_fileperms_t attr_perms;
 
     status = apr_stat(&finfo, fname, APR_FINFO_PROT, cont);
     if (!APR_STATUS_IS_SUCCESS(status))
         return status;
 
     if (attributes & APR_FILE_ATTR_READONLY) {
+ /* Make readonly by removing all write bits */
         finfo.protection &= ~APR_UWRITE;
         finfo.protection &= ~APR_GWRITE;
         finfo.protection &= ~APR_WWRITE;
     }
+ else {
+ /* Make non-readonly by setting all write bits permitted by umask */
+ attr_perms = APR_UWRITE | APR_GWRITE | APR_WWRITE;
+ status = get_umask(&mask, cont);
+ if (!APR_STATUS_IS_SUCCESS(status))
+ return status;
+ attr_perms &= ~mask;
+ finfo.protection |= attr_perms;
+ }
+
     if (attributes & APR_FILE_ATTR_EXECUTABLE) {
- /* ### TODO: should this be umask'd? */
- finfo.protection |= APR_UEXECUTE;
- finfo.protection |= APR_GEXECUTE;
- finfo.protection |= APR_WEXECUTE;
+ /* Make executable by setting all execute bits permitted by umask */
+ attr_perms = APR_UEXECUTE | APR_GEXECUTE | APR_WEXECUTE;
+ status = get_umask(&mask, cont);
+ if (!APR_STATUS_IS_SUCCESS(status))
+ return status;
+ attr_perms &= ~mask;
+ finfo.protection |= attr_perms;
+ }
+ else {
+ /* Make non-executable by removing all execute bits */
+ finfo.protection &= ~APR_UEXECUTE;
+ finfo.protection &= ~APR_GEXECUTE;
+ finfo.protection &= ~APR_WEXECUTE;
     }
 
    return apr_file_perms_set(fname, finfo.protection);
 }
                                                   
+APR_DECLARE(apr_status_t) apr_file_attrs_get(const char *fname,
+ apr_fileattrs_t *attributes,
+ apr_pool_t *cont)
+{
+ apr_status_t status;
+ apr_finfo_t finfo;
+ apr_fileperms_t perm_mask;
+ mode_t mask;
+
+ status = apr_stat(&finfo, fname, APR_FINFO_PROT, cont);
+ if (!APR_STATUS_IS_SUCCESS(status))
+ return status;
+
+ *attributes = 0;
+
+ /* All the write bits */
+ perm_mask = APR_UWRITE | APR_GWRITE | APR_WWRITE;
+
+ /* Claim readonly only if no write bits are set */
+ if (!(finfo.protection & perm_mask))
+ *attributes |= APR_FILE_ATTR_READONLY;
+
+ /* All the execute bits allowed by umask */
+ perm_mask = APR_UEXECUTE | APR_GEXECUTE | APR_WEXECUTE;
+ status = get_umask(&mask, cont);
+ if (!APR_STATUS_IS_SUCCESS(status))
+ return status;
+ perm_mask &= ~mask;
+
+ /* Claim executable only if all execute bits are set */
+ if ((finfo.protection & perm_mask) == perm_mask)
+ *attributes |= APR_FILE_ATTR_EXECUTABLE;
+
+ return APR_SUCCESS;
+}
+
 APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo,
                                    const char *fname,
                                    apr_int32_t wanted, apr_pool_t *cont)
Index: file_io/win32/filestat.c
===================================================================
RCS file: /home/cvspublic/apr/file_io/win32/filestat.c,v
retrieving revision 1.62
diff -u -r1.62 filestat.c
--- file_io/win32/filestat.c 1 Feb 2002 01:40:38 -0000 1.62
+++ file_io/win32/filestat.c 2 Feb 2002 20:32:36 -0000
@@ -618,3 +618,10 @@
 {
    return APR_ENOTIMPL;
 }
+
+APR_DECLARE(apr_status_t) apr_file_attrs_get(const char *fname,
+ apr_fileattrs_t *attributes,
+ apr_pool_t *cont)
+{
+ return APR_ENOTIMPL;
+}
Index: include/apr_file_io.h
===================================================================
RCS file: /home/cvspublic/apr/include/apr_file_io.h,v
retrieving revision 1.117
diff -u -r1.117 apr_file_io.h
--- include/apr_file_io.h 1 Feb 2002 01:40:38 -0000 1.117
+++ include/apr_file_io.h 2 Feb 2002 20:32:37 -0000
@@ -578,7 +578,7 @@
 /**
  * Set attributes of the specified file.
  * @param fname The full path to the file (using / on all systems)
- * @param attributes Or'd combination of
+ * @param attributes Or'd combination of attribute flags
  * <PRE>
  * APR_FILE_ATTR_READONLY - make the file readonly
  * APR_FILE_ATTR_EXECUTABLE - make the file executable
@@ -588,11 +588,29 @@
  * of the file permissions, because the operations to provide these
  * attributes are platform specific and may involve more than simply
  * setting permission bits.
+ * @remark If any of the attribute flags are not set in the parameter passed
+ * to this function, then those attributes will be removed from the file.
  * @warning Platforms which do not implement this feature will return
  * APR_ENOTIMPL.
  */
 APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname,
                                              apr_fileattrs_t attributes,
+ apr_pool_t *cont);
+
+/**
+ * Get attributes of the specified file.
+ * @param fname The full path to the file (using / on all systems)
+ * @param attributes Pointer to variable in which to store the file's attributes
+ * @param cont the pool to use.
+ * @remark This function should be used in preference to explict examination
+ * of the file permissions, because the operations to provide these
+ * attributes are platform specific and may involve more than simply
+ * setting permission bits.
+ * @warning Platforms which do not implement this feature will return
+ * APR_ENOTIMPL.
+ */
+APR_DECLARE(apr_status_t) apr_file_attrs_get(const char *fname,
+ apr_fileattrs_t *attributes,
                                              apr_pool_t *cont);
 
 /**
Index: include/arch/unix/fileio.h
===================================================================
RCS file: /home/cvspublic/apr/include/arch/unix/fileio.h,v
retrieving revision 1.37
diff -u -r1.37 fileio.h
--- include/arch/unix/fileio.h 21 Nov 2001 04:21:04 -0000 1.37
+++ include/arch/unix/fileio.h 2 Feb 2002 20:32:37 -0000
@@ -154,5 +154,7 @@
 mode_t apr_unix_perms2mode(apr_fileperms_t perms);
 apr_fileperms_t apr_unix_mode2perms(mode_t mode);
 
+apr_status_t apr_unix_setup_umask(apr_pool_t *cont);
+
 #endif /* ! FILE_IO_H */
 
Index: misc/unix/start.c
===================================================================
RCS file: /home/cvspublic/apr/misc/unix/start.c,v
retrieving revision 1.61
diff -u -r1.61 start.c
--- misc/unix/start.c 1 Feb 2002 17:27:38 -0000 1.61
+++ misc/unix/start.c 2 Feb 2002 20:32:37 -0000
@@ -132,6 +132,11 @@
 #endif
     
     apr_signal_init(pool);
+#if !defined(BEOS) && !defined(OS2) && !defined(WIN32)
+ if ((status = apr_unix_setup_umask(pool)) != APR_SUCCESS) {
+ return status;
+ }
+#endif
 
     return APR_SUCCESS;
 }

-- 
Philip
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Oct 21 14:37:03 2006

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.