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

[PATCH] issue 619 APR patch, issue 532 read-only admin

From: Philip Martin <philip_at_codematters.co.uk>
Date: 2002-01-31 23:26:44 CET

Hi

This is my proposed patch to move apr_copy_file and friends to
APR. I'm posting it here first because I've changed the subversion
code (beyond simple APR formatting) to support optional permissions
copying. I've also included the corresponding read-only admin patch,
so that you can see what this is all for.

--- /dev/null Sun Jul 29 01:33:18 2001
+++ file_io/unix/copy.c Thu Jan 31 21:11:37 2002
@@ -0,0 +1,153 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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"
+
+static apr_status_t
+apr_file_transfer_contents(const char *from_path,
+ const char *to_path,
+ apr_int32_t flags,
+ apr_fileperms_t to_perms,
+ apr_pool_t *pool)
+{
+ apr_file_t *s = NULL, *d = NULL; /* init to null important for APR */
+ apr_status_t status;
+ apr_status_t read_err, write_err;
+ apr_finfo_t finfo;
+ apr_fileperms_t perms;
+ char buf[BUFSIZ];
+
+ /* Open source file. */
+ status = apr_file_open(&s, from_path, APR_READ, APR_OS_DEFAULT, pool);
+ if (status)
+ return status;
+
+ /* Get its size. */
+ if (to_perms == APR_FILE_SOURCE_PERMS) {
+ status = apr_file_info_get(&finfo, APR_FINFO_PROT, s);
+ if (status) {
+ apr_file_close(s); /* toss any error */
+ return status;
+ }
+ perms = finfo.protection;
+ }
+ else
+ perms = to_perms;
+
+ /* Open dest file. */
+ status = apr_file_open(&d, to_path, flags, perms, pool);
+ if (status) {
+ apr_file_close(s); /* toss any error */
+ return status;
+ }
+
+ /* Copy bytes till the cows come home. */
+ read_err = 0;
+ while (!APR_STATUS_IS_EOF(read_err)) {
+ apr_size_t bytes_this_time = sizeof (buf);
+
+ /* Read 'em. */
+ read_err = apr_file_read(s, buf, &bytes_this_time);
+ if (read_err && !APR_STATUS_IS_EOF(read_err)) {
+ apr_file_close(s); /* toss any error */
+ apr_file_close(d); /* toss any error */
+ return read_err;
+ }
+
+ /* Write 'em. */
+ write_err = apr_file_write_full(d, buf, bytes_this_time, NULL);
+ if (write_err) {
+ apr_file_close(s); /* toss any error */
+ apr_file_close(d); /* toss any error */
+ return write_err;
+ }
+
+ if (read_err && APR_STATUS_IS_EOF(read_err)) {
+ status = apr_file_close (s);
+ if (status) {
+ apr_file_close(d); /* toss any error */
+ return status;
+ }
+
+ status = apr_file_close (d);
+ if (status)
+ return status;
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_file_copy(const char *from_path,
+ const char *to_path,
+ apr_fileperms_t perms,
+ apr_pool_t *pool)
+{
+ return apr_file_transfer_contents(from_path, to_path,
+ (APR_WRITE | APR_CREATE | APR_TRUNCATE),
+ perms,
+ pool);
+}
+
+APR_DECLARE(apr_status_t) apr_file_append(const char *from_path,
+ const char *to_path,
+ apr_fileperms_t perms,
+ apr_pool_t *pool)
+{
+ return apr_file_transfer_contents(from_path, to_path,
+ (APR_WRITE | APR_CREATE | APR_APPEND),
+ perms,
+ pool);
+}
Index: libapr.dsp
===================================================================
RCS file: /home/cvspublic/apr/libapr.dsp,v
retrieving revision 1.53
diff -u -r1.53 libapr.dsp
--- libapr.dsp 30 Jan 2002 03:16:13 -0000 1.53
+++ libapr.dsp 31 Jan 2002 21:52:35 -0000
@@ -103,6 +103,10 @@
 # PROP Default_Filter ""
 # Begin Source File
 
+SOURCE=.\file_io\unix\copy.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\file_io\win32\dir.c
 # End Source File
 # Begin Source File
Index: file_io/unix/Makefile.in
===================================================================
RCS file: /home/cvspublic/apr/file_io/unix/Makefile.in,v
retrieving revision 1.23
diff -u -r1.23 Makefile.in
--- file_io/unix/Makefile.in 31 Mar 2001 06:22:38 -0000 1.23
+++ file_io/unix/Makefile.in 31 Jan 2002 21:52:35 -0000
@@ -1,5 +1,6 @@
 
 TARGETS = \
+ copy.lo \
         dir.lo \
         fileacc.lo \
         filedup.lo \
Index: file_io/unix/filestat.c
===================================================================
RCS file: /home/cvspublic/apr/file_io/unix/filestat.c,v
retrieving revision 1.48
diff -u -r1.48 filestat.c
--- file_io/unix/filestat.c 16 Oct 2001 23:24:09 -0000 1.48
+++ file_io/unix/filestat.c 31 Jan 2002 21:52:35 -0000
@@ -136,6 +136,32 @@
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname,
+ apr_fileattrs_t attributes,
+ 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;
+
+ if (attributes & APR_FILE_ATTR_READONLY) {
+ finfo.protection &= ~APR_UWRITE;
+ finfo.protection &= ~APR_GWRITE;
+ finfo.protection &= ~APR_WWRITE;
+ }
+ if (attributes & APR_FILE_ATTR_EXECUTABLE) {
+ /* ### TODO: should this be umask'd? */
+ 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_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.61
diff -u -r1.61 filestat.c
--- file_io/win32/filestat.c 28 Jan 2002 15:56:08 -0000 1.61
+++ file_io/win32/filestat.c 31 Jan 2002 21:52:36 -0000
@@ -611,3 +611,10 @@
 {
     return apr_stat(finfo, fname, wanted | APR_FINFO_LINK, cont);
 }
+
+APR_DECLARE(apr_status_t) apr_file_attrs_set(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.116
diff -u -r1.116 apr_file_io.h
--- include/apr_file_io.h 25 Jan 2002 21:07:49 -0000 1.116
+++ include/apr_file_io.h 31 Jan 2002 21:52:36 -0000
@@ -115,6 +115,28 @@
 #define APR_END SEEK_END
 /** @} */
 
+/**
+ * @defgroup APR_file_set_attributes File Attribute Flags
+ * @{
+ */
+
+/* flags for apr_file_set_attributes */
+#define APR_FILE_ATTR_READONLY 0x01 /**< File is read-only */
+#define APR_FILE_ATTR_EXECUTABLE 0x02 /**< File is executable */
+/** @} */
+
+/**
+ * @defgroup APR_file_copy File Permission Flags
+ * @{
+ */
+
+/* additional permission flags for apr_file_copy and apr_file_append */
+#define APR_FILE_SOURCE_PERMS (APR_OS_DEFAULT+1) /**< Copy file permissions */
+/** @} */
+
+/** File attributes */
+typedef apr_int32_t apr_fileattrs_t;
+
 /** should be same as whence type in lseek, POSIX defines this as int */
 typedef int apr_seek_where_t;
 
@@ -205,6 +227,39 @@
                                           apr_pool_t *pool);
 
 /**
+ * copy the specified file to another file.
+ * @param from_path The full path to the original file (using / on all systems)
+ * @param to_path The full path to the new file (using / on all systems)
+ * @param perms Access permissions for the new file if it is created.
+ * In place of the usual or'd combination of file permissions, the
+ * value APR_FILE_SOURCE_PERMS may be given, in which case the source
+ * file's permissions are copied.
+ * @param pool The pool to use.
+ * @remark The new file does not need to exist, it will be created if required.
+ * @warning If the new file already exists, its contents will be overwritten.
+ */
+APR_DECLARE(apr_status_t) apr_file_copy(const char *from_path,
+ const char *to_path,
+ apr_fileperms_t perms,
+ apr_pool_t *pool);
+
+/**
+ * append the specified file to another file.
+ * @param from_path The full path to the source file (using / on all systems)
+ * @param to_path The full path to the destination file (using / on all systems)
+ * @param perms Access permissions for the destination file if it is created.
+ * In place of the usual or'd combination of file permissions, the
+ * value APR_FILE_SOURCE_PERMS may be given, in which case the source
+ * file's permissions are copied.
+ * @param pool The pool to use.
+ * @remark The new file does not need to exist, it will be created if required.
+ */
+APR_DECLARE(apr_status_t) apr_file_append(const char *from_path,
+ const char *to_path,
+ apr_fileperms_t perms,
+ apr_pool_t *pool);
+
+/**
  * Are we at the end of the file
  * @param fptr The apr file we are testing.
  * @remark Returns APR_EOF if we are at the end of file, APR_SUCCESS otherwise.
@@ -528,6 +583,26 @@
  */
 APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname,
                                            apr_fileperms_t perms);
+
+/**
+ * Set attributes of the specified file.
+ * @param fname The full path to the file (using / on all systems)
+ * @param attributes Or'd combination of
+ * <PRE>
+ * APR_FILE_ATTR_READONLY - make the file readonly
+ * APR_FILE_ATTR_EXECUTABLE - make the file executable
+ * </PRE>
+ * @param cont the pool to use.
+ * @remark This function should be used in preference to explict manipulation
+ * 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_set(const char *fname,
+ apr_fileattrs_t attributes,
+ apr_pool_t *cont);
 
 /**
  * Create a new directory on the file system.

Issue #532: make files in the .svn admin area readonly.

* subversion/include/svn_io.h
  (svn_io_copy_file): Add boolean permissions copying parameter.
  (svn_io_copy_dir_recursively): Add boolean permissions copying parameter.
  (svn_io_set_file_read_only): Add prototype.

* subversion/libsvn_subr/io.c
  (apr_transfer_file_contents): Remove to APR.
  (apr_copy_file): Remove to APR.
  (apr_append_file): Remove to APR.
  (svn_io_copy_file): Call new APR function.
  (svn_io_append_file): Call new APR function.
  (svn_io_copy_dir_recursively): Pass new parameter to svn_io_copy_file and
  recursive svn_io_copy_dir_recursively.
  (svn_io_set_file_read_only): Add function.

* subversion/libsvn_wc/adm_crawler.c
  (do_postfix_text_deltas, do_prop_deltas, restore_file): Pass new parameter
  to svn_io_copy_file.

* subversion/libsvn_wc/adm_files.c
  (maybe_copy_file): Pass new parameter to svn_io_copy_file.
  (sync_adm_file): Use svn_io_set_file_read_only to make permanent adm file
  readonly.
  (close_adm_file): Use svn_io_set_file_read_only to make permanent adm file
  readonly.

* subversion/libsvn_wc/copy.c
  (copy_file_administratively): Pass new parameter to svn_io_copy_file.
  (copy_dir_administratively): Pass new parameter to svn_io_copy_dir_recursively

* subversion/libsvn_wc/get_editor.c (close_file): Add log entry to
  make text-base readonly.

* subversion/libsvn_wc/log.c
  (replace_text_base): Pass new parameter to svn_io_copy_file.
  (log_do_file_readonly): New function.
  (start_handler): Handle SVN_WC__LOG_READONLY.

* subversion/libsvn_wc/props.c (svn_wc__do_property_merge): Add log entries
  to make property files readonly.

* subversion/libsvn_wc/translate.c (svn_wc_copy_and_translate): Pass new
  parameter to svn_io_copy_file.

* subversion/libsvn_wc/wc.h
  (SVN_WC__LOG_READONLY): Add log tag.

Index: ./subversion/include/svn_io.h
===================================================================
--- ./subversion/include/svn_io.h
+++ ./subversion/include/svn_io.h Thu Jan 31 21:58:26 2002
@@ -108,18 +108,22 @@
                                       apr_pool_t *pool);
 
 
-/* Copy SRC to DST. DST will be overwritten if it exists, else it
- will be created. */
+/* Copy SRC to DST. DST will be overwritten if it exists, else it will be
+ created. If COPY_PERMS is set the file permissions of DST will be set to
+ match those of SRC, this will happen before the contents are copied. */
 svn_error_t *svn_io_copy_file (const char *src,
                                const char *dst,
+ svn_boolean_t copy_perms,
                                apr_pool_t *pool);
 
-/* Recursively copy directory SRC into DST_PARENT, as a new entry
- named DST_BASENAME. If DST_BASENAME already exists in DST_PARENT,
- return error. */
+/* Recursively copy directory SRC into DST_PARENT, as a new entry named
+ DST_BASENAME. If DST_BASENAME already exists in DST_PARENT, return
+ error. COPY_PERMS will be passed through to svn_io_copy_file when any
+ files are copied. */
 svn_error_t *svn_io_copy_dir_recursively (svn_stringbuf_t *src,
                                           svn_stringbuf_t *dst_parent,
                                           svn_stringbuf_t *dst_basename,
+ svn_boolean_t copy_perms,
                                           apr_pool_t *pool);
 
 
@@ -134,6 +138,11 @@
 svn_error_t *svn_io_append_file (svn_stringbuf_t *src,
                                  svn_stringbuf_t *dst,
                                  apr_pool_t *pool);
+
+/* Make a file as read-only as the operating system allows.
+ * PATH is the path to the file.
+ */
+svn_error_t *svn_io_set_file_read_only (const char *path, apr_pool_t *pool);
 
 
 /* Read a line from FILE into BUF, but not exceeding *LIMIT bytes.
Index: ./subversion/libsvn_wc/props.c
===================================================================
--- ./subversion/libsvn_wc/props.c
+++ ./subversion/libsvn_wc/props.c Tue Jan 29 19:17:36 2002
@@ -621,6 +621,15 @@
                          real_prop_base,
                          NULL);
 
+ /* Make prop-base readonly */
+ svn_xml_make_open_tag (entry_accum,
+ pool,
+ svn_xml_self_closing,
+ SVN_WC__LOG_READONLY,
+ SVN_WC__LOG_ATTR_NAME,
+ real_prop_base,
+ NULL);
+
   /* Write log entry to move working tmp copy to real working area. */
   svn_xml_make_open_tag (entry_accum,
                          pool,
@@ -629,6 +638,15 @@
                          SVN_WC__LOG_ATTR_NAME,
                          tmp_props,
                          SVN_WC__LOG_ATTR_DEST,
+ real_props,
+ NULL);
+
+ /* Make props readonly */
+ svn_xml_make_open_tag (entry_accum,
+ pool,
+ svn_xml_self_closing,
+ SVN_WC__LOG_READONLY,
+ SVN_WC__LOG_ATTR_NAME,
                          real_props,
                          NULL);
 
Index: ./subversion/libsvn_wc/copy.c
===================================================================
--- ./subversion/libsvn_wc/copy.c
+++ ./subversion/libsvn_wc/copy.c Thu Jan 31 12:55:54 2002
@@ -157,7 +157,7 @@
     }
 
   /* Now, make an actual copy of the working file. */
- SVN_ERR (svn_io_copy_file (src_path->data, dst_path->data, pool));
+ SVN_ERR (svn_io_copy_file (src_path->data, dst_path->data, TRUE, pool));
 
   /* Copy the pristine text-base over. Why? Because it's the *only*
      way we can detect any upcoming local mods on the copy.
@@ -188,17 +188,17 @@
     SVN_ERR (svn_wc__prop_base_path (&dst_bprop, dst_path, 0, pool));
 
     /* Copy the text-base over unconditionally. */
- SVN_ERR (svn_io_copy_file (src_txtb->data, dst_txtb->data, pool));
+ SVN_ERR (svn_io_copy_file (src_txtb->data, dst_txtb->data, TRUE, pool));
 
     /* Copy the props over if they exist. */
     SVN_ERR (svn_io_check_path (src_wprop, &kind, pool));
     if (kind == svn_node_file)
- SVN_ERR (svn_io_copy_file (src_wprop->data, dst_wprop->data, pool));
+ SVN_ERR (svn_io_copy_file (src_wprop->data, dst_wprop->data, TRUE, pool));
       
     /* Copy the base-props over if they exist */
     SVN_ERR (svn_io_check_path (src_bprop, &kind, pool));
     if (kind == svn_node_file)
- SVN_ERR (svn_io_copy_file (src_bprop->data, dst_bprop->data, pool));
+ SVN_ERR (svn_io_copy_file (src_bprop->data, dst_bprop->data, TRUE, pool));
   }
 
   /* Schedule the new file for addition in its parent, WITH HISTORY. */
@@ -261,7 +261,7 @@
       (This gets us all text-base, props, base-props, as well as entries,
       local mods, schedulings, existences, etc.) */
   SVN_ERR (svn_io_copy_dir_recursively (src_path, dst_parent, dst_basename,
- pool));
+ TRUE, pool));
 
   /* Remove all wcprops in the directory, because they're all bogus
      now. After the commit, ra_dav should regenerate them and
Index: ./subversion/libsvn_wc/wc.h
===================================================================
--- ./subversion/libsvn_wc/wc.h
+++ ./subversion/libsvn_wc/wc.h Sun Jan 27 22:20:14 2002
@@ -443,6 +443,9 @@
 /* Append file from SVN_WC__LOG_ATTR_NAME to SVN_WC__LOG_ATTR_DEST. */
 #define SVN_WC__LOG_APPEND "append"
 
