rugged 1.2.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rugged/version.rb +1 -1
  3. data/vendor/libgit2/CMakeLists.txt +1 -1
  4. data/vendor/libgit2/cmake/FindLibSSH2.cmake +13 -0
  5. data/vendor/libgit2/include/git2/attr.h +7 -1
  6. data/vendor/libgit2/include/git2/blob.h +7 -1
  7. data/vendor/libgit2/include/git2/clone.h +1 -1
  8. data/vendor/libgit2/include/git2/common.h +29 -1
  9. data/vendor/libgit2/include/git2/deprecated.h +120 -0
  10. data/vendor/libgit2/include/git2/diff.h +3 -97
  11. data/vendor/libgit2/include/git2/email.h +127 -0
  12. data/vendor/libgit2/include/git2/errors.h +1 -0
  13. data/vendor/libgit2/include/git2/filter.h +7 -1
  14. data/vendor/libgit2/include/git2/notes.h +2 -2
  15. data/vendor/libgit2/include/git2/oidarray.h +5 -8
  16. data/vendor/libgit2/include/git2/remote.h +4 -4
  17. data/vendor/libgit2/include/git2/repository.h +12 -10
  18. data/vendor/libgit2/include/git2/stash.h +1 -1
  19. data/vendor/libgit2/include/git2/stdint.h +3 -3
  20. data/vendor/libgit2/include/git2/sys/email.h +45 -0
  21. data/vendor/libgit2/include/git2/version.h +4 -4
  22. data/vendor/libgit2/include/git2.h +1 -0
  23. data/vendor/libgit2/src/CMakeLists.txt +7 -0
  24. data/vendor/libgit2/src/attr.c +24 -9
  25. data/vendor/libgit2/src/attr_file.c +23 -15
  26. data/vendor/libgit2/src/attr_file.h +3 -3
  27. data/vendor/libgit2/src/blame.c +4 -4
  28. data/vendor/libgit2/src/blame_git.c +1 -1
  29. data/vendor/libgit2/src/blob.c +15 -9
  30. data/vendor/libgit2/src/buffer.c +16 -8
  31. data/vendor/libgit2/src/buffer.h +2 -1
  32. data/vendor/libgit2/src/cc-compat.h +1 -7
  33. data/vendor/libgit2/src/checkout.c +6 -7
  34. data/vendor/libgit2/src/clone.c +1 -1
  35. data/vendor/libgit2/src/commit_graph.c +1 -1
  36. data/vendor/libgit2/src/config.c +11 -7
  37. data/vendor/libgit2/src/config_file.c +2 -2
  38. data/vendor/libgit2/src/config_parse.c +1 -1
  39. data/vendor/libgit2/src/describe.c +1 -1
  40. data/vendor/libgit2/src/diff.c +41 -173
  41. data/vendor/libgit2/src/email.c +299 -0
  42. data/vendor/libgit2/src/email.h +25 -0
  43. data/vendor/libgit2/src/filter.c +7 -1
  44. data/vendor/libgit2/src/hash/sha1/sha1dc/sha1.c +8 -8
  45. data/vendor/libgit2/src/ignore.c +2 -2
  46. data/vendor/libgit2/src/indexer.c +37 -3
  47. data/vendor/libgit2/src/libgit2.c +31 -0
  48. data/vendor/libgit2/src/merge.c +7 -4
  49. data/vendor/libgit2/src/notes.c +31 -31
  50. data/vendor/libgit2/src/oidarray.c +10 -1
  51. data/vendor/libgit2/src/path.c +214 -55
  52. data/vendor/libgit2/src/path.h +29 -9
  53. data/vendor/libgit2/src/pathspec.c +1 -1
  54. data/vendor/libgit2/src/refdb_fs.c +1 -1
  55. data/vendor/libgit2/src/refs.c +2 -2
  56. data/vendor/libgit2/src/refspec.c +1 -1
  57. data/vendor/libgit2/src/remote.c +12 -5
  58. data/vendor/libgit2/src/repository.c +233 -41
  59. data/vendor/libgit2/src/repository.h +5 -0
  60. data/vendor/libgit2/src/reset.c +1 -1
  61. data/vendor/libgit2/src/revparse.c +4 -4
  62. data/vendor/libgit2/src/stash.c +1 -1
  63. data/vendor/libgit2/src/streams/openssl_legacy.c +1 -1
  64. data/vendor/libgit2/src/streams/openssl_legacy.h +1 -1
  65. data/vendor/libgit2/src/threadstate.c +2 -1
  66. data/vendor/libgit2/src/trailer.c +1 -1
  67. data/vendor/libgit2/src/transports/ssh.c +4 -4
  68. data/vendor/libgit2/src/transports/winhttp.c +1 -1
  69. data/vendor/libgit2/src/util.c +1 -1
  70. data/vendor/libgit2/src/util.h +1 -1
  71. data/vendor/libgit2/src/win32/findfile.c +1 -1
  72. data/vendor/libgit2/src/win32/posix.h +6 -6
  73. data/vendor/libgit2/src/win32/posix_w32.c +9 -6
  74. metadata +11 -6
