/* Lisp functions for making directory listings.
- Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1993, 1994, 1999 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <sys/types.h>
#include <sys/stat.h>
+#include "systime.h"
+
#ifdef VMS
#include <string.h>
#include <rms.h>
#endif
#endif /* not NONSYSTEM_DIR_LIBRARY */
+#include <sys/stat.h>
+
#ifndef MSDOS
#define DIRENTRY struct direct
/* Returns a search buffer, with a fastmap allocated and ready to go. */
extern struct re_pattern_buffer *compile_pattern ();
+/* From filemode.c. Can't go in Lisp.h because of `stat'. */
+extern void filemodestring P_ ((struct stat *, char *));
+
#define min(a, b) ((a) < (b) ? (a) : (b))
/* if system does not have symbolic links, it does not have lstat.
Lisp_Object Vcompletion_ignored_extensions;
Lisp_Object Qcompletion_ignore_case;
Lisp_Object Qdirectory_files;
+Lisp_Object Qdirectory_files_and_attributes;
Lisp_Object Qfile_name_completion;
Lisp_Object Qfile_name_all_completions;
Lisp_Object Qfile_attributes;
+Lisp_Object Qfile_attributes_lessp;
\f
-DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
- "Return a list of names of files in DIRECTORY.\n\
-There are three optional arguments:\n\
-If FULL is non-nil, return absolute file names. Otherwise return names\n\
- that are relative to the specified directory.\n\
-If MATCH is non-nil, mention only file names that match the regexp MATCH.\n\
-If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
- NOSORT is useful if you plan to sort the result yourself.")
- (directory, full, match, nosort)
+/* Function shared by Fdirectory_files and Fdirectory_files_and_attributes.
+ When ATTRS is zero, return a list of directory filenames; when
+ non-zero, return a list of directory filenames and their attributes. */
+Lisp_Object
+directory_files_internal (directory, full, match, nosort, attrs)
Lisp_Object directory, full, match, nosort;
+ int attrs;
{
DIR *d;
int dirnamelen;
int needsep = 0;
struct gcpro gcpro1, gcpro2;
- /* If the file name has special constructs in it,
- call the corresponding file handler. */
- handler = Ffind_file_name_handler (directory, Qdirectory_files);
- if (!NILP (handler))
- {
- Lisp_Object args[6];
-
- args[0] = handler;
- args[1] = Qdirectory_files;
- args[2] = directory;
- args[3] = full;
- args[4] = match;
- args[5] = nosort;
- return Ffuncall (6, args);
- }
-
/* Because of file name handlers, these functions might call
Ffuncall, and cause a GC. */
GCPRO1 (match);
report_file_error ("Opening directory", Fcons (directory, Qnil));
list = Qnil;
- dirnamelen = STRING_BYTES (XSTRING (encoded_directory));
+ dirnamelen = STRING_BYTES (XSTRING (directory));
re_match_object = Qt;
/* Decide whether we need to add a directory separator. */
#ifndef VMS
if (dirnamelen == 0
- || !IS_ANY_SEP (XSTRING (encoded_directory)->data[dirnamelen - 1]))
+ || !IS_ANY_SEP (XSTRING (directory)->data[dirnamelen - 1]))
needsep = 1;
#endif /* not VMS */
while (1)
{
DIRENTRY *dp = readdir (d);
- int len;
if (!dp) break;
- len = NAMLEN (dp);
if (DIRENTRY_NONEMPTY (dp))
{
+ int len;
+
+ len = NAMLEN (dp);
+ name = DECODE_FILE (make_string (dp->d_name, len));
+ len = STRING_BYTES (XSTRING (name));
+
if (NILP (match)
- || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0)))
+ || (0 <= re_search (bufp, XSTRING (name)->data, len, 0, len, 0)))
{
+ Lisp_Object finalname;
+
+ finalname = name;
if (!NILP (full))
{
int afterdirindex = dirnamelen;
int total = len + dirnamelen;
int nchars;
+ Lisp_Object fullname;
- name = make_uninit_multibyte_string (total + needsep,
- total + needsep);
- bcopy (XSTRING (encoded_directory)->data, XSTRING (name)->data,
+ fullname = make_uninit_multibyte_string (total + needsep,
+ total + needsep);
+ bcopy (XSTRING (directory)->data, XSTRING (fullname)->data,
dirnamelen);
if (needsep)
- XSTRING (name)->data[afterdirindex++] = DIRECTORY_SEP;
- bcopy (dp->d_name,
- XSTRING (name)->data + afterdirindex, len);
- nchars = chars_in_text (XSTRING (name)->data,
+ XSTRING (fullname)->data[afterdirindex++] = DIRECTORY_SEP;
+ bcopy (XSTRING (name)->data,
+ XSTRING (fullname)->data + afterdirindex, len);
+ nchars = chars_in_text (XSTRING (fullname)->data,
afterdirindex + len);
- XSTRING (name)->size = nchars;
- if (nchars == STRING_BYTES (XSTRING (name)))
- SET_STRING_BYTES (XSTRING (name), -1);
+ XSTRING (fullname)->size = nchars;
+ if (nchars == STRING_BYTES (XSTRING (fullname)))
+ SET_STRING_BYTES (XSTRING (fullname), -1);
+ finalname = fullname;
+ }
+
+ if (attrs)
+ {
+ /* Construct an expanded filename for the directory entry.
+ Use the decoded names for input to Ffile_attributes. */
+ Lisp_Object decoded_fullname;
+ Lisp_Object fileattrs;
+
+ decoded_fullname = Fexpand_file_name (name, directory);
+ fileattrs = Ffile_attributes (decoded_fullname);
+
+ list = Fcons (Fcons (finalname, fileattrs), list);
}
else
- name = make_string (dp->d_name, len);
- name = DECODE_FILE (name);
- list = Fcons (name, list);
+ {
+ list = Fcons (finalname, list);
+ }
}
}
}
UNGCPRO;
if (!NILP (nosort))
return list;
- return Fsort (Fnreverse (list), Qstring_lessp);
+ if (attrs)
+ return Fsort (Fnreverse (list), Qfile_attributes_lessp);
+ else
+ return Fsort (Fnreverse (list), Qstring_lessp);
+}
+
+
+DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
+ "Return a list of names of files in DIRECTORY.\n\
+There are three optional arguments:\n\
+If FULL is non-nil, return absolute file names. Otherwise return names\n\
+ that are relative to the specified directory.\n\
+If MATCH is non-nil, mention only file names that match the regexp MATCH.\n\
+If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
+ NOSORT is useful if you plan to sort the result yourself.")
+ (directory, full, match, nosort)
+ Lisp_Object directory, full, match, nosort;
+{
+ Lisp_Object handler;
+
+ /* If the file name has special constructs in it,
+ call the corresponding file handler. */
+ handler = Ffind_file_name_handler (directory, Qdirectory_files);
+ if (!NILP (handler))
+ {
+ Lisp_Object args[6];
+
+ args[0] = handler;
+ args[1] = Qdirectory_files;
+ args[2] = directory;
+ args[3] = full;
+ args[4] = match;
+ args[5] = nosort;
+ return Ffuncall (6, args);
+ }
+
+ return directory_files_internal (directory, full, match, nosort, 0);
}
+
+DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes, Sdirectory_files_and_attributes, 1, 4, 0,
+ "Return a list of names of files and their attributes in DIRECTORY.\n\
+There are three optional arguments:\n\
+If FULL is non-nil, return absolute file names. Otherwise return names\n\
+ that are relative to the specified directory.\n\
+If MATCH is non-nil, mention only file names that match the regexp MATCH.\n\
+If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
+ NOSORT is useful if you plan to sort the result yourself.")
+ (directory, full, match, nosort)
+ Lisp_Object directory, full, match, nosort;
+{
+ Lisp_Object handler;
+
+ /* If the file name has special constructs in it,
+ call the corresponding file handler. */
+ handler = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes);
+ if (!NILP (handler))
+ {
+ Lisp_Object args[6];
+
+ args[0] = handler;
+ args[1] = Qdirectory_files_and_attributes;
+ args[2] = directory;
+ args[3] = full;
+ args[4] = match;
+ args[5] = nosort;
+ return Ffuncall (6, args);
+ }
+
+ return directory_files_internal (directory, full, match, nosort, 1);
+}
+
\f
Lisp_Object file_name_completion ();
if (!passcount && len > XSTRING (encoded_file)->size)
/* and exit this for loop if a match is found */
for (tem = Vcompletion_ignored_extensions;
- CONSP (tem); tem = XCONS (tem)->cdr)
+ CONSP (tem); tem = XCDR (tem))
{
- elt = XCONS (tem)->car;
+ elt = XCAR (tem);
if (!STRINGP (elt)) continue;
skip = len - XSTRING (elt)->size;
if (skip < 0) continue;
/* Ignore this element if it fails to match all the regexps. */
for (regexps = Vcompletion_regexp_list; CONSP (regexps);
- regexps = XCONS (regexps)->cdr)
+ regexps = XCDR (regexps))
{
- tem = Fstring_match (XCONS (regexps)->car, elt, zero);
+ tem = Fstring_match (XCAR (regexps), elt, zero);
if (NILP (tem))
break;
}
\f
Lisp_Object
make_time (time)
- int time;
+ time_t time;
{
return Fcons (make_number (time >> 16),
Fcons (make_number (time & 0177777), Qnil));
First integer has high-order 16 bits of time, second has low 16 bits.\n\
5. Last modification time, likewise.\n\
6. Last status change time, likewise.\n\
- 7. Size in bytes (-1, if number is out of range).\n\
+ 7. Size in bytes.\n\
+ This is a floating point number if the size is too large for an integer.\n\
8. File modes, as a string of ten letters or dashes as in ls -l.\n\
9. t iff file's gid would change if file were deleted and recreated.\n\
-10. inode number.\n\
+10. inode number. If inode number is larger than the Emacs integer,\n\
+ this is a cons cell containing two integers: first the high part,\n\
+ then the low 16 bits.\n\
11. Device number.\n\
\n\
If file does not exist, returns nil.")
values[4] = make_time (s.st_atime);
values[5] = make_time (s.st_mtime);
values[6] = make_time (s.st_ctime);
- values[7] = make_number ((int) s.st_size);
- /* If the size is out of range, give back -1. */
+ values[7] = make_number (s.st_size);
+ /* If the size is out of range for an integer, return a float. */
if (XINT (values[7]) != s.st_size)
- XSETINT (values[7], -1);
+ values[7] = make_float ((double)s.st_size);
filemodestring (&s, modes);
values[8] = make_string (modes, 10);
#ifdef BSD4_3 /* Gross kludge to avoid lack of "#if defined(...)" in VMS */
else
/* But keep the most common cases as integers. */
values[10] = make_number (s.st_ino);
- values[11] = make_number (s.st_dev);
+
+ /* Likewise for device. */
+ if (s.st_dev & (((EMACS_INT) (-1)) << VALBITS))
+ values[11] = Fcons (make_number (s.st_dev >> 16),
+ make_number (s.st_dev & 0xffff));
+ else
+ values[11] = make_number (s.st_dev);
+
return Flist (sizeof(values) / sizeof(values[0]), values);
}
+
+DEFUN ("file-attributes-lessp", Ffile_attributes_lessp, Sfile_attributes_lessp, 2, 2, 0,
+ "Return t if first arg file attributes list is less than second.\n\
+Comparison is in lexicographic order and case is significant.")
+ (f1, f2)
+ Lisp_Object f1, f2;
+{
+ return Fstring_lessp (Fcar (f1), Fcar (f2));
+}
\f
void
syms_of_dired ()
{
Qdirectory_files = intern ("directory-files");
+ Qdirectory_files_and_attributes = intern ("directory-files-and-attributes");
Qfile_name_completion = intern ("file-name-completion");
Qfile_name_all_completions = intern ("file-name-all-completions");
Qfile_attributes = intern ("file-attributes");
+ Qfile_attributes_lessp = intern ("file-attributes-lessp");
staticpro (&Qdirectory_files);
+ staticpro (&Qdirectory_files_and_attributes);
staticpro (&Qfile_name_completion);
staticpro (&Qfile_name_all_completions);
staticpro (&Qfile_attributes);
+ staticpro (&Qfile_attributes_lessp);
defsubr (&Sdirectory_files);
+ defsubr (&Sdirectory_files_and_attributes);
defsubr (&Sfile_name_completion);
#ifdef VMS
defsubr (&Sfile_name_all_versions);
#endif /* VMS */
defsubr (&Sfile_name_all_completions);
defsubr (&Sfile_attributes);
+ defsubr (&Sfile_attributes_lessp);
#ifdef VMS
Qcompletion_ignore_case = intern ("completion-ignore-case");