+/* Make file SVN_WC__LOG_ATTR_NAME readonly */
+#define SVN_WC__LOG_READONLY "readonly"
+
 /* Handle closure after a commit completes successfully:
  *
  * If SVN/tmp/text-base/SVN_WC__LOG_ATTR_NAME exists, then
Index: ./subversion/libsvn_wc/adm_crawler.c
===================================================================
--- ./subversion/libsvn_wc/adm_crawler.c
+++ ./subversion/libsvn_wc/adm_crawler.c Thu Jan 31 12:55:55 2002
@@ -525,7 +525,8 @@
 
       SVN_ERR (svn_wc_translated_file (&tmp_wfile, entrypath, pool));
       tmp_text_base = svn_wc__text_base_path (entrypath, TRUE, pool);
- SVN_ERR (svn_io_copy_file (tmp_wfile->data, tmp_text_base->data, pool));
+ SVN_ERR (svn_io_copy_file (tmp_wfile->data, tmp_text_base->data, FALSE,
+ pool));
       if (tmp_wfile != entrypath)
         SVN_ERR (svn_io_remove_file (tmp_wfile->data, pool));
 
@@ -571,7 +572,8 @@
 
   /* Copy the local prop file to the administrative temp area */
   SVN_ERR (svn_wc__prop_path (&tmp_prop_path, path, 1, pool));
