Coverage Report

Created: 2023-11-27 06:56

/src/git/path.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Utilities for paths and pathnames
3
 */
4
#include "git-compat-util.h"
5
#include "abspath.h"
6
#include "environment.h"
7
#include "gettext.h"
8
#include "hex.h"
9
#include "repository.h"
10
#include "strbuf.h"
11
#include "string-list.h"
12
#include "dir.h"
13
#include "worktree.h"
14
#include "setup.h"
15
#include "submodule-config.h"
16
#include "path.h"
17
#include "packfile.h"
18
#include "object-store-ll.h"
19
#include "lockfile.h"
20
#include "exec-cmd.h"
21
22
static int get_st_mode_bits(const char *path, int *mode)
23
0
{
24
0
  struct stat st;
25
0
  if (lstat(path, &st) < 0)
26
0
    return -1;
27
0
  *mode = st.st_mode;
28
0
  return 0;
29
0
}
30
31
static char bad_path[] = "/bad-path/";
32
33
static struct strbuf *get_pathname(void)
34
6.37k
{
35
6.37k
  static struct strbuf pathname_array[4] = {
36
6.37k
    STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
37
6.37k
  };
38
6.37k
  static int index;
39
6.37k
  struct strbuf *sb = &pathname_array[index];
40
6.37k
  index = (index + 1) % ARRAY_SIZE(pathname_array);
41
6.37k
  strbuf_reset(sb);
42
6.37k
  return sb;
43
6.37k
}
44
45
static const char *cleanup_path(const char *path)
46
129k
{
47
  /* Clean it up */
48
129k
  if (skip_prefix(path, "./", &path)) {
49
0
    while (*path == '/')
50
0
      path++;
51
0
  }
52
129k
  return path;
53
129k
}
54
55
static void strbuf_cleanup_path(struct strbuf *sb)
56
129k
{
57
129k
  const char *path = cleanup_path(sb->buf);
58
129k
  if (path > sb->buf)
59
0
    strbuf_remove(sb, 0, path - sb->buf);
60
129k
}
61
62
char *mksnpath(char *buf, size_t n, const char *fmt, ...)
63
0
{
64
0
  va_list args;
65
0
  unsigned len;
66
67
0
  va_start(args, fmt);
68
0
  len = vsnprintf(buf, n, fmt, args);
69
0
  va_end(args);
70
0
  if (len >= n) {
71
0
    strlcpy(buf, bad_path, n);
72
0
    return buf;
73
0
  }
74
0
  return (char *)cleanup_path(buf);
75
0
}
76
77
static int dir_prefix(const char *buf, const char *dir)
78
81.1k
{
79
81.1k
  int len = strlen(dir);
80
81.1k
  return !strncmp(buf, dir, len) &&
81
81.1k
    (is_dir_sep(buf[len]) || buf[len] == '\0');
82
81.1k
}
83
84
/* $buf =~ m|$dir/+$file| but without regex */
85
static int is_dir_file(const char *buf, const char *dir, const char *file)
86
81.1k
{
87
81.1k
  int len = strlen(dir);
88
81.1k
  if (strncmp(buf, dir, len) || !is_dir_sep(buf[len]))
89
81.1k
    return 0;
90
4
  while (is_dir_sep(buf[len]))
91
2
    len++;
92
2
  return !strcmp(buf + len, file);
93
81.1k
}
94
95
static void replace_dir(struct strbuf *buf, int len, const char *newdir)
96
0
{
97
0
  int newlen = strlen(newdir);
98
0
  int need_sep = (buf->buf[len] && !is_dir_sep(buf->buf[len])) &&
99
0
    !is_dir_sep(newdir[newlen - 1]);
100
0
  if (need_sep)
101
0
    len--;  /* keep one char, to be replaced with '/'  */
102
0
  strbuf_splice(buf, 0, len, newdir, newlen);
103
0
  if (need_sep)
104
0
    buf->buf[newlen] = '/';
105
0
}
106
107
struct common_dir {
108
  /* Not considered garbage for report_linked_checkout_garbage */
109
  unsigned ignore_garbage:1;
110
  unsigned is_dir:1;
111
  /* Belongs to the common dir, though it may contain paths that don't */
112
  unsigned is_common:1;
113
  const char *path;
114
};
115
116
static struct common_dir common_list[] = {
117
  { 0, 1, 1, "branches" },
118
  { 0, 1, 1, "common" },
119
  { 0, 1, 1, "hooks" },
120
  { 0, 1, 1, "info" },
121
  { 0, 0, 0, "info/sparse-checkout" },
122
  { 1, 1, 1, "logs" },
123
  { 1, 0, 0, "logs/HEAD" },
124
  { 0, 1, 0, "logs/refs/bisect" },
125
  { 0, 1, 0, "logs/refs/rewritten" },
126
  { 0, 1, 0, "logs/refs/worktree" },
127
  { 0, 1, 1, "lost-found" },
128
  { 0, 1, 1, "objects" },
129
  { 0, 1, 1, "refs" },
130
  { 0, 1, 0, "refs/bisect" },
131
  { 0, 1, 0, "refs/rewritten" },
132
  { 0, 1, 0, "refs/worktree" },
133
  { 0, 1, 1, "remotes" },
134
  { 0, 1, 1, "worktrees" },
135
  { 0, 1, 1, "rr-cache" },
136
  { 0, 1, 1, "svn" },
137
  { 0, 0, 1, "config" },
138
  { 1, 0, 1, "gc.pid" },
139
  { 0, 0, 1, "packed-refs" },
140
  { 0, 0, 1, "shallow" },
141
  { 0, 0, 0, NULL }
142
};
143
144
/*
145
 * A compressed trie.  A trie node consists of zero or more characters that
146
 * are common to all elements with this prefix, optionally followed by some
147
 * children.  If value is not NULL, the trie node is a terminal node.
148
 *
149
 * For example, consider the following set of strings:
150
 * abc
151
 * def
152
 * definite
153
 * definition
154
 *
155
 * The trie would look like:
156
 * root: len = 0, children a and d non-NULL, value = NULL.
157
 *    a: len = 2, contents = bc, value = (data for "abc")
158
 *    d: len = 2, contents = ef, children i non-NULL, value = (data for "def")
159
 *       i: len = 3, contents = nit, children e and i non-NULL, value = NULL
160
 *           e: len = 0, children all NULL, value = (data for "definite")
161
 *           i: len = 2, contents = on, children all NULL,
162
 *              value = (data for "definition")
163
 */
164
struct trie {
165
  struct trie *children[256];
166
  int len;
167
  char *contents;
168
  void *value;
169
};
170
171
static struct trie *make_trie_node(const char *key, void *value)
172
0
{
173
0
  struct trie *new_node = xcalloc(1, sizeof(*new_node));
174
0
  new_node->len = strlen(key);
175
0
  if (new_node->len) {
176
0
    new_node->contents = xmalloc(new_node->len);
177
0
    memcpy(new_node->contents, key, new_node->len);
178
0
  }
179
0
  new_node->value = value;
180
0
  return new_node;
181
0
}
182
183
/*
184
 * Add a key/value pair to a trie.  The key is assumed to be \0-terminated.
185
 * If there was an existing value for this key, return it.
186
 */
