- /* Lisp functions for making directory listings.
+/* Lisp functions for making directory listings.
Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of SXEmacs
#endif
#define USE_D_TYPE 1
-#define USE_MATCH_ARG 1
Lisp_Object Vcompletion_ignored_extensions;
Lisp_Object Vdirectory_files_no_trivial_p;
Lisp_Object Qcompanion_bf;
Lisp_Object Qsorted_list, Qdesc_sorted_list, Qunsorted_list;
+Lisp_Object Qmatch_full;
Lisp_Object Qnoncyclic_directory, Qcyclic_directory;
Lisp_Object Qsymlink, Qalive_symlink, Qdead_symlink;
Lisp_Object Qwhiteout;
long unsigned int maxdepth;
_Bool fullp:1;
_Bool symlink_file_p:1;
+ _Bool matchfullp:1;
};
static Lisp_Object fname_as_directory(Lisp_Object);
static char *
dired_realpath(const char *file)
{
- char *result = xmalloc_atomic(4096);
-
- realpath(file, result);
+ char *result = xmalloc_atomic(4096);
+ if ( xrealpath(file, result) == NULL ) {
+ xfree(result);
+ result = NULL;
+ }
return result;
}
#endif
* store it to our companion bloom filter
*/
canon_name = CANONICALISE_FILENAME(statnam);
-
- /* now, recycle full name */
- fullname = make_ext_string(
- canon_name, strlen(canon_name), Qfile_name);
+ if (canon_name) {
+ /* now, recycle full name */
+ fullname = make_ext_string(
+ canon_name, strlen(canon_name), Qfile_name);
+ }
fullname = fname_as_directory(fullname);
/* now stat statnam */
}
#else /* defined(_DIRENT_HAVE_D_TYPE) && USE_D_TYPE */
statnam = (char*)XSTRING_DATA(fullname);
- if (sxemacs_stat(statnam, &st) == 0 &&
- (st.st_mode & S_IFMT) == S_IFDIR) {
- char *canon_name = NULL;
-
- /* ugly things may happen when a link
- * points back to a directory in our recurring
- * area, ln -s . foo is a candidate
- * now, we canonicalise the filename, i.e.
- * resolve all symlinks and afterwards we
- * store it to our companion bloom filter
- * The ugly things are even worse than in the
- * case of D_TYPE, since we !always! have to
- * check against the bloom filter.
- */
- canon_name = CANONICALISE_FILENAME(statnam);
-
- /* now, recycle full name */
- fullname = make_ext_string(
- canon_name, strlen(canon_name),
- Qfile_name);
- fullname = fname_as_directory(fullname);
-
- /* now stat statnam */
- if (sxemacs_stat(statnam, &st) == 0 &&
- (st.st_mode & S_IFMT) == S_IFDIR &&
- /* does the bloom know about the dir? */
- !NILP(compbf) &&
- !(bloom_owns_p(XBLOOM(compbf), fullname))) {
+ if (lstat(statnam, &st) == 0) {
+ if ((st.st_mode & S_IFMT) == S_IFDIR) {
dir_p = 1;
- }
+ } else if ((st.st_mode & S_IFMT) == S_IFLNK && !opts->symlink_file_p) {
+ char *canon_name = NULL;
+
+ /* ugly things may happen when a link
+ * points back to a directory in our recurring
+ * area, ln -s . foo is a candidate
+ * now, we canonicalise the filename, i.e.
+ * resolve all symlinks and afterwards we
+ * store it to our companion bloom filter
+ * The ugly things are even worse than in the
+ * case of D_TYPE, since we !always! have to
+ * check against the bloom filter.
+ */
+ canon_name = CANONICALISE_FILENAME(statnam);
+
+ if (canon_name) {
+ /* now, recycle full name */
+ fullname = make_ext_string(
+ canon_name, strlen(canon_name),
+ Qfile_name);
+ }
+ fullname = fname_as_directory(fullname);
+
+ /* now stat statnam */
+ if (sxemacs_stat(statnam, &st) == 0 &&
+ (st.st_mode & S_IFMT) == S_IFDIR &&
+ /* does the bloom know about the dir? */
+ !NILP(compbf) &&
+ !(bloom_owns_p(XBLOOM(compbf), fullname))) {
+ dir_p = 1;
+ }
- if (canon_name) {
- xfree(canon_name);
+ if (canon_name) {
+ xfree(canon_name);
+ }
}
}
+
#endif /* defined(_DIRENT_HAVE_D_TYPE) && USE_D_TYPE */
/* argh, here is a design flaw!
- With the former variant it is NOT possible to have
the trivial filenames on the result list, since a
match against "^[.]$" would exclude everything, while
- actually it was likely meant to _solely_ exclude "."
+ actually it was likely meant to _solely_ exclude "."
from the result list
- Furthermore, we _MUST_ traverse in preorder,
otherwise there is the possibility that pathnames are
dired_stack_push(ds, dsi);
}
-#if USE_MATCH_ARG
- if (!NILP(match) && !pathname_matches_p(name, match, bufp)) {
+ if (result_p && !NILP(match)
+ && !pathname_matches_p((opts->matchfullp?fullname:name),
+ match, bufp)) {
result_p = 0;
}
-#endif
if (result_p) {
dllist_append(XDLLIST(result), (void*)resname);
* processing an entry twice */
Lisp_Object compbf = Qnil;
int speccount = specpdl_depth();
-#if USE_MATCH_ARG
struct re_pattern_buffer *bufp = NULL;
-#endif
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
ds = new_dired_stack();
set_dynacat_finaliser(lds, (dynacat_finaliser_f)dired_stack_fini);
GCPRO5(directory, result, compbf, bloom_filter, lds);
-#if USE_MATCH_ARG
/* SXEmacs: this should come after Ffile_name_as_directory() to avoid
potential regexp cache smashage. It comes before the opendir()
because it might signal an error. */
regex_match_object = Qnil;
regex_emacs_buffer = current_buffer;
-#endif
if (opts->maxdepth > 0) {
compbf = make_bloom(8192, 8);
} else if (EQ(result_type, Qdesc_sorted_list)) {
final_result = Fdllist_to_list(result);
final_result = Fsort(final_result, Qstring_greaterp);
- } else if (EQ(result_type, Qt) || EQ(result_type, Qlist)) {
+ } else if (!NILP(result_type) || EQ(result_type, Qlist)) {
final_result = Fdllist_to_list(result);
}
\f
EXFUN(Fdirectory_files_recur, 8);
-DEFUN("directory-files", Fdirectory_files, 1, 5, 0, /*
+DEFUN("directory-files", Fdirectory_files, 1, 7, 0, /*
Return a list of names of files in DIRECTORY.
-Args are DIRECTORY &optional FULL MATCH RESULT-TYPE FILES_ONLY.
+Args are DIRECTORY &optional FULL MATCH RESULT-TYPE FILES_ONLY
+SYMLINK_IS_FILE BLOOM_FILTER
There are four optional arguments:
-If FULL is non-nil, absolute pathnames of the files are returned.
+FULL can be one of:
+- t to return absolute pathnames of the files.
+- match-full to return and match on absolute pathnames of the files.
+- nil to return relative filenames.
If MATCH is non-nil, it may be a string indicating a regular
expression which pathnames must meet in order to be returned.
Moreover, a predicate function can be specified which is called with
-one argument, the pathname in question. On non-nil return value,
-the pathname is considered in the final result, otherwise it is
-ignored.
+one argument, the pathname in question. On non-nil return value, the
+pathname is considered in the final result, otherwise it is ignored.
+Note that FULL affects whether the match is done on the filename of
+the full pathname.
Optional argument RESULT-TYPE can be one of:
- sorted-list (default) to return a list, sorted in alphabetically
The two latter types can be useful if you plan to sort the result
yourself, or want to feed the result to further processing.
+For compatibility with XEmacs' NOSORT argument to this function,
+RESULT-TYPE can also be any non-nil value. In that case it will
+return an unsorted list. (https://issues.sxemacs.org/show_bug.cgi?id=163)
+
Optional argument FILES-ONLY can be one of:
- t to return only files and symlinks in DIRECTORY
- nil (default) to return all entries (files, symlinks, and
subdirectories) in DIRECTORY
- subdir to return only subdirectories -- but *NOT* symlinks to
directories -- in DIRECTORY
+
+Optional argument SYMLINK-IS-FILE specifies whether symlinks
+should be resolved \(which is the default behaviour\) or whether
+they are treated as ordinary files \(non-nil\), in the latter
+case symlinks to directories are not recurred.
+
+Optional argument BLOOM-FILTER specifies a bloom filter where
+to put results in addition to the ordinary result list.
*/
- (directory, full, match, result_type, files_only))
+ (directory, full, match, result_type, files_only,
+ symlink_is_file, bloom_filter))
{
- Lisp_Object handler;
+ Lisp_Object handler = Qnil;
Lisp_Object result = Qnil;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
+#if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
+ /* just a convenience array for gc pro'ing */
+ Lisp_Object args[8] = {
+ directory, match, result_type, files_only,
+ symlink_is_file, bloom_filter, handler, result};
+#endif /* !BDWGC */
struct dfr_options_s opts = {
.maxdepth = 0,
.fullp = !NILP(full),
- .symlink_file_p = 0,
+ .symlink_file_p = !NILP(symlink_is_file),
+ .matchfullp = EQ(full,Qmatch_full),
};
- GCPRO6(directory, full, match, result_type, files_only, result);
+ struct gcpro gcpro1;
+
+ /* argument checks */
+ CHECK_STRING(directory);
+
+ GCPROn(args, countof(args));
directory = directory_files_canonicalise_dn(directory);
handler = Ffind_file_name_handler(directory, Qdirectory_files);
if (!NILP(handler)) {
UNGCPRO;
- return call6(handler, Qdirectory_files,
- directory, full, match, result_type, files_only);
+ return call8(handler, Qdirectory_files,
+ directory, full, match, result_type, files_only,
+ symlink_is_file, bloom_filter);
}
result = directory_files_magic(directory, match,
- files_only, /* bloom filter */Qnil,
+ files_only, bloom_filter,
&opts);
UNGCPRO;
Args are DIRECTORY &optional FULL MATCH RESULT_TYPE FILES-ONLY MAXDEPTH
SYMLINK_IS_FILE BLOOM_FILTER
-If FULL is non-nil, absolute pathnames of the files are returned.
+FULL can be one of:
+- t to return absolute pathnames of the files.
+- match-full to return and match on absolute pathnames of the files.
+- nil to return relative filenames.
If MATCH is non-nil, it may be a string indicating a regular
expression which pathnames must meet in order to be returned.
Moreover, a predicate function can be specified which is called with
-one argument, the pathname in question. On non-nil return value,
-the pathname is considered in the final result, otherwise it is
-ignored.
+one argument, the pathname in question. On non-nil return value, the
+pathname is considered in the final result, otherwise it is ignored.
+Note that FULL affects whether the match is done on the filename of
+the full pathname.
Optional argument RESULT-TYPE can be one of:
- sorted-list (default) to return a list, sorted in alphabetically
maximal recursion depth, use 0 to emulate old `directory-files'.
Optional argument SYMLINK-IS-FILE specifies whether symlinks
-should be resolved \(which is the default behaviour\) or whether
+should be resolved \(which is the default behaviour\) or whether
they are treated as ordinary files \(non-nil\), in the latter
case symlinks to directories are not recurred.
*/
(directory, full, match, result_type, files_only, maxdepth,
symlink_is_file, bloom_filter))
-#if 0
- (int nargs, Lisp_Object *args))
-#endif
{
Lisp_Object handler = Qnil, result = Qnil;
#if !defined HAVE_BDWGC || !defined EF_USE_BDWGC
.maxdepth = 64,
.fullp = !NILP(full),
.symlink_file_p = !NILP(symlink_is_file),
+ .matchfullp = EQ(full, Qmatch_full),
};
struct gcpro gcpro1;
/* argument checks */
CHECK_STRING(directory);
- if (!NILP(match)) {
- CHECK_STRING(match);
- }
if (!NILP(maxdepth)) {
CHECK_NATNUM(maxdepth);
opts.maxdepth = XUINT(maxdepth);
in case it is a directory. */
value = lstat(fullname, st_addr);
if (S_ISLNK(st_addr->st_mode))
- sxemacs_stat(fullname, st_addr);
+ (void)sxemacs_stat(fullname, st_addr);
#else
value = sxemacs_stat(fullname, st_addr);
#endif
==
XSTRING_CHAR_LENGTH(bestmatch)))
/* If there is more than one exact match aside from
- case, and one of them is exact including case,
- prefer that one. */
+ case, and one of them is exact including case,
+ prefer that one. */
&& 0 > scmp_1(p2,
XSTRING_DATA(file),
file_name_length, 0)
defsymbol(&Qsorted_list, "sorted-list");
defsymbol(&Qdesc_sorted_list, "desc-sorted-list");
defsymbol(&Qunsorted_list, "unsorted-list");
+ defsymbol(&Qmatch_full, "match-full");
DEFSUBR(Fdirectory_files);
DEFSUBR(Fdirectory_files_recur);