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