1 #include "git-compat-util.h"
2 #include "environment.h"
6 * Munge st_size into an unsigned int.
8 static unsigned int munge_st_size(off_t st_size
) {
9 unsigned int sd_size
= st_size
;
12 * If the file is an exact multiple of 4 GiB, modify the value so it
13 * doesn't get marked as racily clean (zero).
15 if (!sd_size
&& st_size
)
21 void fill_stat_data(struct stat_data
*sd
, struct stat
*st
)
23 sd
->sd_ctime
.sec
= (unsigned int)st
->st_ctime
;
24 sd
->sd_mtime
.sec
= (unsigned int)st
->st_mtime
;
25 sd
->sd_ctime
.nsec
= ST_CTIME_NSEC(*st
);
26 sd
->sd_mtime
.nsec
= ST_MTIME_NSEC(*st
);
27 sd
->sd_dev
= st
->st_dev
;
28 sd
->sd_ino
= st
->st_ino
;
29 sd
->sd_uid
= st
->st_uid
;
30 sd
->sd_gid
= st
->st_gid
;
31 sd
->sd_size
= munge_st_size(st
->st_size
);
34 int match_stat_data(const struct stat_data
*sd
, struct stat
*st
)
38 if (sd
->sd_mtime
.sec
!= (unsigned int)st
->st_mtime
)
39 changed
|= MTIME_CHANGED
;
40 if (trust_ctime
&& check_stat
&&
41 sd
->sd_ctime
.sec
!= (unsigned int)st
->st_ctime
)
42 changed
|= CTIME_CHANGED
;
45 if (check_stat
&& sd
->sd_mtime
.nsec
!= ST_MTIME_NSEC(*st
))
46 changed
|= MTIME_CHANGED
;
47 if (trust_ctime
&& check_stat
&&
48 sd
->sd_ctime
.nsec
!= ST_CTIME_NSEC(*st
))
49 changed
|= CTIME_CHANGED
;
53 if (sd
->sd_uid
!= (unsigned int) st
->st_uid
||
54 sd
->sd_gid
!= (unsigned int) st
->st_gid
)
55 changed
|= OWNER_CHANGED
;
56 if (sd
->sd_ino
!= (unsigned int) st
->st_ino
)
57 changed
|= INODE_CHANGED
;
62 * st_dev breaks on network filesystems where different
63 * clients will have different views of what "device"
64 * the filesystem is on
66 if (check_stat
&& sd
->sd_dev
!= (unsigned int) st
->st_dev
)
67 changed
|= INODE_CHANGED
;
70 if (sd
->sd_size
!= munge_st_size(st
->st_size
))
71 changed
|= DATA_CHANGED
;
76 void stat_validity_clear(struct stat_validity
*sv
)
78 FREE_AND_NULL(sv
->sd
);
81 int stat_validity_check(struct stat_validity
*sv
, const char *path
)
85 if (stat(path
, &st
) < 0)
86 return sv
->sd
== NULL
;
89 return S_ISREG(st
.st_mode
) && !match_stat_data(sv
->sd
, &st
);
92 void stat_validity_update(struct stat_validity
*sv
, int fd
)
96 if (fstat(fd
, &st
) < 0 || !S_ISREG(st
.st_mode
))
97 stat_validity_clear(sv
);
100 CALLOC_ARRAY(sv
->sd
, 1);
101 fill_stat_data(sv
->sd
, &st
);