rugged 1.2.0 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
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