/* Lisp functions for making directory listings.
- Copyright (C) 1985-1986, 1993-1994, 1999-2011 Free Software Foundation, Inc.
+ Copyright (C) 1985-1986, 1993-1994, 1999-2013 Free Software
+ Foundation, Inc.
This file is part of GNU Emacs.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <setjmp.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
#endif /* HAVE_DIRENT_H */
#include <filemode.h>
+#include <stat-time.h>
#ifdef MSDOS
#define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
#include "lisp.h"
#include "systime.h"
+#include "character.h"
#include "buffer.h"
#include "commands.h"
-#include "character.h"
#include "charset.h"
#include "coding.h"
#include "regex.h"
static Lisp_Object Qfile_attributes_lessp;
static ptrdiff_t scmp (const char *, const char *, ptrdiff_t);
-static Lisp_Object Ffile_attributes (Lisp_Object, Lisp_Object);
\f
#ifdef WINDOWSNT
Lisp_Object
directory_files_internal_unwind (Lisp_Object dh)
{
DIR *d = (DIR *) XSAVE_VALUE (dh)->pointer;
- BLOCK_INPUT;
+ block_input ();
closedir (d);
- UNBLOCK_INPUT;
+ unblock_input ();
return Qnil;
}
/* 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.
+ If not ATTRS, return a list of directory filenames;
+ if ATTRS, return a list of directory filenames and their attributes.
In the latter case, ID_FORMAT is passed to Ffile_attributes. */
Lisp_Object
-directory_files_internal (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort, int attrs, Lisp_Object id_format)
+directory_files_internal (Lisp_Object directory, Lisp_Object full,
+ Lisp_Object match, Lisp_Object nosort, bool attrs,
+ Lisp_Object id_format)
{
DIR *d;
ptrdiff_t directory_nbytes;
Lisp_Object list, dirfilename, encoded_directory;
struct re_pattern_buffer *bufp = NULL;
- int needsep = 0;
+ bool needsep = 0;
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
DIRENTRY *dp;
/* Now *bufp is the compiled form of MATCH; don't call anything
which might compile a new regexp until we're done with the loop! */
- BLOCK_INPUT;
+ block_input ();
d = opendir (SSDATA (dirfilename));
- UNBLOCK_INPUT;
+ unblock_input ();
if (d == NULL)
report_file_error ("Opening directory", Fcons (directory, Qnil));
if (DIRENTRY_NONEMPTY (dp))
{
ptrdiff_t len;
- int wanted = 0;
+ bool wanted = 0;
Lisp_Object name, finalname;
- struct gcpro inner_gcpro1, inner_gcpro2;
+ struct gcpro gcpro1, gcpro2;
len = NAMLEN (dp);
name = finalname = make_unibyte_string (dp->d_name, len);
- GCPRO2_VAR (finalname, name, inner_gcpro);
+ GCPRO2 (finalname, name);
/* Note: DECODE_FILE can GC; it should protect its argument,
though. */
/* Some bug somewhere. */
if (nchars > nbytes)
- abort ();
+ emacs_abort ();
STRING_SET_CHARS (fullname, nchars);
if (nchars == nbytes)
/* Construct an expanded filename for the directory entry.
Use the decoded names for input to Ffile_attributes. */
Lisp_Object decoded_fullname, fileattrs;
- struct gcpro innermost_gcpro1, innermost_gcpro2;
+ struct gcpro gcpro1, gcpro2;
decoded_fullname = fileattrs = Qnil;
- GCPRO2_VAR (decoded_fullname, fileattrs, innermost_gcpro);
+ GCPRO2 (decoded_fullname, fileattrs);
/* Both Fexpand_file_name and Ffile_attributes can GC. */
decoded_fullname = Fexpand_file_name (name, directory);
fileattrs = Ffile_attributes (decoded_fullname, id_format);
list = Fcons (Fcons (finalname, fileattrs), list);
- UNGCPRO_VAR (innermost_gcpro);
+ UNGCPRO;
}
else
list = Fcons (finalname, list);
}
- UNGCPRO_VAR (inner_gcpro);
+ UNGCPRO;
}
}
- BLOCK_INPUT;
+ block_input ();
closedir (d);
- UNBLOCK_INPUT;
+ unblock_input ();
#ifdef WINDOWSNT
if (attrs)
Vw32_get_true_file_attributes = w32_save;
}
\f
-static Lisp_Object file_name_completion
- (Lisp_Object file, Lisp_Object dirname, int all_flag, int ver_flag,
- Lisp_Object predicate);
+static Lisp_Object file_name_completion (Lisp_Object, Lisp_Object, bool,
+ Lisp_Object);
DEFUN ("file-name-completion", Ffile_name_completion, Sfile_name_completion,
2, 3, 0,
if (!NILP (handler))
return call4 (handler, Qfile_name_completion, file, directory, predicate);
- return file_name_completion (file, directory, 0, 0, predicate);
+ return file_name_completion (file, directory, 0, predicate);
}
DEFUN ("file-name-all-completions", Ffile_name_all_completions,
if (!NILP (handler))
return call3 (handler, Qfile_name_all_completions, file, directory);
- return file_name_completion (file, directory, 1, 0, Qnil);
+ return file_name_completion (file, directory, 1, Qnil);
}
static int file_name_completion_stat (Lisp_Object dirname, DIRENTRY *dp, struct stat *st_addr);
static Lisp_Object Qdefault_directory;
static Lisp_Object
-file_name_completion (Lisp_Object file, Lisp_Object dirname, int all_flag, int ver_flag, Lisp_Object predicate)
+file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag,
+ Lisp_Object predicate)
{
DIR *d;
ptrdiff_t bestmatchsize = 0;
Lisp_Object encoded_file;
Lisp_Object encoded_dir;
struct stat st;
- int directoryp;
- /* If includeall is zero, exclude files in completion-ignored-extensions as
+ bool directoryp;
+ /* If not INCLUDEALL, exclude files in completion-ignored-extensions as
well as "." and "..". Until shown otherwise, assume we can't exclude
anything. */
- int includeall = 1;
+ bool includeall = 1;
ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
CHECK_STRING (file);
-#ifdef FILE_SYSTEM_CASE
- file = FILE_SYSTEM_CASE (file);
-#endif
bestmatch = Qnil;
encoded_file = encoded_dir = Qnil;
GCPRO5 (file, dirname, bestmatch, encoded_file, encoded_dir);
encoded_dir = ENCODE_FILE (dirname);
- BLOCK_INPUT;
+ block_input ();
d = opendir (SSDATA (Fdirectory_file_name (encoded_dir)));
- UNBLOCK_INPUT;
+ unblock_input ();
if (!d)
report_file_error ("Opening directory", Fcons (dirname, Qnil));
{
DIRENTRY *dp;
ptrdiff_t len;
- int canexclude = 0;
+ bool canexclude = 0;
errno = 0;
dp = readdir (d);
if (file_name_completion_stat (encoded_dir, dp, &st) < 0)
continue;
- directoryp = S_ISDIR (st.st_mode);
+ directoryp = S_ISDIR (st.st_mode) != 0;
tem = Qnil;
/* If all_flag is set, always include all.
It would not actually be helpful to the user to ignore any possible
if (includeall && !canexclude)
{ /* If we have one non-excludable file, we want to exclude the
- excudable files. */
+ excludable files. */
includeall = 0;
/* Throw away any previous excludable match found. */
bestmatch = Qnil;
if (!NILP (predicate))
{
Lisp_Object val;
- struct gcpro inner_gcpro1;
+ struct gcpro gcpro1;
- GCPRO1_VAR (name, inner_gcpro);
+ GCPRO1 (name);
val = call1 (predicate, name);
- UNGCPRO_VAR (inner_gcpro);
+ UNGCPRO;
if (NILP (val))
continue;
/* This tests that the current file is an exact match
but BESTMATCH is not (it is too long). */
if ((matchsize == SCHARS (name)
- && matchsize + !!directoryp < SCHARS (bestmatch))
+ && matchsize + directoryp < SCHARS (bestmatch))
||
/* If there is no exact match ignoring case,
prefer a match that does not change the case
either both or neither are exact. */
(((matchsize == SCHARS (name))
==
- (matchsize + !!directoryp == SCHARS (bestmatch)))
+ (matchsize + directoryp == SCHARS (bestmatch)))
&& (cmp = Fcompare_strings (name, zero,
make_number (SCHARS (file)),
file, zero,
ptrdiff_t len = NAMLEN (dp);
ptrdiff_t pos = SCHARS (dirname);
int value;
- char *fullname;
USE_SAFE_ALLOCA;
- SAFE_ALLOCA (fullname, char *, len + pos + 2);
+ char *fullname = SAFE_ALLOCA (len + pos + 2);
#ifdef MSDOS
/* Some fields of struct stat are *very* expensive to compute on MS-DOS,
2. File uid as a string or a number. If a string value cannot be
looked up, a numeric value, either an integer or a float, is returned.
3. File gid, likewise.
- 4. Last access time, as a list of two integers.
- First integer has high-order 16 bits of time, second has low 16 bits.
+ 4. Last access time, as a list of integers (HIGH LOW USEC PSEC) in the
+ same style as (current-time).
(See a note below about access time on FAT-based filesystems.)
5. Last modification time, likewise. This is the time of the last
change to the file's contents.
if (!(NILP (id_format) || EQ (id_format, Qinteger)))
{
- BLOCK_INPUT;
+ block_input ();
uname = stat_uname (&s);
gname = stat_gname (&s);
- UNBLOCK_INPUT;
+ unblock_input ();
}
if (uname)
values[2] = DECODE_SYSTEM (build_string (uname));
else
values[3] = make_fixnum_or_float (s.st_gid);
- values[4] = make_time (s.st_atime);
- values[5] = make_time (s.st_mtime);
- values[6] = make_time (s.st_ctime);
+ values[4] = make_lisp_time (get_stat_atime (&s));
+ values[5] = make_lisp_time (get_stat_mtime (&s));
+ values[6] = make_lisp_time (get_stat_ctime (&s));
/* If the file size is a 4-byte type, assume that files of sizes in
the 2-4 GiB range wrap around to negative values, as this is a
return Fstring_lessp (Fcar (f1), Fcar (f2));
}
\f
+
+DEFUN ("system-users", Fsystem_users, Ssystem_users, 0, 0, 0,
+ doc: /* Return a list of user names currently registered in the system.
+If we don't know how to determine that on this platform, just
+return a list with one element, taken from `user-real-login-name'. */)
+ (void)
+{
+ Lisp_Object users = Qnil;
+#if defined HAVE_GETPWENT && defined HAVE_ENDPWENT
+ struct passwd *pw;
+
+ while ((pw = getpwent ()))
+ users = Fcons (DECODE_SYSTEM (build_string (pw->pw_name)), users);
+
+ endpwent ();
+#endif
+ if (EQ (users, Qnil))
+ /* At least current user is always known. */
+ users = Fcons (Vuser_real_login_name, Qnil);
+ return users;
+}
+
+DEFUN ("system-groups", Fsystem_groups, Ssystem_groups, 0, 0, 0,
+ doc: /* Return a list of user group names currently registered in the system.
+The value may be nil if not supported on this platform. */)
+ (void)
+{
+ Lisp_Object groups = Qnil;
+#if defined HAVE_GETGRENT && defined HAVE_ENDGRENT
+ struct group *gr;
+
+ while ((gr = getgrent ()))
+ groups = Fcons (DECODE_SYSTEM (build_string (gr->gr_name)), groups);
+
+ endgrent ();
+#endif
+ return groups;
+}
+
void
syms_of_dired (void)
{
defsubr (&Sfile_name_all_completions);
defsubr (&Sfile_attributes);
defsubr (&Sfile_attributes_lessp);
+ defsubr (&Ssystem_users);
+ defsubr (&Ssystem_groups);
DEFVAR_LISP ("completion-ignored-extensions", Vcompletion_ignored_extensions,
doc: /* Completion ignores file names ending in any string in this list.