- SVN_ERR (svn_io_copy_file (prop_path->data, tmp_prop_path->data, pool));
+ SVN_ERR (svn_io_copy_file (prop_path->data, tmp_prop_path->data, FALSE,
+ pool));
 
   /* Load all properties into hashes */
   SVN_ERR (svn_wc__load_prop_file (tmp_prop_path->data, localprops, pool));
@@ -1768,7 +1770,7 @@
   tmp_text_base_path = svn_wc__text_base_path (file_path, TRUE, pool);
 
   SVN_ERR (svn_io_copy_file (text_base_path->data, tmp_text_base_path->data,
- pool));
+ FALSE, pool));
 
   SVN_ERR (svn_wc__get_eol_style (&eol_style, &eol,
                                   file_path->data, pool));
Index: ./subversion/libsvn_wc/log.c
===================================================================
--- ./subversion/libsvn_wc/log.c
+++ ./subversion/libsvn_wc/log.c Thu Jan 31 12:55:55 2002
@@ -194,7 +194,8 @@
                (&same, tmp_wfile, filepath, pool));
 
       if (! same)
- SVN_ERR (svn_io_copy_file (tmp_wfile->data, filepath->data, pool));
+ SVN_ERR (svn_io_copy_file (tmp_wfile->data, filepath->data, FALSE,
+ pool));
 
       SVN_ERR (svn_io_remove_file (tmp_wfile->data, pool));
 