187
static void *add_to_trie(struct trie *root, const char *key, void *value)
188
0
{
189
0
  struct trie *child;
190
0
  void *old;
191
0
  int i;
192
193
0
  if (!*key) {
194
    /* we have reached the end of the key */
195
0
    old = root->value;
196
0
    root->value = value;
197
0
    return old;
198
0
  }
199
200
0
  for (i = 0; i < root->len; i++) {
201
0
    if (root->contents[i] == key[i])
202
0
      continue;
203
204
    /*
205
     * Split this node: child will contain this node's
206
     * existing children.
207
     */
208
0
    child = xmalloc(sizeof(*child));
209
0
    memcpy(child->children, root->children, sizeof(root->children));
210
211
0
    child->len = root->len - i - 1;
212
0
    if (child->len) {
213
0
      child->contents = xstrndup(root->contents + i + 1,
214
0
               child->len);
215
0
    }
216
0
    child->value = root->value;
217
0
    root->value = NULL;
218
0
    root->len = i;
219
220
0
    memset(root->children, 0, sizeof(root->children));
221
0
    root->children[(unsigned char)root->contents[i]] = child;
222
223
    /* This is the newly-added child. */
224
0
    root->children[(unsigned char)key[i]] =
225
0
      make_trie_node(key + i + 1, value);
226
0
    return NULL;
227
0
  }
228
229
  /* We have matched the entire compressed section */
230
0
  if (key[i]) {
231
0
    child = root->children[(unsigned char)key[root->len]];
232
0
    if (child) {
233
0
      return add_to_trie(child, key + root->len + 1, value);
234
0
    } else {
235
0
      child = make_trie_node(key + root->len + 1, value);
236
0
      root->children[(unsigned char)key[root->len]] = child;
237
0
      return NULL;
238
0
    }
239
0
  }
240
241
0
  old = root->value;
242
0
  root->value = value;
243
0
  return old;
244
0
}
245
246
typedef int (*match_fn)(const char *unmatched, void *value, void *baton);
247
248
/*
249
 * Search a trie for some key.  Find the longest /-or-\0-terminated
250
 * prefix of the key for which the trie contains a value.  If there is
251
 * no such prefix, return -1.  Otherwise call fn with the unmatched
252
 * portion of the key and the found value.  If fn returns 0 or
253
 * positive, then return its return value.  If fn returns negative,
254
 * then call fn with the next-longest /-terminated prefix of the key
255
 * (i.e. a parent directory) for which the trie contains a value, and
256
 * handle its return value the same way.  If there is no shorter
257
 * /-terminated prefix with a value left, then return the negative
258
 * return value of the most recent fn invocation.
259
 *
260
 * The key is partially normalized: consecutive slashes are skipped.
261
 *
262
 * For example, consider the trie containing only [logs,
263
 * logs/refs/bisect], both with values, but not logs/refs.
264
 *
265
 * | key                | unmatched      | prefix to node   | return value |
266
 * |--------------------|----------------|------------------|--------------|
267
 * | a                  | not called     | n/a              | -1           |
268
 * | logstore           | not called     | n/a              | -1           |
269
 * | logs               | \0             | logs             | as per fn    |
270
 * | logs/              | /              | logs             | as per fn    |
271
 * | logs/refs          | /refs          | logs             | as per fn    |
272
 * | logs/refs/         | /refs/         | logs             | as per fn    |
273
 * | logs/refs/b        | /refs/b        | logs             | as per fn    |
274
 * | logs/refs/bisected | /refs/bisected | logs             | as per fn    |
275
 * | logs/refs/bisect   | \0             | logs/refs/bisect | as per fn    |
276
 * | logs/refs/bisect/  | /              | logs/refs/bisect | as per fn    |
277
 * | logs/refs/bisect/a | /a             | logs/refs/bisect | as per fn    |
278
 * | (If fn in the previous line returns -1, then fn is called once more:) |
279
 * | logs/refs/bisect/a | /refs/bisect/a | logs             | as per fn    |
280
 * |--------------------|----------------|------------------|--------------|
281
 */
282
static int trie_find(struct trie *root, const char *key, match_fn fn,
283
         void *baton)
284
0
{
285
0
  int i;
286
0
  int result;
287
0
  struct trie *child;
288
289
0
  if (!*key) {
290
    /* we have reached the end of the key */
291
0
    if (root->value && !root->len)
292
0
      return fn(key, root->value, baton);
293
0
    else
294
0
      return -1;
295
0
  }
296
297
0
  for (i = 0; i < root->len; i++) {
298
    /* Partial path normalization: skip consecutive slashes. */
299
0
    if (key[i] == '/' && key[i+1] == '/') {
300
0
      key++;
301
0
      continue;
302
0
    }
303
0
    if (root->contents[i] != key[i])
304
0
      return -1;
305
0
  }
306
307
  /* Matched the entire compressed section */
308
0
  key += i;
309
0
  if (!*key) {
310
    /* End of key */
311
0
    if (root->value)
312
0
      return fn(key, root->value, baton);
313
0
    else
314
0
      return -1;
315
0
  }
316
317
  /* Partial path normalization: skip consecutive slashes */
318
0
  while (key[0] == '/' && key[1] == '/')
319
0
    key++;
320
321
0
  child = root->children[(unsigned char)*key];
322
0
  if (child)
323
0
    result = trie_find(child, key + 1, fn, baton);
324
0
  else
325
0
    result = -1;
326
327
0
  if (result >= 0 || (*key != '/' && *key != 0))
328
0
    return result;
329
0
  if (root->value)
330
0
    return fn(key, root->value, baton);
331
0
  else
332
0
    return -1;
333
0
}
334
335
static struct trie common_trie;
336
static int common_trie_done_setup;
337
338
static void init_common_trie(void)
339
0
{
340
0
  struct common_dir *p;
341
342
0
  if (common_trie_done_setup)
343
0
    return;
344
345
0
  for (p = common_list; p->path; p++)
346
0
    add_to_trie(&common_trie, p->path, p);
347
348
0
  common_trie_done_setup = 1;
349
0
}
350
351
/*
352
 * Helper function for update_common_dir: returns 1 if the dir
353
 * prefix is common.
354
 */
355
static int check_common(const char *unmatched, void *value,
356
      void *baton UNUSED)
357
0
{
358
0
  struct common_dir *dir = value;
359
360
0
  if (dir->is_dir && (unmatched[0] == 0 || unmatched[0] == '/'))
361
0
    return dir->is_common;
362
363
0
  if (!dir->is_dir && unmatched[0] == 0)
364
0
    return dir->is_common;
365
366
0
  return 0;
367
0
}
368
369
static void update_common_dir(struct strbuf *buf, int git_dir_len,
370
            const char *common_dir)
371
0
{
372
0
  char *base = buf->buf + git_dir_len;
373
0
  int has_lock_suffix = strbuf_strip_suffix(buf, LOCK_SUFFIX);
374
375
0
  init_common_trie();
376
0
  if (trie_find(&common_trie, base, check_common, NULL) > 0)
377
0
    replace_dir(buf, git_dir_len, common_dir);
378
379
0
  if (has_lock_suffix)
380
0
    strbuf_addstr(buf, LOCK_SUFFIX);
381
0
}
382
383
void report_linked_checkout_garbage(void)
384
0
{
385
0
  struct strbuf sb = STRBUF_INIT;
386
0
  const struct common_dir *p;
387
0
  int len;
388
389
0
  if (!the_repository->different_commondir)
390
0
    return;
391
0
  strbuf_addf(&sb, "%s/", get_git_dir());
392
0
  len = sb.len;
393
0
  for (p = common_list; p->path; p++) {
394
0
    const char *path = p->path;
395
0
    if (p->ignore_garbage)
396
0
      continue;
397
0
    strbuf_setlen(&sb, len);
398
0
    strbuf_addstr(&sb, path);
399
0
    if (file_exists(sb.buf))
400
0
      report_garbage(PACKDIR_FILE_GARBAGE, sb.buf);
401
0
  }
402
0
  strbuf_release(&sb);
403
0
}
404
405
static void adjust_git_path(const struct repository *repo,
406
          struct strbuf *buf, int git_dir_len)
