+/*
+ * This only updates the "non-critical" parts of the directory
+ * cache, ie the parts that aren't tracked by GIT, and only used
+ * to validate the cache.
+ */
+void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
+{
+ ce->ce_ctime.sec = htonl(st->st_ctime);
+ ce->ce_mtime.sec = htonl(st->st_mtime);
+#ifdef USE_NSEC
+ ce->ce_ctime.nsec = htonl(st->st_ctim.tv_nsec);
+ ce->ce_mtime.nsec = htonl(st->st_mtim.tv_nsec);
+#endif
+ ce->ce_dev = htonl(st->st_dev);
+ ce->ce_ino = htonl(st->st_ino);
+ ce->ce_uid = htonl(st->st_uid);
+ ce->ce_gid = htonl(st->st_gid);
+ ce->ce_size = htonl(st->st_size);
+}
+
+static int ce_compare_data(struct cache_entry *ce, struct stat *st)
+{
+ int match = -1;
+ int fd = open(ce->name, O_RDONLY);
+
+ if (fd >= 0) {
+ unsigned char sha1[20];
+ if (!index_fd(sha1, fd, st, 0, NULL))
+ match = memcmp(sha1, ce->sha1, 20);
+ close(fd);
+ }
+ return match;
+}
+
+static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size)
+{
+ int match = -1;
+ char *target;
+ void *buffer;
+ unsigned long size;
+ char type[10];
+ int len;
+
+ target = xmalloc(expected_size);
+ len = readlink(ce->name, target, expected_size);
+ if (len != expected_size) {
+ free(target);
+ return -1;
+ }
+ buffer = read_sha1_file(ce->sha1, type, &size);
+ if (!buffer) {
+ free(target);
+ return -1;
+ }
+ if (size == expected_size)
+ match = memcmp(buffer, target, size);
+ free(buffer);
+ free(target);
+ return match;
+}
+
+static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
+{
+ switch (st->st_mode & S_IFMT) {
+ case S_IFREG:
+ if (ce_compare_data(ce, st))
+ return DATA_CHANGED;
+ break;
+ case S_IFLNK:
+ if (ce_compare_link(ce, st->st_size))
+ return DATA_CHANGED;
+ break;
+ default:
+ return TYPE_CHANGED;
+ }
+ return 0;
+}
+
+static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)