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 - 1.49
+++ file_io/unix/filestat.c 2 Feb 2002 20:32:36 -
@@ -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,