+ return (unsigned long)ptr > (unsigned long)-1000L;
+}
+
+static int add_file_to_cache(char *path)
+{
+ int size, namelen, option, status;
+ struct cache_entry *ce;
+ struct stat st;
+ int fd;
+ char *target;
+
+ status = lstat(path, &st);
+ if (status < 0 || S_ISDIR(st.st_mode)) {
+ /* When we used to have "path" and now we want to add
+ * "path/file", we need a way to remove "path" before
+ * being able to add "path/file". However,
+ * "git-update-cache --remove path" would not work.
+ * --force-remove can be used but this is more user
+ * friendly, especially since we can do the opposite
+ * case just fine without --force-remove.
+ */
+ if (status == 0 || (errno == ENOENT || errno == ENOTDIR)) {
+ if (allow_remove)
+ return remove_file_from_cache(path);
+ }
+ return error("open(\"%s\"): %s", path, strerror(errno));
+ }
+ namelen = strlen(path);
+ size = cache_entry_size(namelen);
+ ce = xmalloc(size);
+ memset(ce, 0, size);
+ memcpy(ce->name, path, namelen);
+ fill_stat_cache_info(ce, &st);
+ ce->ce_mode = create_ce_mode(st.st_mode);
+ ce->ce_flags = htons(namelen);
+ switch (st.st_mode & S_IFMT) {
+ case S_IFREG:
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ if (index_fd(ce->sha1, fd, &st, !info_only, NULL) < 0)
+ return -1;
+ break;
+ case S_IFLNK:
+ target = xmalloc(st.st_size+1);
+ if (readlink(path, target, st.st_size+1) != st.st_size) {
+ free(target);
+ return -1;