@@ -596,7 +596,8 @@ static int unuse_one_window(struct packed_git *current, int keep_fd)
596
596
lru_l -> next = lru_w -> next ;
597
597
else {
598
598
lru_p -> windows = lru_w -> next ;
599
- if (!lru_p -> windows && lru_p -> pack_fd != keep_fd ) {
599
+ if (!lru_p -> windows && lru_p -> pack_fd != -1
600
+ && lru_p -> pack_fd != keep_fd ) {
600
601
close (lru_p -> pack_fd );
601
602
pack_open_fds -- ;
602
603
lru_p -> pack_fd = -1 ;
@@ -812,14 +813,13 @@ unsigned char *use_pack(struct packed_git *p,
812
813
{
813
814
struct pack_window * win = * w_cursor ;
814
815
815
- if (p -> pack_fd == -1 && open_packed_git (p ))
816
- die ("packfile %s cannot be accessed" , p -> pack_name );
817
-
818
816
/* Since packfiles end in a hash of their content and it's
819
817
* pointless to ask for an offset into the middle of that
820
818
* hash, and the in_window function above wouldn't match
821
819
* don't allow an offset too close to the end of the file.
822
820
*/
821
+ if (!p -> pack_size && p -> pack_fd == -1 && open_packed_git (p ))
822
+ die ("packfile %s cannot be accessed" , p -> pack_name );
823
823
if (offset > (p -> pack_size - 20 ))
824
824
die ("offset beyond end of packfile (truncated pack?)" );
825
825
@@ -833,6 +833,10 @@ unsigned char *use_pack(struct packed_git *p,
833
833
if (!win ) {
834
834
size_t window_align = packed_git_window_size / 2 ;
835
835
off_t len ;
836
+
837
+ if (p -> pack_fd == -1 && open_packed_git (p ))
838
+ die ("packfile %s cannot be accessed" , p -> pack_name );
839
+
836
840
win = xcalloc (1 , sizeof (* win ));
837
841
win -> offset = (offset / window_align ) * window_align ;
838
842
len = p -> pack_size - win -> offset ;
@@ -850,6 +854,12 @@ unsigned char *use_pack(struct packed_git *p,
850
854
die ("packfile %s cannot be mapped: %s" ,
851
855
p -> pack_name ,
852
856
strerror (errno ));
857
+ if (!win -> offset && win -> len == p -> pack_size
858
+ && !p -> do_not_close ) {
859
+ close (p -> pack_fd );
860
+ pack_open_fds -- ;
861
+ p -> pack_fd = -1 ;
862
+ }
853
863
pack_mmap_calls ++ ;
854
864
pack_open_windows ++ ;
855
865
if (pack_mapped > peak_pack_mapped )
@@ -1950,6 +1960,27 @@ off_t find_pack_entry_one(const unsigned char *sha1,
1950
1960
return 0 ;
1951
1961
}
1952
1962
1963
+ static int is_pack_valid (struct packed_git * p )
1964
+ {
1965
+ /* An already open pack is known to be valid. */
1966
+ if (p -> pack_fd != -1 )
1967
+ return 1 ;
1968
+
1969
+ /* If the pack has one window completely covering the
1970
+ * file size, the pack is known to be valid even if
1971
+ * the descriptor is not currently open.
1972
+ */
1973
+ if (p -> windows ) {
1974
+ struct pack_window * w = p -> windows ;
1975
+
1976
+ if (!w -> offset && w -> len == p -> pack_size )
1977
+ return 1 ;
1978
+ }
1979
+
1980
+ /* Force the pack to open to prove its valid. */
1981
+ return !open_packed_git (p );
1982
+ }
1983
+
1953
1984
static int find_pack_entry (const unsigned char * sha1 , struct pack_entry * e )
1954
1985
{
1955
1986
static struct packed_git * last_found = (void * )1 ;
@@ -1979,7 +2010,7 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
1979
2010
* it may have been deleted since the index
1980
2011
* was loaded!
1981
2012
*/
1982
- if (p -> pack_fd == -1 && open_packed_git (p )) {
2013
+ if (! is_pack_valid (p )) {
1983
2014
error ("packfile %s cannot be accessed" , p -> pack_name );
1984
2015
goto next ;
1985
2016
}
0 commit comments