407
81.1k
{
408
81.1k
  const char *base = buf->buf + git_dir_len;
409
81.1k
  if (is_dir_file(base, "info", "grafts"))
410
0
    strbuf_splice(buf, 0, buf->len,
411
0
            repo->graft_file, strlen(repo->graft_file));
412
81.1k
  else if (!strcmp(base, "index"))
413
0
    strbuf_splice(buf, 0, buf->len,
414
0
            repo->index_file, strlen(repo->index_file));
415
81.1k
  else if (dir_prefix(base, "objects"))
416
0
    replace_dir(buf, git_dir_len + 7, repo->objects->odb->path);
417
81.1k
  else if (git_hooks_path && dir_prefix(base, "hooks"))
418
0
    replace_dir(buf, git_dir_len + 5, git_hooks_path);
419
81.1k
  else if (repo->different_commondir)
420
0
    update_common_dir(buf, git_dir_len, repo->commondir);
421
81.1k
}
422
423
static void strbuf_worktree_gitdir(struct strbuf *buf,
424
           const struct repository *repo,
425
           const struct worktree *wt)
426
81.1k
{
427
81.1k
  if (!wt)
428
81.1k
    strbuf_addstr(buf, repo->gitdir);
429
0
  else if (!wt->id)
430
0
    strbuf_addstr(buf, repo->commondir);
431
0
  else
432
0
    strbuf_git_common_path(buf, repo, "worktrees/%s", wt->id);
433
81.1k
}
434
435
static void do_git_path(const struct repository *repo,
436
      const struct worktree *wt, struct strbuf *buf,
437
      const char *fmt, va_list args)
438
81.1k
{
439
81.1k
  int gitdir_len;
440
81.1k
  strbuf_worktree_gitdir(buf, repo, wt);
441
81.1k
  if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
442
81.1k
    strbuf_addch(buf, '/');
443
81.1k
  gitdir_len = buf->len;
444
81.1k
  strbuf_vaddf(buf, fmt, args);
445
81.1k
  if (!wt)
446
81.1k
    adjust_git_path(repo, buf, gitdir_len);
447
81.1k
  strbuf_cleanup_path(buf);
448
81.1k
}
449
450
char *repo_git_path(const struct repository *repo,
451
        const char *fmt, ...)
452
8.54k
{
453
8.54k
  struct strbuf path = STRBUF_INIT;
454
8.54k
  va_list args;
455
8.54k
  va_start(args, fmt);
456
8.54k
  do_git_path(repo, NULL, &path, fmt, args);
457
8.54k
  va_end(args);
458
8.54k
  return strbuf_detach(&path, NULL);
459
8.54k
}
460
461
void strbuf_repo_git_path(struct strbuf *sb,
462
        const struct repository *repo,
463
        const char *fmt, ...)
464
0
{
465
0
  va_list args;
466
0
  va_start(args, fmt);
467
0
  do_git_path(repo, NULL, sb, fmt, args);
468
0
  va_end(args);
469
0
}
470
471
char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
472
4.88k
{
473
4.88k
  va_list args;
474
4.88k
  strbuf_reset(buf);
475
4.88k
  va_start(args, fmt);
476
4.88k
  do_git_path(the_repository, NULL, buf, fmt, args);
477
4.88k
  va_end(args);
478
4.88k
  return buf->buf;
479
4.88k
}
480
481
void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
482
61.3k
{
483
61.3k
  va_list args;
484
61.3k
  va_start(args, fmt);
485
61.3k
  do_git_path(the_repository, NULL, sb, fmt, args);
486
61.3k
  va_end(args);
487
61.3k
}
488
489
const char *git_path(const char *fmt, ...)
490
6.10k
{
491
6.10k
  struct strbuf *pathname = get_pathname();
492
6.10k
  va_list args;
493
6.10k
  va_start(args, fmt);
494
6.10k
  do_git_path(the_repository, NULL, pathname, fmt, args);
495
6.10k
  va_end(args);
496
6.10k
  return pathname->buf;
497
6.10k
}
498
499
char *git_pathdup(const char *fmt, ...)
500
5
{
501
5
  struct strbuf path = STRBUF_INIT;
502
5
  va_list args;
503
5
  va_start(args, fmt);
504
5
  do_git_path(the_repository, NULL, &path, fmt, args);
505
5
  va_end(args);
506
5
  return strbuf_detach(&path, NULL);
507
5
}
508
509
char *mkpathdup(const char *fmt, ...)
510
48.0k
{
511
48.0k
  struct strbuf sb = STRBUF_INIT;
512
48.0k
  va_list args;
513
48.0k
  va_start(args, fmt);
514
48.0k
  strbuf_vaddf(&sb, fmt, args);
515
48.0k
  va_end(args);
516
48.0k
  strbuf_cleanup_path(&sb);
517
48.0k
  return strbuf_detach(&sb, NULL);
518
48.0k
}
519
520
const char *mkpath(const char *fmt, ...)
521
0
{
522
0
  va_list args;
523
0
  struct strbuf *pathname = get_pathname();
524
0
  va_start(args, fmt);
525
0
  strbuf_vaddf(pathname, fmt, args);
526
0
  va_end(args);
527
0
  return cleanup_path(pathname->buf);
528
0
}
529
530
const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)
531
267
{
532
267
  struct strbuf *pathname = get_pathname();
533
267
  va_list args;
534
267
  va_start(args, fmt);
535
267
  do_git_path(the_repository, wt, pathname, fmt, args);
536
267
  va_end(args);
537
267
  return pathname->buf;
538
267
}
539
540
static void do_worktree_path(const struct repository *repo,
541
           struct strbuf *buf,
542
           const char *fmt, va_list args)