@@ -601,9 +601,10 @@ static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size)
601
601
  idx->inbuf_len += size - to_expell;
602
602
  }
603
603
 
604
+ #if defined(NO_MMAP) || !defined(GIT_WIN32)
605
+
604
606
  static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t size)
605
607
  {
606
- #ifdef NO_MMAP
607
608
  size_t remaining_size = size;
608
609
  const char *ptr = (const char *)data;
609
610
 
@@ -619,7 +620,31 @@ static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t s
619
620
  offset += nb;
620
621
  remaining_size -= nb;
621
622
  }
623
+
624
+ return 0;
625
+ }
626
+
627
+ static int append_to_pack(git_indexer *idx, const void *data, size_t size)
628
+ {
629
+ if (write_at(idx, data, idx->pack->mwf.size, size) < 0) {
630
+ git_error_set(GIT_ERROR_OS, "cannot extend packfile '%s'", idx->pack->pack_name);
631
+ return -1;
632
+ }
633
+
634
+ return 0;
635
+ }
636
+
622
637
  #else
638
+
639
+ /*
640
+ * Windows may keep different views to a networked file for the mmap- and
641
+ * open-accessed versions of a file, so any writes done through
642
+ * `write(2)`/`pwrite(2)` may not be reflected on the data that `mmap(2)` is
643
+ * able to read.
644
+ */
645
+
646
+ static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t size)
647
+ {
623
648
  git_file fd = idx->pack->mwf.fd;
624
649
  size_t mmap_alignment;
625
650
  size_t page_offset;
@@ -644,7 +669,6 @@ static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t s
644
669
  map_data = (unsigned char *)map.data;
645
670
  memcpy(map_data + page_offset, data, size);
646
671
  p_munmap(&map);
647
- #endif
648
672
 
649
673
  return 0;
650
674
  }
@@ -680,6 +704,8 @@ static int append_to_pack(git_indexer *idx, const void *data, size_t size)
680
704
  return write_at(idx, data, idx->pack->mwf.size, size);
681
705
  }
682
706
 
707
+ #endif
708
+
683
709
  static int read_stream_object(git_indexer *idx, git_indexer_progress *stats)