@@ -384,6 +385,22 @@
   return SVN_NO_ERROR;
 }
 
+/* Make file NAME in log's CWD readonly */
+static svn_error_t *
+log_do_file_readonly (struct log_runner *loggy,
+ const char *name,
+ enum svn_wc__xfer_action action,
+ const XML_Char **atts)
+{
+ svn_stringbuf_t *full_path;
+
+ full_path = svn_stringbuf_dup (loggy->path, loggy->pool);
+ svn_path_add_component_nts (full_path, name);
+
+ SVN_ERR (svn_io_set_file_read_only (full_path->data, loggy->pool));
+
+ return SVN_NO_ERROR;
+}
 
 /* Remove file NAME in log's CWD. */
 static svn_error_t *
@@ -871,6 +888,9 @@
                                           "error renaming %s to %s",
                                           tmp_prop_path->data,
                                           prop_base_path->data);
+
+ SVN_ERR (svn_io_set_file_read_only (prop_base_path->data,
+ loggy->pool));
             }
           
 
@@ -1007,6 +1027,9 @@
   }
   else if (strcmp (eltname, SVN_WC__LOG_APPEND) == 0) {
     err = log_do_file_xfer (loggy, name, svn_wc__xfer_append, atts);
+ }
+ else if (strcmp (eltname, SVN_WC__LOG_READONLY) == 0) {
+ err = log_do_file_readonly (loggy, name, svn_wc__xfer_append, atts);
   }
   else
     {
Index: ./subversion/libsvn_wc/adm_ops.c
===================================================================
--- ./subversion/libsvn_wc/adm_ops.c
+++ ./subversion/libsvn_wc/adm_ops.c Thu Jan 31 18:11:53 2002
@@ -848,7 +848,7 @@
       SVN_ERR (svn_io_check_path (pthing, &kind, pool));
       if (kind == svn_node_file)
         {
- if ((err = svn_io_copy_file (pthing->data, thing->data, pool)))
+ if ((err = svn_io_copy_file (pthing->data, thing->data, FALSE, pool)))
             return revert_error (err, fullpath, "restoring props", pool);
           SVN_ERR (svn_io_file_affected_time (&tstamp, thing, pool));
           entry->prop_time = tstamp;
Index: ./subversion/libsvn_wc/adm_files.c
===================================================================
--- ./subversion/libsvn_wc/adm_files.c
+++ ./subversion/libsvn_wc/adm_files.c Sun Jan 27 22:18:53 2002
@@ -290,7 +290,7 @@
     }
   else /* SRC exists, so copy it to DST. */
     {
- err = svn_io_copy_file (src->data, dst->data, pool);
+ err = svn_io_copy_file (src->data, dst->data, FALSE, pool);
       if (err)
         return err;
     }
@@ -328,6 +328,8 @@
   
   /* Rename. */
   apr_err = apr_file_rename (tmp_path->data, path->data, pool);
+ if (APR_STATUS_IS_SUCCESS (apr_err))
+ SVN_ERR (svn_io_set_file_read_only (path->data, pool));
 
   /* Unconditionally restore path. */
   chop_admin_name (path, components_added);
@@ -681,6 +683,8 @@
       
       /* Rename. */
       apr_err = apr_file_rename (tmp_path->data, path->data, pool);
+ if (APR_STATUS_IS_SUCCESS(apr_err))
+ SVN_ERR (svn_io_set_file_read_only (path->data, pool));
       
       /* Unconditionally restore path. */
       chop_admin_name (path, components_added);
Index: ./subversion/libsvn_wc/get_editor.c
===================================================================
--- ./subversion/libsvn_wc/get_editor.c
+++ ./subversion/libsvn_wc/get_editor.c Wed Jan 30 18:14:55 2002
@@ -1907,7 +1907,16 @@
                                      NULL);
             }
         }