543
0
{
544
0
  strbuf_addstr(buf, repo->worktree);
545
0
  if(buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
546
0
    strbuf_addch(buf, '/');
547
548
0
  strbuf_vaddf(buf, fmt, args);
549
0
  strbuf_cleanup_path(buf);
550
0
}
551
552
char *repo_worktree_path(const struct repository *repo, const char *fmt, ...)
553
0
{
554
0
  struct strbuf path = STRBUF_INIT;
555
0
  va_list args;
556
557
0
  if (!repo->worktree)
558
0
    return NULL;
559
560
0
  va_start(args, fmt);
561
0
  do_worktree_path(repo, &path, fmt, args);
562
0
  va_end(args);
563
564
0
  return strbuf_detach(&path, NULL);
565
0
}
566
567
void strbuf_repo_worktree_path(struct strbuf *sb,
568
             const struct repository *repo,
569
             const char *fmt, ...)
570
0
{
571
0
  va_list args;
572
573
0
  if (!repo->worktree)
574
0
    return;
575
576
0
  va_start(args, fmt);
577
0
  do_worktree_path(repo, sb, fmt, args);
578
0
  va_end(args);
579
0
}
580
581
/* Returns 0 on success, negative on failure. */
582
static int do_submodule_path(struct strbuf *buf, const char *path,
583
           const char *fmt, va_list args)
584
0
{
585
0
  struct strbuf git_submodule_common_dir = STRBUF_INIT;
586
0
  struct strbuf git_submodule_dir = STRBUF_INIT;
587
0
  int ret;
588
589
0
  ret = submodule_to_gitdir(&git_submodule_dir, path);
590
0
  if (ret)
591
0
    goto cleanup;
592
593
0
  strbuf_complete(&git_submodule_dir, '/');
594
0
  strbuf_addbuf(buf, &git_submodule_dir);
595
0
  strbuf_vaddf(buf, fmt, args);
596
597
0
  if (get_common_dir_noenv(&git_submodule_common_dir, git_submodule_dir.buf))
598
0
    update_common_dir(buf, git_submodule_dir.len, git_submodule_common_dir.buf);
599
600
0
  strbuf_cleanup_path(buf);
601
602
0
cleanup:
603
0
  strbuf_release(&git_submodule_dir);
604
0
  strbuf_release(&git_submodule_common_dir);
605
0
  return ret;
606
0
}
607
608
char *git_pathdup_submodule(const char *path, const char *fmt, ...)
609
0
{
610
0
  int err;
611
0
  va_list args;
612
0
  struct strbuf buf = STRBUF_INIT;
613
0
  va_start(args, fmt);
614
0
  err = do_submodule_path(&buf, path, fmt, args);
615
0
  va_end(args);
616
0
  if (err) {
617
0
    strbuf_release(&buf);
618
0
    return NULL;
619
0
  }
620
0
  return strbuf_detach(&buf, NULL);
621
0
}
622
623
int strbuf_git_path_submodule(struct strbuf *buf, const char *path,
624
            const char *fmt, ...)
625
0
{
626
0
  int err;
627
0
  va_list args;
628
0
  va_start(args, fmt);
629
0
  err = do_submodule_path(buf, path, fmt, args);
630
0
  va_end(args);
631
632
0
  return err;
633
0
}
634
635
static void do_git_common_path(const struct repository *repo,
636
             struct strbuf *buf,
637
             const char *fmt,
638
             va_list args)
639
0
{
640
0
  strbuf_addstr(buf, repo->commondir);
641
0
  if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
642
0
    strbuf_addch(buf, '/');
643
0
  strbuf_vaddf(buf, fmt, args);
644
0
  strbuf_cleanup_path(buf);
645
0
}
646
647
const char *git_common_path(const char *fmt, ...)
648
0
{
649
0
  struct strbuf *pathname = get_pathname();
650
0
  va_list args;
651
0
  va_start(args, fmt);
652
0
  do_git_common_path(the_repository, pathname, fmt, args);
653
0
  va_end(args);
654
0
  return pathname->buf;
655
0
}
656
657
void strbuf_git_common_path(struct strbuf *sb,
658
          const struct repository *repo,
659
          const char *fmt, ...)
660
0
{
661
0
  va_list args;
662
0
  va_start(args, fmt);
663
0
  do_git_common_path(repo, sb, fmt, args);
664
0
  va_end(args);
665
0
}
666
667
int validate_headref(const char *path)
668
11.4k
{
669
11.4k
  struct stat st;
670
11.4k
  char buffer[256];
671
11.4k
  const char *refname;
672
11.4k
  struct object_id oid;
673
11.4k
  int fd;
674
11.4k
  ssize_t len;
675
676
11.4k
  if (lstat(path, &st) < 0)
677
1.24k
    return -1;
678
679
  /* Make sure it is a "refs/.." symlink */
680
10.1k
  if (S_ISLNK(st.st_mode)) {
681
0
    len = readlink(path, buffer, sizeof(buffer)-1);
682
0
    if (len >= 5 && !memcmp("refs/", buffer, 5))
683
0
      return 0;
684
0
    return -1;
685
0
  }
686
687
  /*
688
   * Anything else, just open it and try to see if it is a symbolic ref.
689
   */
690
10.1k
  fd = open(path, O_RDONLY);
691
10.1k
  if (fd < 0)
692
0
    return -1;
693
10.1k
  len = read_in_full(fd, buffer, sizeof(buffer)-1);
694
10.1k
  close(fd);
695
696
10.1k
  if (len < 0)
697
0
    return -1;
698
10.1k
  buffer[len] = '\0';
699
700
  /*
701
   * Is it a symbolic ref?
702
   */
703
10.1k
  if (skip_prefix(buffer, "ref:", &refname)) {
704
10.1k
    while (isspace(*refname))
705
10.1k
      refname++;
706
10.1k
    if (starts_with(refname, "refs/"))
707
10.1k
      return 0;
708
10.1k
  }
709
710
  /*
711
   * Is this a detached HEAD?
712
   */
713
0
  if (!get_oid_hex(buffer, &oid))
714
0
    return 0;
715
716
0
  return -1;
717
0
}
718
719
static struct passwd *getpw_str(const char *username, size_t len)
720
0
{
721
0
  struct passwd *pw;
722
0
  char *username_z = xmemdupz(username, len);
723
0
  pw = getpwnam(username_z);
724
0
  free(username_z);
725
0
  return pw;
726
0
}
727
728
/*
729
 * Return a string with ~ and ~user expanded via getpw*. Returns NULL on getpw
730
 * failure or if path is NULL.
731
 *
732
 * If real_home is true, strbuf_realpath($HOME) is used in the `~/` expansion.
733
 *
734
 * If the path starts with `%(prefix)/`, the remainder is interpreted as
735
 * relative to where Git is installed, and expanded to the absolute path.
736
 */
737
char *interpolate_path(const char *path, int real_home)
738
0
{
739
0
  struct strbuf user_path = STRBUF_INIT;
740
0
  const char *to_copy = path;
741
742
0
  if (!path)
743
0
    goto return_null;
744
745
0
  if (skip_prefix(path, "%(prefix)/", &path))
746
0
    return system_path(path);
747
748
0
  if (path[0] == '~') {
749
0
    const char *first_slash = strchrnul(path, '/');
750
0
    const char *username = path + 1;
751
0
    size_t username_len = first_slash - username;
752
0
    if (username_len == 0) {
753
0
      const char *home = getenv("HOME");
754
0
      if (!home)
755
0
        goto return_null;
756
0
      if (real_home)
757
0
        strbuf_add_real_path(&user_path, home);
758
0
      else
759
0
        strbuf_addstr(&user_path, home);
760
#ifdef GIT_WINDOWS_NATIVE
761
      convert_slashes(user_path.buf);
762
#endif
763
0
    } else {
764
0
      struct passwd *pw = getpw_str(username, username_len);
765
0
      if (!pw)
766
0
        goto return_null;
767
0
      strbuf_addstr(&user_path, pw->pw_dir);
768
0
    }
769
0
    to_copy = first_slash;
770
0
  }
771
0
  strbuf_addstr(&user_path, to_copy);
772
0
  return strbuf_detach(&user_path, NULL);
773
0
return_null:
774
0
  strbuf_release(&user_path);
775
0
  return NULL;
776
0
}
777
778
/*
779
 * First, one directory to try is determined by the following algorithm.
780
 *
781
 * (0) If "strict" is given, the path is used as given and no DWIM is
782
 *     done. Otherwise:
783
 * (1) "~/path" to mean path under the running user's home directory;
784
 * (2) "~user/path" to mean path under named user's home directory;
785
 * (3) "relative/path" to mean cwd relative directory; or
786
 * (4) "/absolute/path" to mean absolute directory.
787
 *
788
 * Unless "strict" is given, we check "%s/.git", "%s", "%s.git/.git", "%s.git"
789
 * in this order. We select the first one that is a valid git repository, and
790
 * chdir() to it. If none match, or we fail to chdir, we return NULL.
791
 *
792
 * If all goes well, we return the directory we used to chdir() (but
793
 * before ~user is expanded), avoiding getcwd() resolving symbolic
794
 * links.  User relative paths are also returned as they are given,
795
 * except DWIM suffixing.
796
 */
797
const char *enter_repo(const char *path, int strict)
798
0
{
799
0
  static struct strbuf validated_path = STRBUF_INIT;
800
0
  static struct strbuf used_path = STRBUF_INIT;
801
802
0
  if (!path)
803
0
    return NULL;
804
805
0
  if (!strict) {
806
0
    static const char *suffix[] = {
807
0
      "/.git", "", ".git/.git", ".git", NULL,
808
0
    };
809
0
    const char *gitfile;
810
0
    int len = strlen(path);
811
0
    int i;
812
0
    while ((1 < len) && (path[len-1] == '/'))
813
0
      len--;
814
815
    /*
816
     * We can handle arbitrary-sized buffers, but this remains as a
817
     * sanity check on untrusted input.
818
     */
819
0
    if (PATH_MAX <= len)
820
0
      return NULL;
821
822
0
    strbuf_reset(&used_path);
823
0
    strbuf_reset(&validated_path);
824
0
    strbuf_add(&used_path, path, len);
825
0
    strbuf_add(&validated_path, path, len);
826
827
0
    if (used_path.buf[0] == '~') {
828
0
      char *newpath = interpolate_path(used_path.buf, 0);
829
0
      if (!newpath)
830
0
        return NULL;
831
0
      strbuf_attach(&used_path, newpath, strlen(newpath),
832
0
              strlen(newpath));
833
0
    }
834
0
    for (i = 0; suffix[i]; i++) {
835
0
      struct stat st;
836
0
      size_t baselen = used_path.len;
837
0
      strbuf_addstr(&used_path, suffix[i]);
838
0
      if (!stat(used_path.buf, &st) &&
839
0
          (S_ISREG(st.st_mode) ||
840
0
          (S_ISDIR(st.st_mode) && is_git_directory(used_path.buf)))) {
841
0
        strbuf_addstr(&validated_path, suffix[i]);
842
0
        break;
843
0
      }
844
0
      strbuf_setlen(&used_path, baselen);
845
0
    }
846
0
    if (!suffix[i])
847
0
      return NULL;
848
0
    gitfile = read_gitfile(used_path.buf);
849
0
    if (gitfile) {
850
0
      strbuf_reset(&used_path);
851
0
      strbuf_addstr(&used_path, gitfile);
852
0
    }
853
0
    if (chdir(used_path.buf))
854
0
      return NULL;
855
0
    path = validated_path.buf;
856
0
  }
857
0
  else {
858
0
    const char *gitfile = read_gitfile(path);
859
0
    if (gitfile)
860
0
      path = gitfile;
861
0
    if (chdir(path))
862
0
      return NULL;
863
0
  }
864
865
0
  if (is_git_directory(".")) {
866
0
    set_git_dir(".", 0);
867
0
    check_repository_format(NULL);
868
0
    return path;
869
0
  }
870
871
0
  return NULL;
872
0
}
873
874
static int calc_shared_perm(int mode)
875
0
{
876
0
  int tweak;
877
878
0
  if (get_shared_repository() < 0)
879
0
    tweak = -get_shared_repository();
880
0
  else
881
0
    tweak = get_shared_repository();
882
883
0
  if (!(mode & S_IWUSR))
884
0
    tweak &= ~0222;
885
0
  if (mode & S_IXUSR)
886
    /* Copy read bits to execute bits */
887
0
    tweak |= (tweak & 0444) >> 2;
888
0
  if (get_shared_repository() < 0)
889
0
    mode = (mode & ~0777) | tweak;
890
0
  else
891
0
    mode |= tweak;
892
893
0
  return mode;
894
0
}
895
896
897
int adjust_shared_perm(const char *path)
898
105k
{
899
105k
  int old_mode, new_mode;
900
901
105k
  if (!get_shared_repository())
902
105k
    return 0;
903
0
  if (get_st_mode_bits(path, &old_mode) < 0)
904
0
    return -1;
905
906
0
  new_mode = calc_shared_perm(old_mode);
907
0
  if (S_ISDIR(old_mode)) {
908
    /* Copy read bits to execute bits */
909
0
    new_mode |= (new_mode & 0444) >> 2;
910
911
    /*
912
     * g+s matters only if any extra access is granted
913
     * based on group membership.
914
     */
915
0
    if (FORCE_DIR_SET_GID && (new_mode & 060))
916
0
      new_mode |= FORCE_DIR_SET_GID;
917
0
  }
918
919
0
  if (((old_mode ^ new_mode) & ~S_IFMT) &&
920
0
      chmod(path, (new_mode & ~S_IFMT)) < 0)
921
0
    return -2;
922
0
  return 0;
923
0
}
924
925
void safe_create_dir(const char *dir, int share)
926
9.76k
{
927
9.76k
  if (mkdir(dir, 0777) < 0) {
928
1.22k
    if (errno != EEXIST) {
929
0
      perror(dir);
930
0
      exit(1);
931
0
    }
932
1.22k
  }
933
8.54k
  else if (share && adjust_shared_perm(dir))
934
0
    die(_("Could not make %s writable by group"), dir);
935
9.76k
}
936
937
static int have_same_root(const char *path1, const char *path2)
938
0
{
939
0
  int is_abs1, is_abs2;
940
941
0
  is_abs1 = is_absolute_path(path1);
942
0
  is_abs2 = is_absolute_path(path2);
943
0
  return (is_abs1 && is_abs2 && tolower(path1[0]) == tolower(path2[0])) ||
944
0
         (!is_abs1 && !is_abs2);
945
0
}
946
947
/*
948
 * Give path as relative to prefix.
949
 *
950
 * The strbuf may or may not be used, so do not assume it contains the
951
 * returned path.
952
 */
953
const char *relative_path(const char *in, const char *prefix,
954
        struct strbuf *sb)
955
1.60k
{
956
1.60k
  int in_len = in ? strlen(in) : 0;
957
1.60k
  int prefix_len = prefix ? strlen(prefix) : 0;
958
1.60k
  int in_off = 0;
959
1.60k
  int prefix_off = 0;
960
1.60k
  int i = 0, j = 0;
961
962
1.60k
  if (!in_len)
963
0
    return "./";
964
1.60k
  else if (!prefix_len)
965
1.60k
    return in;
966
967
0
  if (have_same_root(in, prefix))
968
    /* bypass dos_drive, for "c:" is identical to "C:" */
969
0
    i = j = has_dos_drive_prefix(in);
970
0
  else {
971
0
    return in;
972
0
  }
973
974
0
  while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
975
0
    if (is_dir_sep(prefix[i])) {
976
0
      while (is_dir_sep(prefix[i]))
977
0
        i++;
978
0
      while (is_dir_sep(in[j]))
979
0
        j++;
980
0
      prefix_off = i;
981
0
      in_off = j;
982
0
    } else {
983
0
      i++;
984
0
      j++;
985
0
    }
986
0
  }
987
988
0
  if (
989
      /* "prefix" seems like prefix of "in" */
990
0
      i >= prefix_len &&
991
      /*
992
       * but "/foo" is not a prefix of "/foobar"
993
       * (i.e. prefix not end with '/')
994
       */
995
0
      prefix_off < prefix_len) {
996
0
    if (j >= in_len) {
997
      /* in="/a/b", prefix="/a/b" */
998
0
      in_off = in_len;
999
0
    } else if (is_dir_sep(in[j])) {
1000
      /* in="/a/b/c", prefix="/a/b" */
1001
0
      while (is_dir_sep(in[j]))
1002
0
        j++;
1003
0
      in_off = j;
1004
0
    } else {
1005
      /* in="/a/bbb/c", prefix="/a/b" */
1006
0
      i = prefix_off;
1007
0
    }
1008
0
  } else if (
1009
       /* "in" is short than "prefix" */
1010
0
       j >= in_len &&
1011
       /* "in" not end with '/' */
1012
0
       in_off < in_len) {
1013
0
    if (is_dir_sep(prefix[i])) {
1014
      /* in="/a/b", prefix="/a/b/c/" */
1015
0
      while (is_dir_sep(prefix[i]))
1016
0
        i++;
1017
0
      in_off = in_len;
1018
0
    }
1019
0
  }
1020
0
  in += in_off;
1021
0
  in_len -= in_off;
1022
1023
0
  if (i >= prefix_len) {
1024
0
    if (!in_len)
1025
0
      return "./";
1026
0
    else
1027
0
      return in;
1028
0
  }
1029
1030
0
  strbuf_reset(sb);
1031
0
  strbuf_grow(sb, in_len);
1032
1033
0
  while (i < prefix_len) {
1034
0
    if (is_dir_sep(prefix[i])) {
1035
0
      strbuf_addstr(sb, "../");
1036
0
      while (is_dir_sep(prefix[i]))
1037
0
        i++;
1038
0
      continue;
1039
0
    }
1040
0
    i++;
1041
0
  }
1042
0
  if (!is_dir_sep(prefix[prefix_len - 1]))
1043
0
    strbuf_addstr(sb, "../");
1044
1045
0
  strbuf_addstr(sb, in);
1046
1047
0
  return sb->buf;
1048
0
}
1049
1050
/*
1051
 * A simpler implementation of relative_path
1052
 *
1053
 * Get relative path by removing "prefix" from "in". This function
1054
 * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
1055
 * to increase performance when traversing the path to work_tree.
1056
 */
