11
#include "odb/source-loose.h"
12
#include "odb/streaming.h"
13
#include "oidtree.h"
14
+#include "path.h"
15
#include "repository.h"
16
#include "strbuf.h"
17
+#include "tempfile.h"
18
+#include "write-or-die.h"
19
20
static int append_loose_object(const struct object_id *oid,
21
const char *path UNUSED,
586
return !!check_and_freshen_file(path.buf, 1, mtime);
587
}
588
589
+/* Finalize a file on disk, and close it. */
590
+static void close_loose_object(struct odb_source_loose *loose,
591
+ int fd, const char *filename)
592
+{
593
+ if (loose->base.will_destroy)
594
+ goto out;
595
+
596
+ if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
597
+ odb_transaction_files_fsync(loose->base.odb->transaction, fd, filename);
598
+ else if (fsync_object_files > 0)
599
+ fsync_or_die(fd, filename);
600
+ else
601
+ fsync_component_or_die(FSYNC_COMPONENT_LOOSE_OBJECT, fd,
602
+ filename);
603
+
604
+out:
605
+ if (close(fd) != 0)
606
+ die_errno(_("error when closing loose object file"));
607
+}
608
+
609
+/* Size of directory component, including the ending '/' */
610
+static inline int directory_size(const char *filename)
611
+{
612
+ const char *s = strrchr(filename, '/');
613
+ if (!s)
614
+ return 0;
615
+ return s - filename + 1;
616
+}
617
+
618
+/*
619
+ * This creates a temporary file in the same directory as the final
620
+ * 'filename'
621
+ *
622
+ * We want to avoid cross-directory filename renames, because those
623
+ * can have problems on various filesystems (FAT, NFS, Coda).
624
+ */
625
+static int create_tmpfile(struct repository *repo,
626
+ struct strbuf *tmp, const char *filename)
627
+{
628
+ int fd, dirlen = directory_size(filename);
629
+
630
+ strbuf_reset(tmp);
631
+ strbuf_add(tmp, filename, dirlen);
632
+ strbuf_addstr(tmp, "tmp_obj_XXXXXX");
633
+ fd = git_mkstemp_mode(tmp->buf, 0444);
634
+ if (fd < 0 && dirlen && errno == ENOENT) {
635
+ /*
636
+ * Make sure the directory exists; note that the contents
637
+ * of the buffer are undefined after mkstemp returns an
638
+ * error, so we have to rewrite the whole buffer from
639
+ * scratch.
640
+ */
641
+ strbuf_reset(tmp);
642
+ strbuf_add(tmp, filename, dirlen - 1);
643
+ if (mkdir(tmp->buf, 0777) && errno != EEXIST)
644
+ return -1;
645
+ if (adjust_shared_perm(repo, tmp->buf))
646
+ return -1;
647
+
648
+ /* Try again */
649
+ strbuf_addstr(tmp, "/tmp_obj_XXXXXX");
650
+ fd = git_mkstemp_mode(tmp->buf, 0444);
651
+ }
652
+ return fd;
653
+}
654
+
655
+/**
656
+ * Common steps for loose object writers to start writing loose
657
+ * objects:
658
+ *
659
+ * - Create tmpfile for the loose object.
660
+ * - Setup zlib stream for compression.
661
+ * - Start to feed header to zlib stream.
662
+ *
663
+ * Returns a "fd", which should later be provided to
664
+ * end_loose_object_common().
665
+ */
666
+static int start_loose_object_common(struct odb_source_loose *loose,
667
+ struct strbuf *tmp_file,
668
+ const char *filename, unsigned flags,
669
+ git_zstream *stream,
670
+ unsigned char *buf, size_t buflen,
671
+ struct git_hash_ctx *c, struct git_hash_ctx *compat_c,
672
+ char *hdr, int hdrlen)
673
+{
674
+ const struct git_hash_algo *algo = loose->base.odb->repo->hash_algo;
675
+ const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo;
676
+ int fd;
677
+ struct repo_config_values *cfg = repo_config_values(loose->base.odb->repo);
678
+
679
+ fd = create_tmpfile(loose->base.odb->repo, tmp_file, filename);
680
+ if (fd < 0) {
681
+ if (flags & ODB_WRITE_OBJECT_SILENT)
682
+ return -1;
683
+ else if (errno == EACCES)
684
+ return error(_("insufficient permission for adding "
685
+ "an object to repository database %s"),
686
+ loose->base.path);
687
+ else
688
+ return error_errno(
689
+ _("unable to create temporary file"));
690
+ }
691
+
692
+ /* Setup zlib stream for compression */
693
+ git_deflate_init(stream, cfg->zlib_compression_level);
694
+ stream->next_out = buf;
695
+ stream->avail_out = buflen;
696
+ git_hash_init(c, algo);
697
+ if (compat && compat_c)
698
+ git_hash_init(compat_c, compat);
699
+
700
+ /* Start to feed header to zlib stream */
701
+ stream->next_in = (unsigned char *)hdr;
702
+ stream->avail_in = hdrlen;
703
+ while (git_deflate(stream, 0) == Z_OK)
704
+ ; /* nothing */
705
+ git_hash_update(c, hdr, hdrlen);
706
+ if (compat && compat_c)
707
+ git_hash_update(compat_c, hdr, hdrlen);
708
+
709
+ return fd;
710
+}
711
+
712
+/**
713
+ * Common steps for the inner git_deflate() loop for writing loose
714
+ * objects. Returns what git_deflate() returns.
715
+ */
716
+static int write_loose_object_common(struct odb_source_loose *loose,
717
+ struct git_hash_ctx *c, struct git_hash_ctx *compat_c,
718
+ git_zstream *stream, const int flush,
719
+ unsigned char *in0, const int fd,
720
+ unsigned char *compressed,
721
+ const size_t compressed_len)
722
+{
723
+ const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo;
724
+ int ret;
725
+
726
+ ret = git_deflate(stream, flush ? Z_FINISH : 0);
727
+ git_hash_update(c, in0, stream->next_in - in0);
728
+ if (compat && compat_c)
729
+ git_hash_update(compat_c, in0, stream->next_in - in0);
730
+ if (write_in_full(fd, compressed, stream->next_out - compressed) < 0)
731
+ die_errno(_("unable to write loose object file"));
732
+ stream->next_out = compressed;
733
+ stream->avail_out = compressed_len;
734
+
735
+ return ret;
736
+}
737
+
738
+/**
739
+ * Common steps for loose object writers to end writing loose objects:
740
+ *
741
+ * - End the compression of zlib stream.
742
+ * - Get the calculated oid to "oid".
743
+ */
744
+static int end_loose_object_common(struct odb_source_loose *loose,
745
+ struct git_hash_ctx *c, struct git_hash_ctx *compat_c,
746
+ git_zstream *stream, struct object_id *oid,
747
+ struct object_id *compat_oid)
748
+{
749
+ const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo;
750
+ int ret;
751
+
752
+ ret = git_deflate_end_gently(stream);
753
+ if (ret != Z_OK)
754
+ return ret;
755
+ git_hash_final_oid(oid, c);
756
+ if (compat && compat_c)
757
+ git_hash_final_oid(compat_oid, compat_c);
758
+
759
+ return Z_OK;
760
+}
761
+
762
+static int write_loose_object(struct odb_source_loose *loose,
763
+ const struct object_id *oid, char *hdr,
764
+ int hdrlen, const void *buf, unsigned long len,
765
+ const time_t *mtime, unsigned flags)
766
+{
767
+ int fd, ret;
768
+ unsigned char compressed[4096];
769
+ git_zstream stream;
770
+ struct git_hash_ctx c;
771
+ struct object_id parano_oid;
772
+ static struct strbuf tmp_file = STRBUF_INIT;
773
+ static struct strbuf filename = STRBUF_INIT;
774
+
775
+ if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
776
+ odb_transaction_files_prepare(loose->base.odb->transaction);
777
+
778
+ odb_loose_path(loose, &filename, oid);
779
+
780
+ fd = start_loose_object_common(loose, &tmp_file, filename.buf, flags,
781
+ &stream, compressed, sizeof(compressed),
782
+ &c, NULL, hdr, hdrlen);
783
+ if (fd < 0)
784
+ return -1;
785
+
786
+ /* Then the data itself.. */
787
+ stream.next_in = (void *)buf;
788
+ stream.avail_in = len;
789
+ do {
790
+ unsigned char *in0 = stream.next_in;
791
+
792
+ ret = write_loose_object_common(loose, &c, NULL, &stream, 1, in0, fd,
793
+ compressed, sizeof(compressed));
794
+ } while (ret == Z_OK);
795
+
796
+ if (ret != Z_STREAM_END)
797
+ die(_("unable to deflate new object %s (%d)"), oid_to_hex(oid),
798
+ ret);
799
+ ret = end_loose_object_common(loose, &c, NULL, &stream, ¶no_oid, NULL);
800
+ if (ret != Z_OK)
801
+ die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid),
802
+ ret);
803
+ if (!oideq(oid, ¶no_oid))
804
+ die(_("confused by unstable object source data for %s"),
805
+ oid_to_hex(oid));
806
+
807
+ close_loose_object(loose, fd, tmp_file.buf);
808
+
809
+ if (mtime) {
810
+ struct utimbuf utb = {
811
+ .actime = *mtime,
812
+ .modtime = *mtime,
813
+ };
814
+
815
+ if (utime(tmp_file.buf, &utb) < 0 &&
816
+ !(flags & ODB_WRITE_OBJECT_SILENT))
817
+ warning_errno(_("failed utime() on %s"), tmp_file.buf);
818
+ }
819
+
820
+ return finalize_object_file_flags(loose->base.odb->repo, tmp_file.buf, filename.buf,
821
+ FOF_SKIP_COLLISION_CHECK);
822
+}
823
+
824
static int odb_source_loose_write_object(struct odb_source *source,
825
const void *buf, size_t len,
826
enum object_type type,
849
size_t len,
850
struct object_id *oid)
851
{
852
+ struct odb_source_loose *loose = odb_source_loose_downcast(source);
853
+ const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo;
854
+ struct object_id compat_oid;
855
+ int fd, ret, err = 0, flush = 0;
856
+ unsigned char compressed[4096];
857
+ git_zstream stream;
858
+ struct git_hash_ctx c, compat_c;
859
+ struct strbuf tmp_file = STRBUF_INIT;
860
+ struct strbuf filename = STRBUF_INIT;
861
+ unsigned char buf[8192];
862
+ int dirlen;
863
+ char hdr[MAX_HEADER_LEN];
864
+ int hdrlen;
865
+
866
+ if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
867
+ odb_transaction_files_prepare(loose->base.odb->transaction);
868
+
869
+ /* Since oid is not determined, save tmp file to odb path. */
870
+ strbuf_addf(&filename, "%s/", loose->base.path);
871
+ hdrlen = format_object_header(hdr, sizeof(hdr), OBJ_BLOB, len);
872
+
873
/*
615
- * TODO: the implementation should be moved here, see the comment on
616
- * the called function in "object-file.h".
874
+ * Common steps for write_loose_object and stream_loose_object to
875
+ * start writing loose objects:
876
+ *
877
+ * - Create tmpfile for the loose object.
878
+ * - Setup zlib stream for compression.
879
+ * - Start to feed header to zlib stream.
880
*/
618
- struct odb_source_loose *loose = odb_source_loose_downcast(source);
619
- return odb_source_loose_write_stream(loose, in_stream, len, oid);
881
+ fd = start_loose_object_common(loose, &tmp_file, filename.buf, 0,
882
+ &stream, compressed, sizeof(compressed),
883
+ &c, &compat_c, hdr, hdrlen);
884
+ if (fd < 0) {
885
+ err = -1;
886
+ goto cleanup;
887
+ }
888
+
889
+ /* Then the data itself.. */
890
+ do {
891
+ unsigned char *in0 = stream.next_in;
892
+
893
+ if (!stream.avail_in && !in_stream->is_finished) {
894
+ ssize_t read_len = odb_write_stream_read(in_stream, buf,
895
+ sizeof(buf));
896
+ if (read_len < 0) {
897
+ close(fd);
898
+ err = -1;
899
+ goto cleanup;
900
+ }
901
+
902
+ stream.avail_in = read_len;
903
+ stream.next_in = buf;
904
+ in0 = buf;
905
+ /* All data has been read. */
906
+ if (in_stream->is_finished)
907
+ flush = 1;
908
+ }
909
+ ret = write_loose_object_common(loose, &c, &compat_c, &stream, flush, in0, fd,
910
+ compressed, sizeof(compressed));
911
+ /*
912
+ * Unlike write_loose_object(), we do not have the entire
913
+ * buffer. If we get Z_BUF_ERROR due to too few input bytes,
914
+ * then we'll replenish them in the next input_stream->read()
915
+ * call when we loop.
916
+ */
917
+ } while (ret == Z_OK || ret == Z_BUF_ERROR);
918
+
919
+ if (stream.total_in != len + hdrlen)
920
+ die(_("write stream object %"PRIuMAX" != %"PRIuMAX), (uintmax_t)stream.total_in,
921
+ (uintmax_t)len + hdrlen);
922
+
923
+ /*
924
+ * Common steps for write_loose_object and stream_loose_object to
925
+ * end writing loose object:
926
+ *
927
+ * - End the compression of zlib stream.
928
+ * - Get the calculated oid.
929
+ */
930
+ if (ret != Z_STREAM_END)
931
+ die(_("unable to stream deflate new object (%d)"), ret);
932
+ ret = end_loose_object_common(loose, &c, &compat_c, &stream, oid, &compat_oid);
933
+ if (ret != Z_OK)
934
+ die(_("deflateEnd on stream object failed (%d)"), ret);
935
+ close_loose_object(loose, fd, tmp_file.buf);
936
+
937
+ if (odb_freshen_object(loose->base.odb, oid)) {
938
+ unlink_or_warn(tmp_file.buf);
939
+ goto cleanup;
940
+ }
941
+ odb_loose_path(loose, &filename, oid);
942
+
943
+ /* We finally know the object path, and create the missing dir. */
944
+ dirlen = directory_size(filename.buf);
945
+ if (dirlen) {
946
+ struct strbuf dir = STRBUF_INIT;
947
+ strbuf_add(&dir, filename.buf, dirlen);
948
+
949
+ if (safe_create_dir_in_gitdir(loose->base.odb->repo, dir.buf) &&
950
+ errno != EEXIST) {
951
+ err = error_errno(_("unable to create directory %s"), dir.buf);
952
+ strbuf_release(&dir);
953
+ goto cleanup;
954
+ }
955
+ strbuf_release(&dir);
956
+ }
957
+
958
+ err = finalize_object_file_flags(loose->base.odb->repo, tmp_file.buf, filename.buf,
959
+ FOF_SKIP_COLLISION_CHECK);
960
+ if (!err && compat)
961
+ err = repo_add_loose_object_map(loose, oid, &compat_oid);
962
+cleanup:
963
+ strbuf_release(&tmp_file);
964
+ strbuf_release(&filename);
965
+ return err;
966
}
967
968
static int odb_source_loose_begin_transaction(struct odb_source *source UNUSED,