/* Returns a connection state. S_OK if all is well. */ static inline struct connection_state list_directory(struct connection *conn, unsigned char *dirpath, struct string *page) { int show_hidden_files = get_opt_bool((const unsigned char *)"protocol.file.show_hidden_files", NULL); struct directory_entry *entries; struct connection_state state; errno = 0; entries = get_directory_entries(dirpath, show_hidden_files); if (!entries) { if (errno) return connection_state_for_errno(errno); return connection_state(S_OUT_OF_MEM); } state = init_directory_listing(page, conn->uri); if (!is_in_state(state, S_OK)) return connection_state(S_OUT_OF_MEM); add_dir_entries(entries, dirpath, page); if (!add_to_string(page, (const unsigned char *)"</pre>\n<hr/>\n</body>\n</html>\n")) { done_string(page); return connection_state(S_OUT_OF_MEM); } return connection_state(S_OK); }
/* Recursively scan the directory identified by ST. */ struct directory * scan_directory (struct tar_stat_info *st) { char const *dir = st->orig_file_name; char *dirp = get_directory_entries (st); dev_t device = st->stat.st_dev; bool cmdline = ! st->parent; namebuf_t nbuf; char *tmp; struct directory *directory; char ch; if (! dirp) savedir_error (dir); info_attach_exclist (st); tmp = xstrdup (dir); zap_slashes (tmp); directory = procdir (tmp, st, (cmdline ? PD_FORCE_INIT : 0), &ch); free (tmp); nbuf = namebuf_create (dir); if (dirp) { if (directory->children != NO_CHILDREN) { char *entry; /* directory entry being scanned */ struct dumpdir_iter *itr; makedumpdir (directory, dirp); for (entry = dumpdir_first (directory->dump, 1, &itr); entry; entry = dumpdir_next (itr)) { char *full_name = namebuf_name (nbuf, entry + 1); if (*entry == 'I') /* Ignored entry */ *entry = 'N'; else if (excluded_name (full_name, st)) *entry = 'N'; else { int fd = st->fd; void (*diag) (char const *) = 0; struct tar_stat_info stsub; tar_stat_init (&stsub); if (fd < 0) { errno = - fd; diag = open_diag; } else if (fstatat (fd, entry + 1, &stsub.stat, fstatat_flags) != 0) diag = stat_diag; else if (S_ISDIR (stsub.stat.st_mode)) { int subfd = subfile_open (st, entry + 1, open_read_flags); if (subfd < 0) diag = open_diag; else { stsub.fd = subfd; if (fstat (subfd, &stsub.stat) != 0) diag = stat_diag; } } if (diag) { file_removed_diag (full_name, false, diag); *entry = 'N'; } else if (S_ISDIR (stsub.stat.st_mode)) { int pd_flag = 0; if (!recursion_option) pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN; else if (directory->children == ALL_CHILDREN) pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN; *entry = 'D'; stsub.parent = st; procdir (full_name, &stsub, pd_flag, entry); restore_parent_fd (&stsub); } else if (one_file_system_option && device != stsub.stat.st_dev) *entry = 'N'; else if (*entry == 'Y') /* New entry, skip further checks */; /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */ else if (OLDER_STAT_TIME (stsub.stat, m) && (!after_date_option || OLDER_STAT_TIME (stsub.stat, c))) *entry = 'N'; else *entry = 'Y'; tar_stat_destroy (&stsub); } } free (itr); } else if (directory->tagfile) maketagdumpdir (directory); } namebuf_free (nbuf); free (dirp); return directory; }