1057
const char *remove_leading_path(const char *in, const char *prefix)
1058
0
{
1059
0
  static struct strbuf buf = STRBUF_INIT;
1060
0
  int i = 0, j = 0;
1061
1062
0
  if (!prefix || !prefix[0])
1063
0
    return in;
1064
0
  while (prefix[i]) {
1065
0
    if (is_dir_sep(prefix[i])) {
1066
0
      if (!is_dir_sep(in[j]))
1067
0
        return in;
1068
0
      while (is_dir_sep(prefix[i]))
1069
0
        i++;
1070
0
      while (is_dir_sep(in[j]))
1071
0
        j++;
1072
0
      continue;
1073
0
    } else if (in[j] != prefix[i]) {
1074
0
      return in;
1075
0
    }
1076
0
    i++;
1077
0
    j++;
1078
0
  }
1079
0
  if (
1080
      /* "/foo" is a prefix of "/foo" */
1081
0
      in[j] &&
1082
      /* "/foo" is not a prefix of "/foobar" */
1083
0
      !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
1084
0
     )
1085
0
    return in;
1086
0
  while (is_dir_sep(in[j]))
1087
0
    j++;
1088
1089
0
  strbuf_reset(&buf);
1090
0
  if (!in[j])
1091
0
    strbuf_addstr(&buf, ".");
1092
0
  else
1093
0
    strbuf_addstr(&buf, in + j);
1094
0
  return buf.buf;
1095
0
}
1096
1097
/*
1098
 * It is okay if dst == src, but they should not overlap otherwise.
1099
 * The "dst" buffer must be at least as long as "src"; normalizing may shrink
1100
 * the size of the path, but will never grow it.
1101
 *
1102
 * Performs the following normalizations on src, storing the result in dst:
1103
 * - Ensures that components are separated by '/' (Windows only)
1104
 * - Squashes sequences of '/' except "//server/share" on Windows
1105
 * - Removes "." components.
1106
 * - Removes ".." components, and the components the precede them.
1107
 * Returns failure (non-zero) if a ".." component appears as first path
1108
 * component anytime during the normalization. Otherwise, returns success (0).
1109
 *
1110
 * Note that this function is purely textual.  It does not follow symlinks,
1111
 * verify the existence of the path, or make any system calls.
1112
 *
1113
 * prefix_len != NULL is for a specific case of prefix_pathspec():
1114
 * assume that src == dst and src[0..prefix_len-1] is already
1115
 * normalized, any time "../" eats up to the prefix_len part,
1116
 * prefix_len is reduced. In the end prefix_len is the remaining
1117
 * prefix that has not been overridden by user pathspec.
1118
 *
1119
 * NEEDSWORK: This function doesn't perform normalization w.r.t. trailing '/'.
1120
 * For everything but the root folder itself, the normalized path should not
1121
 * end with a '/', then the callers need to be fixed up accordingly.
1122
 *
1123
 */