684
710
  {
685
711
  git_packfile_stream *stream = &idx->stream;
@@ -1279,11 +1305,19 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
1279
1305
  if (git_mwindow_free_all(&idx->pack->mwf) < 0)
1280
1306
  goto on_error;
1281
1307
 
1282
- /* Truncate file to undo rounding up to next page_size in append_to_pack */
1308
+ #if !defined(NO_MMAP) && defined(GIT_WIN32)
1309
+ /*
1310
+ * Some non-Windows remote filesystems fail when truncating files if the
1311
+ * file permissions change after opening the file (done by p_mkstemp).
1312
+ *
1313
+ * Truncation is only needed when mmap is used to undo rounding up to next
1314
+ * page_size in append_to_pack.
1315
+ */
1283
1316
  if (p_ftruncate(idx->pack->mwf.fd, idx->pack->mwf.size) < 0) {
1284
1317
  git_error_set(GIT_ERROR_OS, "failed to truncate pack file '%s'", idx->pack->pack_name);
1285
1318
  return -1;
1286
1319
  }
1320
+ #endif
1287
1321
 
1288
1322
  if (idx->do_fsync && p_fsync(idx->pack->mwf.fd) < 0) {
1289
1323
  git_error_set(GIT_ERROR_OS, "failed to fsync packfile");
@@ -52,6 +52,7 @@ static void libgit2_settings_global_shutdown(void)
52
52
  {
53
53
  git__free(git__user_agent);
54
54
  git__free(git__ssl_ciphers);
55
+ git_repository__free_extensions();
55
56
  }
56
57
 
57
58
  static int git_libgit2_settings_global_init(void)
@@ -367,6 +368,36 @@ int git_libgit2_opts(int key, ...)
367
368
  git_odb__loose_priority = va_arg(ap, int);
368
369
  break;
369
370
 
371
+ case GIT_OPT_SET_EXTENSIONS:
372
+ {
373
+ const char **extensions = va_arg(ap, const char **);
374
+ size_t len = va_arg(ap, size_t);
375
+ error = git_repository__set_extensions(extensions, len);
376
+ }
377
+ break;
378
+
379
+ case GIT_OPT_GET_EXTENSIONS:
380
+ {
381
+ git_strarray *out = va_arg(ap, git_strarray *);
382
+ char **extensions;
383
+ size_t len;
384
+
385
+ if ((error = git_repository__extensions(&extensions, &len)) < 0)
386
+ break;
387
+
388
+ out->strings = extensions;
389
+ out->count = len;
390
+ }
391
+ break;
392
+
393
+ case GIT_OPT_GET_OWNER_VALIDATION:
394
+ *(va_arg(ap, int *)) = git_repository__validate_ownership;
395
+ break;
396
+
397
+ case GIT_OPT_SET_OWNER_VALIDATION:
398
+ git_repository__validate_ownership = (va_arg(ap, int) != 0);
399
+ break;
400
+
370
401
  default:
371
402
  git_error_set(GIT_ERROR_INVALID, "invalid option key");
372
403
  error = -1;
@@ -816,8 +816,11 @@ static int merge_conflict_resolve_one_renamed(
816
816
  conflict->type == GIT_MERGE_DIFF_RENAMED_ADDED)
817
817
  return 0;
818
818
 
819
- ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0);
820
- theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0);
819
+ ours_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->our_entry.id) != 0) ||
820
+ (conflict->ancestor_entry.mode != conflict->our_entry.mode);
821
+
822
+ theirs_changed = (git_oid__cmp(&conflict->ancestor_entry.id, &conflict->their_entry.id) != 0) ||
823
+ (conflict->ancestor_entry.mode != conflict->their_entry.mode);
821
824
 
822
825
  /* if both are modified (and not to a common target) require a merge */
823
826
  if (ours_changed && theirs_changed &&
@@ -1151,7 +1154,7 @@ static void deletes_by_oid_free(git_oidmap *map) {
1151
1154
  git_oidmap_free(map);
1152
1155
  }
1153
1156
 
1154
- static int deletes_by_oid_enqueue(git_oidmap *map, git_pool* pool, const git_oid *id, size_t idx)
1157
+ static int deletes_by_oid_enqueue(git_oidmap *map, git_pool *pool, const git_oid *id, size_t idx)
1155
1158
  {
1156
1159
  deletes_by_oid_queue *queue;
1157
1160
  size_t *array_entry;
@@ -2366,7 +2369,7 @@ done:
2366
2369
 
2367
2370
  git_annotated_commit_free(other);
2368
2371
  git_annotated_commit_free(new_base);
2369
- git_oidarray_free(&bases);
2372
+ git_oidarray_dispose(&bases);
2370
2373
  git_array_clear(head_ids);
2371
2374
  return error;
2372
2375
  }
@@ -407,31 +407,33 @@ cleanup:
407
407
  return error;
408
408
  }
