Change the format of the revprops block sent in svnserve for
[svn.git] / subversion / libsvn_fs_util / fs-util.c
blob704e598b7b2803152a57aa5481f2bf939f7659d3
1 /* fs-util.c : internal utility functions used by both FSFS and BDB back
2 * ends.
4 * ====================================================================
5 * Copyright (c) 2007 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
19 #include <string.h>
21 #include <apr_pools.h>
22 #include <apr_strings.h>
24 #include "svn_fs.h"
25 #include "svn_path.h"
26 #include "svn_private_config.h"
28 #include "private/svn_fs_util.h"
29 #include "../libsvn_fs/fs-loader.h"
31 const char *
32 svn_fs__canonicalize_abspath(const char *path, apr_pool_t *pool)
34 char *newpath;
35 int path_len;
36 int path_i = 0, newpath_i = 0;
37 svn_boolean_t eating_slashes = FALSE;
39 /* No PATH? No problem. */
40 if (! path)
41 return NULL;
43 /* Empty PATH? That's just "/". */
44 if (! *path)
45 return apr_pstrdup(pool, "/");
47 /* Now, the fun begins. Alloc enough room to hold PATH with an
48 added leading '/'. */
49 path_len = strlen(path);
50 newpath = apr_pcalloc(pool, path_len + 2);
52 /* No leading slash? Fix that. */
53 if (*path != '/')
55 newpath[newpath_i++] = '/';
58 for (path_i = 0; path_i < path_len; path_i++)
60 if (path[path_i] == '/')
62 /* The current character is a '/'. If we are eating up
63 extra '/' characters, skip this character. Else, note
64 that we are now eating slashes. */
65 if (eating_slashes)
66 continue;
67 eating_slashes = TRUE;
69 else
71 /* The current character is NOT a '/'. If we were eating
72 slashes, we need not do that any more. */
73 if (eating_slashes)
74 eating_slashes = FALSE;
77 /* Copy the current character into our new buffer. */
78 newpath[newpath_i++] = path[path_i];
81 /* Did we leave a '/' attached to the end of NEWPATH (other than in
82 the root directory case)? */
83 if ((newpath[newpath_i - 1] == '/') && (newpath_i > 1))
84 newpath[newpath_i - 1] = '\0';
86 return newpath;
89 svn_error_t *
90 svn_fs__check_fs(svn_fs_t *fs,
91 svn_boolean_t expect_open)
93 if ((expect_open && fs->fsap_data)
94 || ((! expect_open) && (! fs->fsap_data)))
95 return SVN_NO_ERROR;
96 if (expect_open)
97 return svn_error_create(SVN_ERR_FS_NOT_OPEN, 0,
98 _("Filesystem object has not been opened yet"));
99 else
100 return svn_error_create(SVN_ERR_FS_ALREADY_OPEN, 0,
101 _("Filesystem object already open"));
104 char *
105 svn_fs__next_entry_name(const char **next_p,
106 const char *path,
107 apr_pool_t *pool)
109 const char *end;
111 /* Find the end of the current component. */
112 end = strchr(path, '/');
114 if (! end)
116 /* The path contains only one component, with no trailing
117 slashes. */
118 *next_p = 0;
119 return apr_pstrdup(pool, path);
121 else
123 /* There's a slash after the first component. Skip over an arbitrary
124 number of slashes to find the next one. */
125 const char *next = end;
126 while (*next == '/')
127 next++;
128 *next_p = next;
129 return apr_pstrndup(pool, path, end - path);