1124
int normalize_path_copy_len(char *dst, const char *src, int *prefix_len)
1125
47.4k
{
1126
47.4k
  char *dst0;
1127
47.4k
  const char *end;
1128
1129
  /*
1130
   * Copy initial part of absolute path: "/", "C:/", "//server/share/".
1131
   */
1132
47.4k
  end = src + offset_1st_component(src);
1133
71.4k
  while (src < end) {
1134
24.0k
    char c = *src++;
1135
24.0k
    if (is_dir_sep(c))
1136
24.0k
      c = '/';
1137
24.0k
    *dst++ = c;
1138
24.0k
  }
1139
47.4k
  dst0 = dst;
1140
1141
47.4k
  while (is_dir_sep(*src))
1142
0
    src++;
1143
1144
95.4k
  for (;;) {
1145
95.4k
    char c = *src;
1146
1147
    /*
1148
     * A path component that begins with . could be
1149
     * special:
1150
     * (1) "." and ends   -- ignore and terminate.
1151
     * (2) "./"           -- ignore them, eat slash and continue.
1152
     * (3) ".." and ends  -- strip one and terminate.
1153
     * (4) "../"          -- strip one, eat slash and continue.
1154
     */
1155
95.4k
    if (c == '.') {
1156
0
      if (!src[1]) {
1157
        /* (1) */
1158
0
        src++;
1159
0
      } else if (is_dir_sep(src[1])) {
1160
        /* (2) */
1161
0
        src += 2;
1162
0
        while (is_dir_sep(*src))
1163
0
          src++;
1164
0
        continue;
1165
0
      } else if (src[1] == '.') {
1166
0
        if (!src[2]) {
1167
          /* (3) */
1168
0
          src += 2;
1169
0
          goto up_one;
1170
0
        } else if (is_dir_sep(src[2])) {
1171
          /* (4) */
1172
0
          src += 3;
1173
0
          while (is_dir_sep(*src))
1174
0
            src++;
1175
0
          goto up_one;
1176
0
        }
1177
0
      }
1178
0
    }
1179
1180
    /* copy up to the next '/', and eat all '/' */
1181
656k
    while ((c = *src++) != '\0' && !is_dir_sep(c))
1182
560k
      *dst++ = c;
1183
95.4k
    if (is_dir_sep(c)) {
1184
48.0k
      *dst++ = '/';
1185
96.1k
      while (is_dir_sep(c))
1186
48.0k
        c = *src++;
1187
48.0k
      src--;
1188
48.0k
    } else if (!c)
1189
47.4k
      break;
1190
48.0k
    continue;
1191
1192
48.0k
  up_one:
1193
    /*
1194
     * dst0..dst is prefix portion, and dst[-1] is '/';
1195
     * go up one level.
1196
     */
1197
0
    dst--;  /* go to trailing '/' */
1198
0
    if (dst <= dst0)
1199
0
      return -1;
1200
    /* Windows: dst[-1] cannot be backslash anymore */
1201
0
    while (dst0 < dst && dst[-1] != '/')
1202
0
      dst--;
1203
0
    if (prefix_len && *prefix_len > dst - dst0)
1204
0
      *prefix_len = dst - dst0;
1205
0
  }
1206
47.4k
  *dst = '\0';
1207
47.4k
  return 0;
1208
47.4k
}
1209
1210
int normalize_path_copy(char *dst, const char *src)
1211
24.0k
{
1212
24.0k
  return normalize_path_copy_len(dst, src, NULL);
1213
24.0k
}
1214
1215
int strbuf_normalize_path(struct strbuf *src)
1216
0
{
1217
0
  struct strbuf dst = STRBUF_INIT;
1218
1219
0
  strbuf_grow(&dst, src->len);
1220
0
  if (normalize_path_copy(dst.buf, src->buf) < 0) {
1221
0
    strbuf_release(&dst);
1222
0
    return -1;
1223
0
  }
1224
1225
  /*
1226
   * normalize_path does not tell us the new length, so we have to
1227
   * compute it by looking for the new NUL it placed
1228
   */
1229
0
  strbuf_setlen(&dst, strlen(dst.buf));
1230
0
  strbuf_swap(src, &dst);
1231
0
  strbuf_release(&dst);
1232
0
  return 0;
1233
0
}
1234
1235
/*
1236
 * path = Canonical absolute path
1237
 * prefixes = string_list containing normalized, absolute paths without
1238
 * trailing slashes (except for the root directory, which is denoted by "/").
1239
 *
1240
 * Determines, for each path in prefixes, whether the "prefix"
1241
 * is an ancestor directory of path.  Returns the length of the longest
1242
 * ancestor directory, excluding any trailing slashes, or -1 if no prefix
1243
 * is an ancestor.  (Note that this means 0 is returned if prefixes is
1244
 * ["/"].) "/foo" is not considered an ancestor of "/foobar".  Directories
1245
 * are not considered to be their own ancestors.  path must be in a
1246
 * canonical form: empty components, or "." or ".." components are not
1247
 * allowed.
1248
 */
