Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2011-07-04 13:43:34 +0400
committerVicent Marti <tanoku@gmail.com>2011-07-05 04:04:03 +0400
commitf79026b4912bcd2336667f4c1663c06e233f0b32 (patch)
tree645b776032e924b587fad986aa3f3dc08c98d4c5 /src/path.c
parent678e9e045becdc5d75f2ce2259ed01c3531ee181 (diff)
fileops: Cleanup
Cleaned up the structure of the whole OS-abstraction layer. fileops.c now contains a set of utility methods for file management used by the library. These are abstractions on top of the original POSIX calls. There's a new file called `posix.c` that contains emulations/reimplementations of all the POSIX calls the library uses. These are prefixed with `p_`. There's a specific posix file for each platform (win32 and unix). All the path-related methods have been moved from `utils.c` to `path.c` and have their own prefix.
Diffstat (limited to 'src/path.c')
-rw-r--r--src/path.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/path.c b/src/path.c
new file mode 100644
index 000000000..766f67427
--- /dev/null
+++ b/src/path.c
@@ -0,0 +1,204 @@
+#include "common.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+/*
+ * Based on the Android implementation, BSD licensed.
+ * Check http://android.git.kernel.org/
+ */
+int git_path_basename_r(char *buffer, size_t bufflen, const char *path)
+{
+ const char *endp, *startp;
+ int len, result;
+
+ /* Empty or NULL string gets treated as "." */
+ if (path == NULL || *path == '\0') {
+ startp = ".";
+ len = 1;
+ goto Exit;
+ }
+
+ /* Strip trailing slashes */
+ endp = path + strlen(path) - 1;
+ while (endp > path && *endp == '/')
+ endp--;
+
+ /* All slashes becomes "/" */
+ if (endp == path && *endp == '/') {
+ startp = "/";
+ len = 1;
+ goto Exit;
+ }
+
+ /* Find the start of the base */
+ startp = endp;
+ while (startp > path && *(startp - 1) != '/')
+ startp--;
+
+ len = endp - startp +1;
+
+Exit:
+ result = len;
+ if (buffer == NULL) {
+ return result;
+ }
+ if (len > (int)bufflen-1) {
+ len = (int)bufflen-1;
+ result = GIT_ENOMEM;
+ }
+
+ if (len >= 0) {
+ memmove(buffer, startp, len);
+ buffer[len] = 0;
+ }
+ return result;
+}
+
+/*
+ * Based on the Android implementation, BSD licensed.
+ * Check http://android.git.kernel.org/
+ */
+int git_path_dirname_r(char *buffer, size_t bufflen, const char *path)
+{
+ const char *endp;
+ int result, len;
+
+ /* Empty or NULL string gets treated as "." */
+ if (path == NULL || *path == '\0') {
+ path = ".";
+ len = 1;
+ goto Exit;
+ }
+
+ /* Strip trailing slashes */
+ endp = path + strlen(path) - 1;
+ while (endp > path && *endp == '/')
+ endp--;
+
+ /* Find the start of the dir */
+ while (endp > path && *endp != '/')
+ endp--;
+
+ /* Either the dir is "/" or there are no slashes */
+ if (endp == path) {
+ path = (*endp == '/') ? "/" : ".";
+ len = 1;
+ goto Exit;
+ }
+
+ do {
+ endp--;
+ } while (endp > path && *endp == '/');
+
+ len = endp - path +1;
+
+Exit:
+ result = len;
+ if (len+1 > GIT_PATH_MAX) {
+ return GIT_ENOMEM;
+ }
+ if (buffer == NULL)
+ return result;
+
+ if (len > (int)bufflen-1) {
+ len = (int)bufflen-1;
+ result = GIT_ENOMEM;
+ }
+
+ if (len >= 0) {
+ memmove(buffer, path, len);
+ buffer[len] = 0;
+ }
+ return result;
+}
+
+
+char *git_path_dirname(const char *path)
+{
+ char *dname = NULL;
+ int len;
+
+ len = (path ? strlen(path) : 0) + 2;
+ dname = (char *)git__malloc(len);
+ if (dname == NULL)
+ return NULL;
+
+ if (git_path_dirname_r(dname, len, path) < GIT_SUCCESS) {
+ free(dname);
+ return NULL;
+ }
+
+ return dname;
+}
+
+char *git_path_basename(const char *path)
+{
+ char *bname = NULL;
+ int len;
+
+ len = (path ? strlen(path) : 0) + 2;
+ bname = (char *)git__malloc(len);
+ if (bname == NULL)
+ return NULL;
+
+ if (git_path_basename_r(bname, len, path) < GIT_SUCCESS) {
+ free(bname);
+ return NULL;
+ }
+
+ return bname;
+}
+
+
+const char *git_path_topdir(const char *path)
+{
+ size_t len;
+ int i;
+
+ assert(path);
+ len = strlen(path);
+
+ if (!len || path[len - 1] != '/')
+ return NULL;
+
+ for (i = len - 2; i >= 0; --i)
+ if (path[i] == '/')
+ break;
+
+ return &path[i + 1];
+}
+
+void git_path_join_n(char *buffer_out, int count, ...)
+{
+ va_list ap;
+ int i;
+ char *buffer_start = buffer_out;
+
+ va_start(ap, count);
+ for (i = 0; i < count; ++i) {
+ const char *path;
+ int len;
+
+ path = va_arg(ap, const char *);
+
+ assert((i == 0) || path != buffer_start);
+
+ if (i > 0 && *path == '/' && buffer_out > buffer_start && buffer_out[-1] == '/')
+ path++;
+
+ if (!*path)
+ continue;
+
+ len = strlen(path);
+ memmove(buffer_out, path, len);
+ buffer_out = buffer_out + len;
+
+ if (i < count - 1 && buffer_out[-1] != '/')
+ *buffer_out++ = '/';
+ }
+ va_end(ap);
+
+ *buffer_out = '\0';
+}
+