commit - 4da1bbe9cccd432c3afb675e07eedc58bc12ae31
commit + 20ccae39452cdf85f57023c8a7f029b0545adfa7
blob - 57b823a4f04403e0dfd1d1e79cc8fe80f6dbc79c
blob + 0c75579cb470e296c9a97a5ea0ac1e14f342971a
--- include/got_path.h
+++ include/got_path.h
#define GOT_DEFAULT_DIR_MODE (S_IFDIR | \
S_IRWXU | S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH)
+struct dirent;
+
/* Determine whether a path is an absolute path. */
int got_path_is_absolute(const char *);
/* dirname(3) with error handling and dynamically allocated result. */
const struct got_error *got_path_dirname(char **, const char *);
+/*
+ * Obtain the file type of a given directory entry.
+ *
+ * If the entry has some type other than DT_UNKNOWN, resolve to this type.
+ *
+ * Otherwise, attempt to resolve the type of a DT_UNKNOWN directory
+ * entry with lstat(2), though the result may still be DT_UNKNOWN.
+ * This is a fallback to accommodate filesystems which do not provide
+ * directory entry type information.
+ * DT_UNKNOWN directory entries occur on NFS mounts without "readdir plus" RPC.
+ */
+const struct got_error *got_path_dirent_type(int *, const char *,
+ struct dirent *);
+
/* basename(3) with dynamically allocated result. */
const struct got_error *got_path_basename(char **, const char *);
blob - 656685591bdfde81e5346507229c0bd87d2fa18c
blob + c3bd9dd19f3da3ee47a71c5a07cb1bf174eaf2d7
--- lib/fileindex.c
+++ lib/fileindex.c
struct dirent *de = dle->data;
DIR *subdir = NULL;
int subdirfd = -1;
+ int type;
*next = NULL;
- if (de->d_type == DT_DIR) {
+ if (de->d_type == DT_UNKNOWN) {
+ /* Occurs on NFS mounts without "readdir plus" RPC. */
+ char *dir_path;
+ if (asprintf(&dir_path, "%s/%s", rootpath, path) == -1)
+ return got_error_from_errno("asprintf");
+ err = got_path_dirent_type(&type, dir_path, de);
+ free(dir_path);
+ if (err)
+ return err;
+ } else
+ type = de->d_type;
+
+ if (type == DT_DIR) {
char *subpath;
char *subdirpath;
struct got_pathlist_head subdirlist;
blob - be971e697a2b76f0479272ad328aa87e1fe8450d
blob + 549cac5f15819dd3e37527467f02c394f51d5006
--- lib/path.c
+++ lib/path.c
}
const struct got_error *
+got_path_dirent_type(int *type, const char *path_parent, struct dirent *dent)
+{
+ const struct got_error *err = NULL;
+ char *path_child;
+ struct stat sb;
+
+ if (dent->d_type != DT_UNKNOWN) {
+ *type = dent->d_type;
+ return NULL;
+ }
+
+ *type = DT_UNKNOWN;
+
+ /*
+ * This is a fallback to accommodate filesystems which do not
+ * provide directory entry type information. DT_UNKNOWN directory
+ * entries occur on NFS mounts without "readdir plus" RPC.
+ */
+
+ if (asprintf(&path_child, "%s/%s", path_parent, dent->d_name) == -1)
+ return got_error_from_errno("asprintf");
+
+ if (lstat(path_child, &sb) == -1) {
+ err = got_error_from_errno2("lstat", path_child);
+ goto done;
+ }
+
+ if (S_ISFIFO(sb.st_mode))
+ *type = DT_FIFO;
+ else if (S_ISCHR(sb.st_mode))
+ *type = DT_CHR;
+ else if (S_ISDIR(sb.st_mode))
+ *type = DT_DIR;
+ else if (S_ISBLK(sb.st_mode))
+ *type = DT_BLK;
+ else if (S_ISLNK(sb.st_mode))
+ *type = DT_LNK;
+ else if (S_ISREG(sb.st_mode))
+ *type = DT_REG;
+ else if (S_ISSOCK(sb.st_mode))
+ *type = DT_SOCK;
+done:
+ free(path_child);
+ return err;
+}
+
+const struct got_error *
got_path_basename(char **s, const char *path)
{
char *base;
blob - a4aa416aa740d7f102a9b038776457ef3096c1e4
blob + 3c2632d04567f59182586129b87e15927dbe4b0d
--- lib/reference.c
+++ lib/reference.c
struct dirent *dent;
struct got_reference *ref;
char *child;
+ int type;
dent = readdir(d);
if (dent == NULL)
strcmp(dent->d_name, "..") == 0)
continue;
- switch (dent->d_type) {
+ err = got_path_dirent_type(&type, path_subdir, dent);
+ if (err)
+ break;
+
+ switch (type) {
case DT_REG:
err = open_ref(&ref, path_refs, subdir, dent->d_name,
0);
blob - 7531c15dc53560bdff8f322c2b1f6f3c61d849f4
blob + dec92533e2bad4d1d830b4d80f307bdc5314cb8a
--- lib/repository.c
+++ lib/repository.c
nentries = 0;
while ((de = readdir(dir)) != NULL) {
int ignore = 0;
+ int type;
if (strcmp(de->d_name, ".") == 0 ||
strcmp(de->d_name, "..") == 0)
}
if (ignore)
continue;
- if (de->d_type == DT_DIR) {
+
+ err = got_path_dirent_type(&type, path_dir, de);
+ if (err)
+ goto done;
+
+ if (type == DT_DIR) {
err = import_subdir(&new_te, de, path_dir,
ignores, repo, progress_cb, progress_arg);
if (err) {
err = NULL;
continue;
}
- } else if (de->d_type == DT_REG) {
+ } else if (type == DT_REG) {
err = import_file(&new_te, de, path_dir, repo);
if (err)
goto done;