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 static void set_times(struct stat
*st
, const struct stat_data
*sd
)
36 st
->st_ctime
= sd
->sd_ctime
.sec
;
37 st
->st_mtime
= sd
->sd_mtime
.sec
;
41 #ifdef USE_ST_TIMESPEC
42 st
->st_ctimespec
.tv_nsec
= sd
->sd_ctime
.nsec
;
43 st
->st_mtimespec
.tv_nsec
= sd
->sd_mtime
.nsec
;
45 st
->st_ctim
.tv_nsec
= sd
->sd_ctime
.nsec
;
46 st
->st_mtim
.tv_nsec
= sd
->sd_mtime
.nsec
;
51 void fake_lstat_data(const struct stat_data
*sd
, struct stat
*st
)
54 st
->st_dev
= sd
->sd_dev
;
55 st
->st_ino
= sd
->sd_ino
;
56 st
->st_uid
= sd
->sd_uid
;
57 st
->st_gid
= sd
->sd_gid
;
58 st
->st_size
= sd
->sd_size
;
61 int match_stat_data(const struct stat_data
*sd
, struct stat
*st
)
65 if (sd
->sd_mtime
.sec
!= (unsigned int)st
->st_mtime
)
66 changed
|= MTIME_CHANGED
;
67 if (trust_ctime
&& check_stat
&&
68 sd
->sd_ctime
.sec
!= (unsigned int)st
->st_ctime
)
69 changed
|= CTIME_CHANGED
;
72 if (check_stat
&& sd
->sd_mtime
.nsec
!= ST_MTIME_NSEC(*st
))
73 changed
|= MTIME_CHANGED
;
74 if (trust_ctime
&& check_stat
&&
75 sd
->sd_ctime
.nsec
!= ST_CTIME_NSEC(*st
))
76 changed
|= CTIME_CHANGED
;
80 if (sd
->sd_uid
!= (unsigned int) st
->st_uid
||
81 sd
->sd_gid
!= (unsigned int) st
->st_gid
)
82 changed
|= OWNER_CHANGED
;
83 if (sd
->sd_ino
!= (unsigned int) st
->st_ino
)
84 changed
|= INODE_CHANGED
;
89 * st_dev breaks on network filesystems where different
90 * clients will have different views of what "device"
91 * the filesystem is on
93 if (check_stat
&& sd
->sd_dev
!= (unsigned int) st
->st_dev
)
94 changed
|= INODE_CHANGED
;
97 if (sd
->sd_size
!= munge_st_size(st
->st_size
))
98 changed
|= DATA_CHANGED
;
103 void stat_validity_clear(struct stat_validity
*sv
)
105 FREE_AND_NULL(sv
->sd
);
108 int stat_validity_check(struct stat_validity
*sv
, const char *path
)
112 if (stat(path
, &st
) < 0)
113 return sv
->sd
== NULL
;
116 return S_ISREG(st
.st_mode
) && !match_stat_data(sv
->sd
, &st
);
119 void stat_validity_update(struct stat_validity
*sv
, int fd
)
123 if (fstat(fd
, &st
) < 0 || !S_ISREG(st
.st_mode
))
124 stat_validity_clear(sv
);
127 CALLOC_ARRAY(sv
->sd
, 1);
128 fill_stat_data(sv
->sd
, &st
);