1249
int longest_ancestor_length(const char *path, struct string_list *prefixes)
1250
0
{
1251
0
  int i, max_len = -1;
1252
1253
0
  if (!strcmp(path, "/"))
1254
0
    return -1;
1255
1256
0
  for (i = 0; i < prefixes->nr; i++) {
1257
0
    const char *ceil = prefixes->items[i].string;
1258
0
    int len = strlen(ceil);
1259
1260
    /*
1261
     * For root directories (`/`, `C:/`, `//server/share/`)
1262
     * adjust the length to exclude the trailing slash.
1263
     */
1264
0
    if (len > 0 && ceil[len - 1] == '/')
1265
0
      len--;
1266
1267
0
    if (strncmp(path, ceil, len) ||
1268
0
        path[len] != '/' || !path[len + 1])
1269
0
      continue; /* no match */
1270
1271
0
    if (len > max_len)
1272
0
      max_len = len;
1273
0
  }
1274
1275
0
  return max_len;
1276
0
}
1277
1278
/* strip arbitrary amount of directory separators at end of path */
1279
static inline int chomp_trailing_dir_sep(const char *path, int len)
1280
0
{
1281
0
  while (len && is_dir_sep(path[len - 1]))
1282
0
    len--;
1283
0
  return len;
1284
0
}
1285
1286
/*
1287
 * If path ends with suffix (complete path components), returns the offset of
1288
 * the last character in the path before the suffix (sans trailing directory
1289
 * separators), and -1 otherwise.
1290
 */
1291
static ssize_t stripped_path_suffix_offset(const char *path, const char *suffix)
1292
0
{
1293
0
  int path_len = strlen(path), suffix_len = strlen(suffix);
1294
1295
0
  while (suffix_len) {
1296
0
    if (!path_len)
1297
0
      return -1;
1298
1299
0
    if (is_dir_sep(path[path_len - 1])) {
1300
0
      if (!is_dir_sep(suffix[suffix_len - 1]))
1301
0
        return -1;
1302
0
      path_len = chomp_trailing_dir_sep(path, path_len);
1303
0
      suffix_len = chomp_trailing_dir_sep(suffix, suffix_len);
1304
0
    }
1305
0
    else if (path[--path_len] != suffix[--suffix_len])
1306
0
      return -1;
1307
0
  }
1308
1309
0
  if (path_len && !is_dir_sep(path[path_len - 1]))
1310
0
    return -1;
1311
0
  return chomp_trailing_dir_sep(path, path_len);
1312
0
}
1313
1314
/*
1315
 * Returns true if the path ends with components, considering only complete path
1316
 * components, and false otherwise.
1317
 */
1318
int ends_with_path_components(const char *path, const char *components)
1319
0
{
1320
0
  return stripped_path_suffix_offset(path, components) != -1;
1321
0
}
1322
1323
/*
1324
 * If path ends with suffix (complete path components), returns the
1325
 * part before suffix (sans trailing directory separators).
1326
 * Otherwise returns NULL.
1327
 */
1328
char *strip_path_suffix(const char *path, const char *suffix)
1329
0
{
1330
0
  ssize_t offset = stripped_path_suffix_offset(path, suffix);
1331
1332
0
  return offset == -1 ? NULL : xstrndup(path, offset);
1333
0
}
1334
1335
int daemon_avoid_alias(const char *p)
1336
0
{
1337
0
  int sl, ndot;
1338
1339
  /*
1340
   * This resurrects the belts and suspenders paranoia check by HPA
1341
   * done in <435560F7.4080006@zytor.com> thread, now enter_repo()
1342
   * does not do getcwd() based path canonicalization.
1343
   *
1344
   * sl becomes true immediately after seeing '/' and continues to
1345
   * be true as long as dots continue after that without intervening
1346
   * non-dot character.
1347
   */
1348
0
  if (!p || (*p != '/' && *p != '~'))
1349
0
    return -1;
1350
0
  sl = 1; ndot = 0;
1351
0
  p++;
1352
1353
0
  while (1) {
1354
0
    char ch = *p++;
1355
0
    if (sl) {
1356
0
      if (ch == '.')
1357
0
        ndot++;
1358
0
      else if (ch == '/') {
1359
0
        if (ndot < 3)
1360
          /* reject //, /./ and /../ */
1361
0
          return -1;
1362
0
        ndot = 0;
1363
0
      }
1364
0
      else if (ch == 0) {
1365
0
        if (0 < ndot && ndot < 3)
1366
          /* reject /.$ and /..$ */
1367
0
          return -1;
1368
0
        return 0;
1369
0
      }
1370
0
      else
1371
0
        sl = ndot = 0;
1372
0
    }
1373
0
    else if (ch == 0)
1374
0
      return 0;
1375
0
    else if (ch == '/') {
1376
0
      sl = 1;
1377
0
      ndot = 0;
1378
0
    }
1379
0
  }
1380
0
}
1381
1382
/*
1383
 * On NTFS, we need to be careful to disallow certain synonyms of the `.git/`
1384
 * directory:
1385
 *
1386
 * - For historical reasons, file names that end in spaces or periods are
1387
 *   automatically trimmed. Therefore, `.git . . ./` is a valid way to refer
1388
 *   to `.git/`.
1389
 *
1390
 * - For other historical reasons, file names that do not conform to the 8.3
1391
 *   format (up to eight characters for the basename, three for the file
1392
 *   extension, certain characters not allowed such as `+`, etc) are associated
1393
 *   with a so-called "short name", at least on the `C:` drive by default.
1394
 *   Which means that `git~1/` is a valid way to refer to `.git/`.
1395
 *
1396
 *   Note: Technically, `.git/` could receive the short name `git~2` if the
1397
 *   short name `git~1` were already used. In Git, however, we guarantee that
1398
 *   `.git` is the first item in a directory, therefore it will be associated
1399
 *   with the short name `git~1` (unless short names are disabled).
1400
 *
1401
 * - For yet other historical reasons, NTFS supports so-called "Alternate Data
1402
 *   Streams", i.e. metadata associated with a given file, referred to via
1403
 *   `<filename>:<stream-name>:<stream-type>`. There exists a default stream
1404
 *   type for directories, allowing `.git/` to be accessed via
1405
 *   `.git::$INDEX_ALLOCATION/`.
1406
 *
1407
 * When this function returns 1, it indicates that the specified file/directory
1408
 * name refers to a `.git` file or directory, or to any of these synonyms, and
1409
 * Git should therefore not track it.
1410
 *
1411
 * For performance reasons, _all_ Alternate Data Streams of `.git/` are
1412
 * forbidden, not just `::$INDEX_ALLOCATION`.
1413
 *
1414
 * This function is intended to be used by `git fsck` even on platforms where
1415
 * the backslash is a regular filename character, therefore it needs to handle
1416
 * backlash characters in the provided `name` specially: they are interpreted
1417
 * as directory separators.
1418
 */
