Greg Stein <[EMAIL PROTECTED]> 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

Reply via email to