submodule-config: verify submodule names as paths
[gitweb.git] / strbuf.c
index de7a7c273095e4f5907260ddda50bef375381783..9103bc75e482c81bbb8f9d89c72de2935fefcddc 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -187,7 +187,7 @@ void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
 
 void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
 {
-       strbuf_splice(sb, pos, len, NULL, 0);
+       strbuf_splice(sb, pos, len, "", 0);
 }
 
 void strbuf_add(struct strbuf *sb, const void *data, size_t len)
@@ -197,11 +197,11 @@ void strbuf_add(struct strbuf *sb, const void *data, size_t len)
        strbuf_setlen(sb, sb->len + len);
 }
 
-void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
+void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2)
 {
-       strbuf_grow(sb, len);
-       memcpy(sb->buf + sb->len, sb->buf + pos, len);
-       strbuf_setlen(sb, sb->len + len);
+       strbuf_grow(sb, sb2->len);
+       memcpy(sb->buf + sb->len, sb2->buf, sb2->len);
+       strbuf_setlen(sb, sb->len + sb2->len);
 }
 
 void strbuf_addchars(struct strbuf *sb, int c, size_t n)
@@ -384,6 +384,23 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
        return sb->len - oldlen;
 }
 
+ssize_t strbuf_read_once(struct strbuf *sb, int fd, size_t hint)
+{
+       ssize_t cnt;
+
+       strbuf_grow(sb, hint ? hint : 8192);
+       cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
+       if (cnt > 0)
+               strbuf_setlen(sb, sb->len + cnt);
+       return cnt;
+}
+
+ssize_t strbuf_write(struct strbuf *sb, FILE *f)
+{
+       return sb->len ? fwrite(sb->buf, 1, sb->len, f) : 0;
+}
+
+
 #define STRBUF_MAXLINK (2*PATH_MAX)
 
 int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
@@ -425,6 +442,17 @@ int strbuf_getcwd(struct strbuf *sb)
                        strbuf_setlen(sb, strlen(sb->buf));
                        return 0;
                }
+
+               /*
+                * If getcwd(3) is implemented as a syscall that falls
+                * back to a regular lookup using readdir(3) etc. then
+                * we may be able to avoid EACCES by providing enough
+                * space to the syscall as it's not necessarily bound
+                * to the same restrictions as the fallback.
+                */
+               if (errno == EACCES && guessed_len < PATH_MAX)
+                       continue;
+
                if (errno != ERANGE)
                        break;
        }
@@ -470,9 +498,15 @@ int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
        if (errno == ENOMEM)
                die("Out of memory, getdelim failed");
 
-       /* Restore slopbuf that we moved out of the way before */
+       /*
+        * Restore strbuf invariants; if getdelim left us with a NULL pointer,
+        * we can just re-init, but otherwise we should make sure that our
+        * length is empty, and that the result is NUL-terminated.
+        */
        if (!sb->buf)
                strbuf_init(sb, 0);
+       else
+               strbuf_reset(sb);
        return EOF;
 }
 #else
@@ -501,15 +535,37 @@ int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
 }
 #endif
 
-int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
+static int strbuf_getdelim(struct strbuf *sb, FILE *fp, int term)
 {
        if (strbuf_getwholeline(sb, fp, term))
                return EOF;
-       if (sb->buf[sb->len-1] == term)
-               strbuf_setlen(sb, sb->len-1);
+       if (sb->buf[sb->len - 1] == term)
+               strbuf_setlen(sb, sb->len - 1);
        return 0;
 }
 
+int strbuf_getline(struct strbuf *sb, FILE *fp)
+{
+       if (strbuf_getwholeline(sb, fp, '\n'))
+               return EOF;
+       if (sb->buf[sb->len - 1] == '\n') {
+               strbuf_setlen(sb, sb->len - 1);
+               if (sb->len && sb->buf[sb->len - 1] == '\r')
+                       strbuf_setlen(sb, sb->len - 1);
+       }
+       return 0;
+}
+
+int strbuf_getline_lf(struct strbuf *sb, FILE *fp)
+{
+       return strbuf_getdelim(sb, fp, '\n');
+}
+
+int strbuf_getline_nul(struct strbuf *sb, FILE *fp)
+{
+       return strbuf_getdelim(sb, fp, '\0');
+}
+
 int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int term)
 {
        strbuf_reset(sb);
@@ -655,6 +711,17 @@ void strbuf_add_absolute_path(struct strbuf *sb, const char *path)
        strbuf_addstr(sb, path);
 }
 
+void strbuf_add_real_path(struct strbuf *sb, const char *path)
+{
+       if (sb->len) {
+               struct strbuf resolved = STRBUF_INIT;
+               strbuf_realpath(&resolved, path, 1);
+               strbuf_addbuf(sb, &resolved);
+               strbuf_release(&resolved);
+       } else
+               strbuf_realpath(sb, path, 1);
+}
+
 int printf_ln(const char *fmt, ...)
 {
        int ret;
@@ -818,3 +885,23 @@ void strbuf_stripspace(struct strbuf *sb, int skip_comments)
 
        strbuf_setlen(sb, j);
 }
+
+int strbuf_normalize_path(struct strbuf *src)
+{
+       struct strbuf dst = STRBUF_INIT;
+
+       strbuf_grow(&dst, src->len);
+       if (normalize_path_copy(dst.buf, src->buf) < 0) {
+               strbuf_release(&dst);
+               return -1;
+       }
+
+       /*
+        * normalize_path does not tell us the new length, so we have to
+        * compute it by looking for the new NUL it placed
+        */
+       strbuf_setlen(&dst, strlen(dst.buf));
+       strbuf_swap(src, &dst);
+       strbuf_release(&dst);
+       return 0;
+}