409
409
 
410
- static int note_get_default_ref(char **out, git_repository *repo)
410
+ static int note_get_default_ref(git_buf *out, git_repository *repo)
411
411
  {
412
412
  git_config *cfg;
413
- int ret = git_repository_config__weakptr(&cfg, repo);
413
+ int error;
414
+
415
+ if ((error = git_repository_config__weakptr(&cfg, repo)) < 0)
416
+ return error;
414
417
 
415
- *out = (ret != 0) ? NULL : git_config__get_string_force(
416
- cfg, "core.notesref", GIT_NOTES_DEFAULT_REF);
418
+ error = git_config_get_string_buf(out, cfg, "core.notesref");
417
419
 
418
- return ret;
420
+ if (error == GIT_ENOTFOUND)
421
+ error = git_buf_puts(out, GIT_NOTES_DEFAULT_REF);
422
+
423
+ return error;
419
424
  }
420
425
 
421
- static int normalize_namespace(char **out, git_repository *repo, const char *notes_ref)
426
+ static int normalize_namespace(git_buf *out, git_repository *repo, const char *notes_ref)
422
427
  {
423
- if (notes_ref) {
424
- *out = git__strdup(notes_ref);
425
- GIT_ERROR_CHECK_ALLOC(*out);
426
- return 0;
427
- }
428
+ if (notes_ref)
429
+ return git_buf_puts(out, notes_ref);
428
430
 
429
431
  return note_get_default_ref(out, repo);
430
432
  }
431
433
 
432
434
  static int retrieve_note_commit(
433
435
  git_commit **commit_out,
434
- char **notes_ref_out,
436
+ git_buf *notes_ref_out,
435
437
  git_repository *repo,
436
438
  const char *notes_ref)
