88 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C
		
	
	
#include "git-compat-util.h"
 | 
						|
#include "environment.h"
 | 
						|
#include "statinfo.h"
 | 
						|
 | 
						|
void fill_stat_data(struct stat_data *sd, struct stat *st)
 | 
						|
{
 | 
						|
	sd->sd_ctime.sec = (unsigned int)st->st_ctime;
 | 
						|
	sd->sd_mtime.sec = (unsigned int)st->st_mtime;
 | 
						|
	sd->sd_ctime.nsec = ST_CTIME_NSEC(*st);
 | 
						|
	sd->sd_mtime.nsec = ST_MTIME_NSEC(*st);
 | 
						|
	sd->sd_dev = st->st_dev;
 | 
						|
	sd->sd_ino = st->st_ino;
 | 
						|
	sd->sd_uid = st->st_uid;
 | 
						|
	sd->sd_gid = st->st_gid;
 | 
						|
	sd->sd_size = st->st_size;
 | 
						|
}
 | 
						|
 | 
						|
int match_stat_data(const struct stat_data *sd, struct stat *st)
 | 
						|
{
 | 
						|
	int changed = 0;
 | 
						|
 | 
						|
	if (sd->sd_mtime.sec != (unsigned int)st->st_mtime)
 | 
						|
		changed |= MTIME_CHANGED;
 | 
						|
	if (trust_ctime && check_stat &&
 | 
						|
	    sd->sd_ctime.sec != (unsigned int)st->st_ctime)
 | 
						|
		changed |= CTIME_CHANGED;
 | 
						|
 | 
						|
#ifdef USE_NSEC
 | 
						|
	if (check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
 | 
						|
		changed |= MTIME_CHANGED;
 | 
						|
	if (trust_ctime && check_stat &&
 | 
						|
	    sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
 | 
						|
		changed |= CTIME_CHANGED;
 | 
						|
#endif
 | 
						|
 | 
						|
	if (check_stat) {
 | 
						|
		if (sd->sd_uid != (unsigned int) st->st_uid ||
 | 
						|
			sd->sd_gid != (unsigned int) st->st_gid)
 | 
						|
			changed |= OWNER_CHANGED;
 | 
						|
		if (sd->sd_ino != (unsigned int) st->st_ino)
 | 
						|
			changed |= INODE_CHANGED;
 | 
						|
	}
 | 
						|
 | 
						|
#ifdef USE_STDEV
 | 
						|
	/*
 | 
						|
	 * st_dev breaks on network filesystems where different
 | 
						|
	 * clients will have different views of what "device"
 | 
						|
	 * the filesystem is on
 | 
						|
	 */
 | 
						|
	if (check_stat && sd->sd_dev != (unsigned int) st->st_dev)
 | 
						|
			changed |= INODE_CHANGED;
 | 
						|
#endif
 | 
						|
 | 
						|
	if (sd->sd_size != (unsigned int) st->st_size)
 | 
						|
		changed |= DATA_CHANGED;
 | 
						|
 | 
						|
	return changed;
 | 
						|
}
 | 
						|
 | 
						|
void stat_validity_clear(struct stat_validity *sv)
 | 
						|
{
 | 
						|
	FREE_AND_NULL(sv->sd);
 | 
						|
}
 | 
						|
 | 
						|
int stat_validity_check(struct stat_validity *sv, const char *path)
 | 
						|
{
 | 
						|
	struct stat st;
 | 
						|
 | 
						|
	if (stat(path, &st) < 0)
 | 
						|
		return sv->sd == NULL;
 | 
						|
	if (!sv->sd)
 | 
						|
		return 0;
 | 
						|
	return S_ISREG(st.st_mode) && !match_stat_data(sv->sd, &st);
 | 
						|
}
 | 
						|
 | 
						|
void stat_validity_update(struct stat_validity *sv, int fd)
 | 
						|
{
 | 
						|
	struct stat st;
 | 
						|
 | 
						|
	if (fstat(fd, &st) < 0 || !S_ISREG(st.st_mode))
 | 
						|
		stat_validity_clear(sv);
 | 
						|
	else {
 | 
						|
		if (!sv->sd)
 | 
						|
			CALLOC_ARRAY(sv->sd, 1);
 | 
						|
		fill_stat_data(sv->sd, &st);
 | 
						|
	}
 | 
						|
}
 |