1 #define USE_THE_REPOSITORY_VARIABLE
3 #include "git-compat-util.h"
4 #include "environment.h"
8 * Munge st_size into an unsigned int.
10 static unsigned int munge_st_size(off_t st_size
) {
11 unsigned int sd_size
= st_size
;
14 * If the file is an exact multiple of 4 GiB, modify the value so it
15 * doesn't get marked as racily clean (zero).
17 if (!sd_size
&& st_size
)
23 void fill_stat_data(struct stat_data
*sd
, struct stat
*st
)
25 sd
->sd_ctime
.sec
= (unsigned int)st
->st_ctime
;
26 sd
->sd_mtime
.sec
= (unsigned int)st
->st_mtime
;
27 sd
->sd_ctime
.nsec
= ST_CTIME_NSEC(*st
);
28 sd
->sd_mtime
.nsec
= ST_MTIME_NSEC(*st
);
29 sd
->sd_dev
= st
->st_dev
;
30 sd
->sd_ino
= st
->st_ino
;
31 sd
->sd_uid
= st
->st_uid
;
32 sd
->sd_gid
= st
->st_gid
;
33 sd
->sd_size
= munge_st_size(st
->st_size
);
36 static void set_times(struct stat
*st
, const struct stat_data
*sd
)
38 st
->st_ctime
= sd
->sd_ctime
.sec
;
39 st
->st_mtime
= sd
->sd_mtime
.sec
;
43 #ifdef USE_ST_TIMESPEC
44 st
->st_ctimespec
.tv_nsec
= sd
->sd_ctime
.nsec
;
45 st
->st_mtimespec
.tv_nsec
= sd
->sd_mtime
.nsec
;
47 st
->st_ctim
.tv_nsec
= sd
->sd_ctime
.nsec
;
48 st
->st_mtim
.tv_nsec
= sd
->sd_mtime
.nsec
;
53 void fake_lstat_data(const struct stat_data
*sd
, struct stat
*st
)
56 st
->st_dev
= sd
->sd_dev
;
57 st
->st_ino
= sd
->sd_ino
;
58 st
->st_uid
= sd
->sd_uid
;
59 st
->st_gid
= sd
->sd_gid
;
60 st
->st_size
= sd
->sd_size
;
63 int match_stat_data(const struct stat_data
*sd
, struct stat
*st
)
67 if (sd
->sd_mtime
.sec
!= (unsigned int)st
->st_mtime
)
68 changed
|= MTIME_CHANGED
;
69 if (trust_ctime
&& check_stat
&&
70 sd
->sd_ctime
.sec
!= (unsigned int)st
->st_ctime
)
71 changed
|= CTIME_CHANGED
;
74 if (check_stat
&& sd
->sd_mtime
.nsec
!= ST_MTIME_NSEC(*st
))
75 changed
|= MTIME_CHANGED
;
76 if (trust_ctime
&& check_stat
&&
77 sd
->sd_ctime
.nsec
!= ST_CTIME_NSEC(*st
))
78 changed
|= CTIME_CHANGED
;
82 if (sd
->sd_uid
!= (unsigned int) st
->st_uid
||
83 sd
->sd_gid
!= (unsigned int) st
->st_gid
)
84 changed
|= OWNER_CHANGED
;
85 if (sd
->sd_ino
!= (unsigned int) st
->st_ino
)
86 changed
|= INODE_CHANGED
;
91 * st_dev breaks on network filesystems where different
92 * clients will have different views of what "device"
93 * the filesystem is on
95 if (check_stat
&& sd
->sd_dev
!= (unsigned int) st
->st_dev
)
96 changed
|= INODE_CHANGED
;
99 if (sd
->sd_size
!= munge_st_size(st
->st_size
))
100 changed
|= DATA_CHANGED
;
105 void stat_validity_clear(struct stat_validity
*sv
)
107 FREE_AND_NULL(sv
->sd
);
110 int stat_validity_check(struct stat_validity
*sv
, const char *path
)
114 if (stat(path
, &st
) < 0)
115 return sv
->sd
== NULL
;
118 return S_ISREG(st
.st_mode
) && !match_stat_data(sv
->sd
, &st
);
121 void stat_validity_update(struct stat_validity
*sv
, int fd
)
125 if (fstat(fd
, &st
) < 0 || !S_ISREG(st
.st_mode
))
126 stat_validity_clear(sv
);
129 CALLOC_ARRAY(sv
->sd
, 1);
130 fill_stat_data(sv
->sd
, &st
);