437
439
  {
@@ -441,7 +443,7 @@ static int retrieve_note_commit(
441
443
  if ((error = normalize_namespace(notes_ref_out, repo, notes_ref)) < 0)
442
444
  return error;
443
445
 
444
- if ((error = git_reference_name_to_id(&oid, repo, *notes_ref_out)) < 0)
446
+ if ((error = git_reference_name_to_id(&oid, repo, notes_ref_out->ptr)) < 0)
445
447
  return error;
446
448
 
447
449
  if (git_commit_lookup(commit_out, repo, &oid) < 0)
@@ -476,7 +478,7 @@ int git_note_read(git_note **out, git_repository *repo,
476
478
  const char *notes_ref_in, const git_oid *oid)
477
479
  {
478
480
  int error;
479
- char *notes_ref = NULL;
481
+ git_buf notes_ref = GIT_BUF_INIT;
480
482
  git_commit *commit = NULL;
481
483
 
482
484
  error = retrieve_note_commit(&commit, &notes_ref, repo, notes_ref_in);
@@ -487,7 +489,7 @@ int git_note_read(git_note **out, git_repository *repo,
487
489
  error = git_note_commit_read(out, repo, commit, oid);
488
490
 
489
491
  cleanup:
490
- git__free(notes_ref);
492
+ git_buf_dispose(&notes_ref);
491
493
  git_commit_free(commit);
492
494
  return error;
493
495
  }
@@ -534,7 +536,7 @@ int git_note_create(
534
536
  int allow_note_overwrite)
535
537
  {
536
538
  int error;
537
- char *notes_ref = NULL;
539
+ git_buf notes_ref = GIT_BUF_INIT;
538
540
  git_commit *existing_notes_commit = NULL;
539
541
  git_reference *ref = NULL;
540
542
  git_oid notes_blob_oid, notes_commit_oid;
@@ -553,14 +555,14 @@ int git_note_create(
553
555
  if (error < 0)
554
556
  goto cleanup;
555
557
 
556
- error = git_reference_create(&ref, repo, notes_ref,
558
+ error = git_reference_create(&ref, repo, notes_ref.ptr,
557
559
  &notes_commit_oid, 1, NULL);
558
560
 
559
561
  if (out != NULL)
560
562
  git_oid_cpy(out, &notes_blob_oid);
561
563
 
562
564
  cleanup:
563
- git__free(notes_ref);
565
+ git_buf_dispose(&notes_ref);
564
566
  git_commit_free(existing_notes_commit);
565
567
  git_reference_free(ref);
566
568
  return error;
@@ -596,7 +598,7 @@ int git_note_remove(git_repository *repo, const char *notes_ref_in,
596
598
  const git_oid *oid)
597
599
  {
598
600
  int error;
599
- char *notes_ref_target = NULL;
601
+ git_buf notes_ref_target = GIT_BUF_INIT;
600
602
  git_commit *existing_notes_commit = NULL;
601
603
  git_oid new_notes_commit;
602
604
  git_reference *notes_ref = NULL;
@@ -612,11 +614,11 @@ int git_note_remove(git_repository *repo, const char *notes_ref_in,
612
614
  if (error < 0)
613
615
  goto cleanup;
614
616
 
615
- error = git_reference_create(&notes_ref, repo, notes_ref_target,
617
+ error = git_reference_create(&notes_ref, repo, notes_ref_target.ptr,
616
618
  &new_notes_commit, 1, NULL);
617
619
 
618
620
  cleanup:
619
- git__free(notes_ref_target);
621
+ git_buf_dispose(&notes_ref_target);
620
622
  git_reference_free(notes_ref);
621
623
  git_commit_free(existing_notes_commit);
622
624
  return error;
@@ -624,18 +626,16 @@ cleanup:
624
626
 
625
627
  int git_note_default_ref(git_buf *out, git_repository *repo)
626
628
  {
627
- char *default_ref;
628
629
  int error;
629
630
 
630
631
  GIT_ASSERT_ARG(out);
631
632
  GIT_ASSERT_ARG(repo);
632
633
 
633
634
  if ((error = git_buf_sanitize(out)) < 0 ||
634
- (error = note_get_default_ref(&default_ref, repo)) < 0)
635
- return error;
635
+ (error = note_get_default_ref(out, repo)) < 0)
636
+ git_buf_dispose(out);
636
637
 
637
- git_buf_attach(out, default_ref, strlen(default_ref));
638
- return 0;
638
+ return error;
639
639
  }
640
640
 
641
641
  const git_signature *git_note_committer(const git_note *note)
@@ -674,7 +674,7 @@ void git_note_free(git_note *note)
674
674
  }
675
675
 
676
676
  static int process_entry_path(
677
- const char* entry_path,
677
+ const char *entry_path,
678
678
  git_oid *annotated_object_id)
679
679
  {
680
680
  int error = 0;
@@ -780,7 +780,7 @@ int git_note_iterator_new(
780
780
  {
781
781
  int error;
782
782
  git_commit *commit = NULL;
783
- char *notes_ref;
783
+ git_buf notes_ref = GIT_BUF_INIT;
784
784
 
785
785
  error = retrieve_note_commit(&commit, &notes_ref, repo, notes_ref_in);
786
786
  if (error < 0)
@@ -789,15 +789,15 @@ int git_note_iterator_new(
789
789
  error = git_note_commit_iterator_new(it, commit);
790
790
 
791
791
  cleanup:
792
- git__free(notes_ref);
792
+ git_buf_dispose(&notes_ref);
793
793
  git_commit_free(commit);
794
794
 
795
795
  return error;
796
796
  }
797
797
 
798
798
  int git_note_next(
799
- git_oid* note_id,
800
- git_oid* annotated_id,
799
+ git_oid *note_id,
800
+ git_oid *annotated_id,
801
801
  git_note_iterator *it)
802
802
  {
803
803
  int error;
@@ -10,7 +10,7 @@
10
10
  #include "git2/oidarray.h"
11
11
  #include "array.h"
12
12
 
13
- void git_oidarray_free(git_oidarray *arr)
13
+ void git_oidarray_dispose(git_oidarray *arr)
14
14
  {
15
15
  git__free(arr->ids);
16
16
  }
@@ -32,3 +32,12 @@ void git_oidarray__reverse(git_oidarray *arr)
32
32
  git_oid_cpy(&arr->ids[(arr->count-1)-i], &tmp);
33
33
  }
34
34
  }
35
+
36
+ #ifndef GIT_DEPRECATE_HARD
37
+
38
+ void git_oidarray_free(git_oidarray *arr)
39
+ {
40
+ git_oidarray_dispose(arr);
41
+ }
42
+
43
+ #endif
@@ -413,7 +413,7 @@ int git_path_to_dir(git_buf *path)
413
413
  return git_buf_oom(path) ? -1 : 0;
414
414
  }
415
415
 
416
- void git_path_string_to_dir(char* path, size_t size)
416
+ void git_path_string_to_dir(char *path, size_t size)
417
417
  {
418
418
  size_t end = strlen(path);
419
419
 
@@ -2024,78 +2024,237 @@ done:
2024
2024
  return supported;
2025
2025
  }
2026
2026
 
2027
- int git_path_validate_system_file_ownership(const char *path)
2027
+ static git_path__mock_owner_t mock_owner = GIT_PATH_MOCK_OWNER_NONE;
2028
+
2029
+ void git_path__set_owner(git_path__mock_owner_t owner)
2030
+ {
2031
+ mock_owner = owner;
2032
+ }
2033
+
2034
+ #ifdef GIT_WIN32
2035
+ static PSID *sid_dup(PSID sid)
2036
+ {
2037
+ DWORD len;
2038
+ PSID dup;
2039
+
2040
+ len = GetLengthSid(sid);
2041
+
2042
+ if ((dup = git__malloc(len)) == NULL)
2043
+ return NULL;
2044
+
2045
+ if (!CopySid(len, dup, sid)) {
2046
+ git_error_set(GIT_ERROR_OS, "could not duplicate sid");
2047
+ git__free(dup);
2048
+ return NULL;
2049
+ }
2050
+
2051
+ return dup;
2052
+ }
2053
+
2054
+ static int current_user_sid(PSID *out)
2028
2055
  {
2029
- #ifndef GIT_WIN32
2030
- GIT_UNUSED(path);
2031
- return GIT_OK;
2032
- #else
2033
- git_win32_path buf;
2034
- PSID owner_sid;
2035
- PSECURITY_DESCRIPTOR descriptor = NULL;
2036
- HANDLE token;
2037
2056
  TOKEN_USER *info = NULL;
2038
- DWORD err, len;
2039
- int ret;
2057
+ HANDLE token = NULL;
2058
+ DWORD len = 0;
2059
+ int error = -1;
2040
2060
 
2041
- if (git_win32_path_from_utf8(buf, path) < 0)
2042
- return -1;
2061
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
2062
+ git_error_set(GIT_ERROR_OS, "could not lookup process information");
2063
+ goto done;
2064
+ }
2065
+
2066
+ if (GetTokenInformation(token, TokenUser, NULL, 0, &len) ||
2067
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
2068
+ git_error_set(GIT_ERROR_OS, "could not lookup token metadata");
2069
+ goto done;
2070
+ }
2043
2071
 
2044
- err = GetNamedSecurityInfoW(buf, SE_FILE_OBJECT,
2045
- OWNER_SECURITY_INFORMATION |
2046
- DACL_SECURITY_INFORMATION,
2047
- &owner_sid, NULL, NULL, NULL, &descriptor);
2072
+ info = git__malloc(len);
2073
+ GIT_ERROR_CHECK_ALLOC(info);
2048
2074
 
2049
- if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
2050
- ret = GIT_ENOTFOUND;
2051
- goto cleanup;
2075
+ if (!GetTokenInformation(token, TokenUser, info, len, &len)) {
2076
+ git_error_set(GIT_ERROR_OS, "could not lookup current user");
2077
+ goto done;
2052
2078
  }
2053
2079
 
2054
- if (err != ERROR_SUCCESS) {
2080
+ if ((*out = sid_dup(info->User.Sid)))
2081
+ error = 0;
2082
+
2083
+ done:
2084
+ if (token)
2085
+ CloseHandle(token);
2086
+
2087
+ git__free(info);
2088
+ return error;
2089
+ }
2090
+
2091
+ static int file_owner_sid(PSID *out, const char *path)
2092
+ {
2093
+ git_win32_path path_w32;
2094
+ PSECURITY_DESCRIPTOR descriptor = NULL;
2095
+ PSID owner_sid;
2096
+ DWORD ret;
2097
+ int error = -1;
2098
+
2099
+ if (git_win32_path_from_utf8(path_w32, path) < 0)
2100
+ return -1;
2101
+
2102
+ ret = GetNamedSecurityInfoW(path_w32, SE_FILE_OBJECT,
2103
+ OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
2104
+ &owner_sid, NULL, NULL, NULL, &descriptor);
2105
+
2106
+ if (ret == ERROR_FILE_NOT_FOUND || ret == ERROR_PATH_NOT_FOUND)
2107
+ error = GIT_ENOTFOUND;
2108
+ else if (ret != ERROR_SUCCESS)
2055
2109
  git_error_set(GIT_ERROR_OS, "failed to get security information");
2056
- ret = GIT_ERROR;
2057
- goto cleanup;
2110
+ else if (!IsValidSid(owner_sid))
2111
+ git_error_set(GIT_ERROR_OS, "file owner is not valid");
2112
+ else if ((*out = sid_dup(owner_sid)))
2113
+ error = 0;
2114
+
2115
+ if (descriptor)
2116
+ LocalFree(descriptor);
2117
+
2118
+ return error;
2119
+ }
2120
+
2121
+ int git_path_owner_is_current_user(bool *out, const char *path)
2122
+ {
2123
+ PSID owner_sid = NULL, user_sid = NULL;
2124
+ int error = -1;
2125
+
2126
+ if (mock_owner) {
2127
+ *out = (mock_owner == GIT_PATH_MOCK_OWNER_CURRENT_USER);
2128
+ return 0;
2129
+ }
2130
+
2131
+ if ((error = file_owner_sid(&owner_sid, path)) < 0 ||
2132
+ (error = current_user_sid(&user_sid)) < 0)
2133
+ goto done;
2134
+
2135
+ *out = EqualSid(owner_sid, user_sid);
2136
+ error = 0;
2137
+
2138
+ done:
2139
+ git__free(owner_sid);
2140
+ git__free(user_sid);
2141
+ return error;
2142
+ }
2143
+
2144
+ int git_path_owner_is_system(bool *out, const char *path)
2145
+ {
2146
+ PSID owner_sid;
2147
+
2148
+ if (mock_owner) {
2149
+ *out = (mock_owner == GIT_PATH_MOCK_OWNER_SYSTEM);
2150
+ return 0;
2058
2151
  }
2059
2152
 
2060
- if (!IsValidSid(owner_sid)) {
2061
- git_error_set(GIT_ERROR_INVALID, "programdata configuration file owner is unknown");
2062
- ret = GIT_ERROR;
2063
- goto cleanup;
2153
+ if (file_owner_sid(&owner_sid, path) < 0)
2154
+ return -1;
2155
+
2156
+ *out = IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
2157
+ IsWellKnownSid(owner_sid, WinLocalSystemSid);
2158
+
2159
+ git__free(owner_sid);
2160
+ return 0;
2161
+ }
2162
+
2163
+ int git_path_owner_is_system_or_current_user(bool *out, const char *path)
2164
+ {
2165
+ PSID owner_sid = NULL, user_sid = NULL;
2166
+ int error = -1;
2167
+
2168
+ if (mock_owner) {
2169
+ *out = (mock_owner == GIT_PATH_MOCK_OWNER_SYSTEM ||
2170
+ mock_owner == GIT_PATH_MOCK_OWNER_CURRENT_USER);
2171
+ return 0;
2064
2172
  }
2065
2173
 
2174
+ if (file_owner_sid(&owner_sid, path) < 0)
2175
+ goto done;
2176
+
2066
2177
  if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
2067
2178
  IsWellKnownSid(owner_sid, WinLocalSystemSid)) {
2068
- ret = GIT_OK;
2069
- goto cleanup;
2070
- }
2071
-
2072
- /* Obtain current user's SID */
2073
- if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) &&
2074
- !GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
2075
- info = git__malloc(len);
2076
- GIT_ERROR_CHECK_ALLOC(info);
2077
- if (!GetTokenInformation(token, TokenUser, info, len, &len)) {
2078
- git__free(info);
2079
- info = NULL;
2179
+ *out = 1;
2180
+ error = 0;
2181
+ goto done;
2182
+ }
2183
+
2184
+ if (current_user_sid(&user_sid) < 0)
2185
+ goto done;
2186
+
2187
+ *out = EqualSid(owner_sid, user_sid);
2188
+ error = 0;
2189
+
2190
+ done:
2191
+ git__free(owner_sid);
2192
+ git__free(user_sid);
2193
+ return error;
2194
+ }
2195
+
2196
+ #else
2197
+
2198
+ static int path_owner_is(bool *out, const char *path, uid_t *uids, size_t uids_len)
2199
+ {
2200
+ struct stat st;
2201
+ size_t i;
2202
+
2203
+ *out = false;
2204
+
2205
+ if (p_lstat(path, &st) != 0) {
2206
+ if (errno == ENOENT)
2207
+ return GIT_ENOTFOUND;
2208
+
2209
+ git_error_set(GIT_ERROR_OS, "could not stat '%s'", path);
2210
+ return -1;
2211
+ }
2212
+
2213
+ for (i = 0; i < uids_len; i++) {
2214
+ if (uids[i] == st.st_uid) {
2215
+ *out = true;
2216
+ break;
2080
2217
  }
2081
2218
  }
2082
2219
 
2083
- /*
2084
- * If the file is owned by the same account that is running the current
2085
- * process, it's okay to read from that file.
2086
- */
2087
- if (info && EqualSid(owner_sid, info->User.Sid))
2088
- ret = GIT_OK;
2089
- else {
2090
- git_error_set(GIT_ERROR_INVALID, "programdata configuration file owner is not valid");
2091
- ret = GIT_ERROR;
2220
+ return 0;
2221
+ }
2222
+
2223
+ int git_path_owner_is_current_user(bool *out, const char *path)
2224
+ {
2225
+ uid_t userid = geteuid();
2226
+
2227
+ if (mock_owner) {
2228
+ *out = (mock_owner == GIT_PATH_MOCK_OWNER_CURRENT_USER);
2229
+ return 0;
2092
2230
  }
2093
- git__free(info);
2094
2231
 
2095
- cleanup:
2096
- if (descriptor)
2097
- LocalFree(descriptor);
2232
+ return path_owner_is(out, path, &userid, 1);
2233
+ }
2098
2234
 
2099
- return ret;
2100
- #endif
2235
+ int git_path_owner_is_system(bool *out, const char *path)
2236
+ {
2237
+ uid_t userid = 0;
2238
+
2239
+ if (mock_owner) {
2240
+ *out = (mock_owner == GIT_PATH_MOCK_OWNER_SYSTEM);
2241
+ return 0;
2242
+ }
2243
+
2244
+ return path_owner_is(out, path, &userid, 1);
2245
+ }
2246
+
2247
+ int git_path_owner_is_system_or_current_user(bool *out, const char *path)
2248
+ {
2249
+ uid_t userids[2] = { geteuid(), 0 };
2250
+
2251
+ if (mock_owner) {
2252
+ *out = (mock_owner == GIT_PATH_MOCK_OWNER_SYSTEM ||
2253
+ mock_owner == GIT_PATH_MOCK_OWNER_CURRENT_USER);
2254
+ return 0;
2255
+ }
2256
+
2257
+ return path_owner_is(out, path, userids, 2);
2101
2258
  }
2259
+
2260
+ #endif