-
+
+ /* Make text-base readonly */
+ svn_xml_make_open_tag (&entry_accum,
+ fb->pool,
+ svn_xml_self_closing,
+ SVN_WC__LOG_READONLY,
+ SVN_WC__LOG_ATTR_NAME,
+ txtb,
+ NULL);
+
     } /* End of "textual" merging process */
   
 
Index: ./subversion/libsvn_wc/translate.c
===================================================================
--- ./subversion/libsvn_wc/translate.c
+++ ./subversion/libsvn_wc/translate.c Sun Jan 27 23:14:28 2002
@@ -420,7 +420,7 @@
                            apr_pool_t *pool)
 {
 #ifndef SVN_TRANSLATE
- return svn_io_copy_file (src, dst, pool);
+ return svn_io_copy_file (src, dst, FALSE, pool);
 #else /* ! SVN_TRANSLATE */
   apr_file_t *s = NULL, *d = NULL; /* init to null important for APR */
   apr_status_t apr_err;
@@ -437,7 +437,7 @@
   apr_size_t src_format_len = 0;
 
   if (! (eol_str || keywords))
- return svn_io_copy_file (src, dst, pool);
+ return svn_io_copy_file (src, dst, FALSE, pool);
 
   /* Open source file. */
   apr_err = apr_file_open (&s, src, APR_READ | APR_BUFFERED,
Index: ./subversion/libsvn_subr/io.c
===================================================================
--- ./subversion/libsvn_subr/io.c
+++ ./subversion/libsvn_subr/io.c Thu Jan 31 21:59:28 2002
@@ -176,159 +176,16 @@
 
 
 
-/*** Copying and appending files. ***/
-
-#ifndef apr_transfer_file_contents
-/**
- * copy or append one file to another
- * [This is a helper routine for apr_copy_file() and apr_append_file().]
- * @param from_path The full path to the source file (using / on all systems)
- * @param to_path The full path to the dest file (using / on all systems)
- * @flags the flags with which to open the dest file
- * @param pool The pool to use.
- * @tip The source file will be copied until EOF is reached, not until
- * its size at the time of opening is reached.
- * @tip The dest file will be created if it does not exist.
- */
-apr_status_t apr_transfer_file_contents (const char *src,
- const char *dst,
- apr_int32_t flags,
- apr_pool_t *pool);
-
-apr_status_t
-apr_transfer_file_contents (const char *src,
- const char *dst,
- apr_int32_t flags,
- apr_pool_t *pool)
-{
- apr_file_t *s = NULL, *d = NULL; /* init to null important for APR */
- apr_status_t apr_err;
- apr_status_t read_err, write_err;
- apr_finfo_t finfo;
- apr_fileperms_t perms;
- char buf[BUFSIZ];
-
- /* Open source file. */
- apr_err = apr_file_open (&s, src, APR_READ, APR_OS_DEFAULT, pool);
- if (apr_err)
- return apr_err;
-
- /* Get its size. */
- apr_err = apr_file_info_get (&finfo, APR_FINFO_MIN, s);
- if (apr_err)
- {
- apr_file_close (s); /* toss any error */
- return apr_err;
- }
- else
- perms = finfo.protection;
-
- /* Open dest file. */
- apr_err = apr_file_open (&d, dst, flags, perms, pool);
- if (apr_err)
- {
- apr_file_close (s); /* toss */
- return apr_err;
- }
-
- /* Copy bytes till the cows come home. */
- read_err = 0;
- while (!APR_STATUS_IS_EOF(read_err))
- {
- apr_size_t bytes_this_time = sizeof (buf);
-
- /* Read 'em. */
- read_err = apr_file_read (s, buf, &bytes_this_time);
- if (read_err && !APR_STATUS_IS_EOF(read_err))
- {
- apr_file_close (s); /* toss */
- apr_file_close (d); /* toss */
- return read_err;
- }
-
- /* Write 'em. */
- write_err = apr_file_write_full (d, buf, bytes_this_time, NULL);
- if (write_err)
- {
- apr_file_close (s); /* toss */
- apr_file_close (d);
- return write_err;
- }
-
- if (read_err && APR_STATUS_IS_EOF(read_err))
- {
- apr_err = apr_file_close (s);
- if (apr_err)
- {
- apr_file_close (d);
- return apr_err;
- }
-
- apr_err = apr_file_close (d);
- if (apr_err)
- return apr_err;
- }
- }
-
- return 0;
-}
-#endif /* apr_transfer_file_contents */
-
-
-#ifndef apr_copy_file
-/**
- * copy one file to another
- * @param from_path The full path to the source file (using / on all systems)
- * @param to_path The full path to the dest file (using / on all systems)
- * @param pool The pool to use.
- * @tip If a file exists at the new location, then it will be
- * overwritten, else it will be created.
- * @tip The source file will be copied until EOF is reached, not until
- * its size at the time of opening is reached.
- */
-apr_status_t
-apr_copy_file (const char *src, const char *dst, apr_pool_t *pool);
-
-apr_status_t
-apr_copy_file (const char *src, const char *dst, apr_pool_t *pool)
-{
- return apr_transfer_file_contents (src, dst,
- (APR_WRITE | APR_CREATE | APR_TRUNCATE),
- pool);
-}
-#endif /* apr_copy_file */
-
-
-#ifndef apr_append_file
-/**
- * append src file's onto dest file
- * @param from_path The full path to the source file (using / on all systems)
- * @param to_path The full path to the dest file (using / on all systems)
- * @param pool The pool to use.
- * @tip If a file exists at the new location, then it will be appended
- * to, else it will be created.
- * @tip The source file will be copied until EOF is reached, not until
- * its size at the time of opening is reached.
- */
-apr_status_t
-apr_append_file (const char *src, const char *dst, apr_pool_t *pool);
-
-apr_status_t
-apr_append_file (const char *src, const char *dst, apr_pool_t *pool)
-{
- return apr_transfer_file_contents (src, dst,
- (APR_WRITE | APR_APPEND | APR_CREATE),
- pool);
-}
-#endif /* apr_append_file */
-
-
 svn_error_t *
-svn_io_copy_file (const char *src, const char *dst, apr_pool_t *pool)
+svn_io_copy_file (const char *src,
+ const char *dst,
+ svn_boolean_t copy_perms,
+ apr_pool_t *pool)
 {
   apr_status_t apr_err;
+ apr_int32_t options = copy_perms ? APR_FILE_SOURCE_PERMS : APR_OS_DEFAULT;
 
- apr_err = apr_copy_file (src, dst, pool);
+ apr_err = apr_file_copy (src, dst, options, pool);
   if (apr_err)
     return svn_error_createf
       (apr_err, 0, NULL, pool, "svn_io_copy_file: copying %s to %s", src, dst);
@@ -342,7 +199,7 @@
 {
   apr_status_t apr_err;
 
- apr_err = apr_append_file (src->data, dst->data, pool);
+ apr_err = apr_file_append (src->data, dst->data, APR_OS_DEFAULT, pool);
   if (apr_err)
     {
       const char *msg
@@ -358,6 +215,7 @@
 svn_error_t *svn_io_copy_dir_recursively (svn_stringbuf_t *src,
                                           svn_stringbuf_t *dst_parent,
                                           svn_stringbuf_t *dst_basename,
+ svn_boolean_t copy_perms,
                                           apr_pool_t *pool)
 {
   enum svn_node_kind kind;
@@ -393,6 +251,7 @@
                               "'%s' already exists.", dst_path->data);
   
   /* Create the new directory. */
+ /* ### TODO: copy permissions? */
   status = apr_dir_make (dst_path->data, APR_OS_DEFAULT, pool);
   if (status)
     return svn_error_createf (status, 0, NULL, pool,
@@ -427,7 +286,7 @@
           /* Telescope and de-telescope the dst_target in here */
           svn_path_add_component_nts (dst_target, entryname);
           SVN_ERR (svn_io_copy_file (src_target->data, dst_target->data,
- subpool));
+ copy_perms, subpool));
           svn_path_remove_component (dst_target);
         }
 
@@ -437,6 +296,7 @@
                                               dst_target,
                                               svn_stringbuf_create (entryname,
                                                                     subpool),
+ copy_perms,
                                               subpool));
 
       /* ### someday deal with other node kinds? */
@@ -478,6 +338,23 @@
 
   return SVN_NO_ERROR;
 }
+
+
+/*** Permissions and modes. ***/
+
+svn_error_t *
+svn_io_set_file_read_only (const char *path, apr_pool_t *pool)
+{
+ apr_status_t status = apr_file_attrs_set (path, APR_FILE_ATTR_READONLY,
+ pool);
+ if (!APR_STATUS_IS_SUCCESS(status))
+ return svn_error_createf (status, 0, NULL, pool,
+ "failed to set file '%s' read-only", path);
+
+ return SVN_NO_ERROR;
+}
+
+
 
 
 

-- 
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:01 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.