1419
int is_ntfs_dotgit(const char *name)
1420
8.57k
{
1421
8.57k
  char c;
1422
1423
  /*
1424
   * Note that when we don't find `.git` or `git~1` we end up with `name`
1425
   * advanced partway through the string. That's okay, though, as we
1426
   * return immediately in those cases, without looking at `name` any
1427
   * further.
1428
   */
1429
8.57k
  c = *(name++);
1430
8.57k
  if (c == '.') {
1431
    /* .git */
1432
0
    if (((c = *(name++)) != 'g' && c != 'G') ||
1433
0
        ((c = *(name++)) != 'i' && c != 'I') ||
1434
0
        ((c = *(name++)) != 't' && c != 'T'))
1435
0
      return 0;
1436
8.57k
  } else if (c == 'g' || c == 'G') {
1437
    /* git ~1 */
1438
0
    if (((c = *(name++)) != 'i' && c != 'I') ||
1439
0
        ((c = *(name++)) != 't' && c != 'T') ||
1440
0
        *(name++) != '~' ||
1441
0
        *(name++) != '1')
1442
0
      return 0;
1443
0
  } else
1444
8.57k
    return 0;
1445
1446
0
  for (;;) {
1447
0
    c = *(name++);
1448
0
    if (!c || is_xplatform_dir_sep(c) || c == ':')
1449
0
      return 1;
1450
0
    if (c != '.' && c != ' ')
1451
0
      return 0;
1452
0
  }
1453
0
}
1454
1455
static int is_ntfs_dot_generic(const char *name,
1456
             const char *dotgit_name,
1457
             size_t len,
1458
             const char *dotgit_ntfs_shortname_prefix)
1459
0
{
1460
0
  int saw_tilde;
1461
0
  size_t i;
1462
1463
0
  if ((name[0] == '.' && !strncasecmp(name + 1, dotgit_name, len))) {
1464
0
    i = len + 1;
1465
0
only_spaces_and_periods:
1466
0
    for (;;) {
1467
0
      char c = name[i++];
1468
0
      if (!c || c == ':')
1469
0
        return 1;
1470
0
      if (c != ' ' && c != '.')
1471
0
        return 0;
1472
0
    }
1473
0
  }
1474
1475
  /*
1476
   * Is it a regular NTFS short name, i.e. shortened to 6 characters,
1477
   * followed by ~1, ... ~4?
1478
   */
1479
0
  if (!strncasecmp(name, dotgit_name, 6) && name[6] == '~' &&
1480
0
      name[7] >= '1' && name[7] <= '4') {
1481
0
    i = 8;
1482
0
    goto only_spaces_and_periods;
1483
0
  }
1484
1485
  /*
1486
   * Is it a fall-back NTFS short name (for details, see
1487
   * https://en.wikipedia.org/wiki/8.3_filename?
1488
   */
1489
0
  for (i = 0, saw_tilde = 0; i < 8; i++)
1490
0
    if (name[i] == '\0')
1491
0
      return 0;
1492
0
    else if (saw_tilde) {
1493
0
      if (name[i] < '0' || name[i] > '9')
1494
0
        return 0;
1495
0
    } else if (name[i] == '~') {
1496
0
      if (name[++i] < '1' || name[i] > '9')
1497
0
        return 0;
1498
0
      saw_tilde = 1;
1499
0
    } else if (i >= 6)
1500
0
      return 0;
1501
0
    else if (name[i] & 0x80) {
1502
      /*
1503
       * We know our needles contain only ASCII, so we clamp
1504
       * here to make the results of tolower() sane.
1505
       */
1506
0
      return 0;
1507
0
    } else if (tolower(name[i]) != dotgit_ntfs_shortname_prefix[i])
1508
0
      return 0;
1509
1510
0
  goto only_spaces_and_periods;
1511
0
}
1512
1513
/*
1514
 * Inline helper to make sure compiler resolves strlen() on literals at
1515
 * compile time.
1516
 */
1517
static inline int is_ntfs_dot_str(const char *name, const char *dotgit_name,
1518
          const char *dotgit_ntfs_shortname_prefix)
1519
0
{
1520
0
  return is_ntfs_dot_generic(name, dotgit_name, strlen(dotgit_name),
1521
0
           dotgit_ntfs_shortname_prefix);
1522
0
}
1523
1524
int is_ntfs_dotgitmodules(const char *name)
1525
0
{
1526
0
  return is_ntfs_dot_str(name, "gitmodules", "gi7eba");
1527
0
}
1528
1529
int is_ntfs_dotgitignore(const char *name)
1530
0
{
1531
0
  return is_ntfs_dot_str(name, "gitignore", "gi250a");
1532
0
}
1533
1534
int is_ntfs_dotgitattributes(const char *name)
1535
0
{
1536
0
  return is_ntfs_dot_str(name, "gitattributes", "gi7d29");
1537
0
}
1538
1539
int is_ntfs_dotmailmap(const char *name)
1540
0
{
1541
0
  return is_ntfs_dot_str(name, "mailmap", "maba30");
1542
0
}
1543
1544
int looks_like_command_line_option(const char *str)
1545
0
{
1546
0
  return str && str[0] == '-';
1547
0
}
1548
1549
char *xdg_config_home_for(const char *subdir, const char *filename)
1550
2
{
1551
2
  const char *home, *config_home;
1552
1553
2
  assert(subdir);
1554
2
  assert(filename);
1555
2
  config_home = getenv("XDG_CONFIG_HOME");
1556
2
  if (config_home && *config_home)
1557
0
    return mkpathdup("%s/%s/%s", config_home, subdir, filename);
1558
1559
2
  home = getenv("HOME");
1560
2
  if (home)
1561
2
    return mkpathdup("%s/.config/%s/%s", home, subdir, filename);
1562
1563
0
  return NULL;
1564
2
}
1565
1566
char *xdg_config_home(const char *filename)
1567
2
{
1568
2
  return xdg_config_home_for("git", filename);
1569
2
}
1570
1571
char *xdg_cache_home(const char *filename)
1572
0
{
1573
0
  const char *home, *cache_home;
1574
1575
0
  assert(filename);
1576
0
  cache_home = getenv("XDG_CACHE_HOME");
1577
0
  if (cache_home && *cache_home)
1578
0
    return mkpathdup("%s/git/%s", cache_home, filename);
1579
1580
0
  home = getenv("HOME");
1581
0
  if (home)
1582
0
    return mkpathdup("%s/.cache/git/%s", home, filename);
1583
0
  return NULL;
1584
0
}
1585
1586
REPO_GIT_PATH_FUNC(squash_msg, "SQUASH_MSG")
1587
REPO_GIT_PATH_FUNC(merge_msg, "MERGE_MSG")
1588
REPO_GIT_PATH_FUNC(merge_rr, "MERGE_RR")
1589
REPO_GIT_PATH_FUNC(merge_mode, "MERGE_MODE")
1590
REPO_GIT_PATH_FUNC(merge_head, "MERGE_HEAD")
1591
REPO_GIT_PATH_FUNC(merge_autostash, "MERGE_AUTOSTASH")
1592
REPO_GIT_PATH_FUNC(auto_merge, "AUTO_MERGE")
1593
REPO_GIT_PATH_FUNC(fetch_head, "FETCH_HEAD")
1594
REPO_GIT_PATH_FUNC(shallow, "shallow")