/* 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-2012 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#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;
static Lisp_Object Qfile_attributes_lessp;
-static int scmp (const char *, const char *, int);
-static Lisp_Object Ffile_attributes (Lisp_Object, Lisp_Object);
+static ptrdiff_t scmp (const char *, const char *, ptrdiff_t);
\f
#ifdef WINDOWSNT
Lisp_Object
directory_files_internal (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort, int attrs, Lisp_Object id_format)
{
DIR *d;
- int directory_nbytes;
+ ptrdiff_t directory_nbytes;
Lisp_Object list, dirfilename, encoded_directory;
struct re_pattern_buffer *bufp = NULL;
int needsep = 0;
- int count = SPECPDL_INDEX ();
+ ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
DIRENTRY *dp;
#ifdef WINDOWSNT
if (DIRENTRY_NONEMPTY (dp))
{
- int len;
+ ptrdiff_t len;
int 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. */
if (!NILP (full))
{
Lisp_Object fullname;
- int nbytes = len + directory_nbytes + needsep;
- int nchars;
+ ptrdiff_t nbytes = len + directory_nbytes + needsep;
+ ptrdiff_t nchars;
fullname = make_uninit_multibyte_string (nbytes, nbytes);
memcpy (SDATA (fullname), SDATA (directory),
/* 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;
}
}
(Lisp_Object file, Lisp_Object directory, Lisp_Object predicate)
{
Lisp_Object handler;
+ directory = Fexpand_file_name (directory, Qnil);
/* If the directory name has special constructs in it,
call the corresponding file handler. */
(Lisp_Object file, Lisp_Object directory)
{
Lisp_Object handler;
+ directory = Fexpand_file_name (directory, Qnil);
/* If the directory name has special constructs in it,
call the corresponding file handler. */
file_name_completion (Lisp_Object file, Lisp_Object dirname, int all_flag, int ver_flag, Lisp_Object predicate)
{
DIR *d;
- int bestmatchsize = 0;
+ ptrdiff_t bestmatchsize = 0;
int matchcount = 0;
/* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded.
If ALL_FLAG is 0, BESTMATCH is either nil
well as "." and "..". Until shown otherwise, assume we can't exclude
anything. */
int includeall = 1;
- int count = SPECPDL_INDEX ();
+ ptrdiff_t count = SPECPDL_INDEX ();
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
elt = Qnil;
bestmatch = Qnil;
encoded_file = encoded_dir = Qnil;
GCPRO5 (file, dirname, bestmatch, encoded_file, encoded_dir);
- dirname = Fexpand_file_name (dirname, Qnil);
specbind (Qdefault_directory, dirname);
/* Do completion on the encoded file name
while (1)
{
DIRENTRY *dp;
- int len;
+ ptrdiff_t len;
int canexclude = 0;
errno = 0;
completions when making a list of them. */
if (!all_flag)
{
- int skip;
+ ptrdiff_t skip;
#if 0 /* FIXME: The `scmp' call compares an encoded and a decoded string. */
/* If this entry matches the current bestmatch, the only
for (tem = Vcompletion_ignored_extensions;
CONSP (tem); tem = XCDR (tem))
{
- int elt_len;
+ ptrdiff_t elt_len;
char *p1;
elt = XCAR (tem);
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;
/* Suitably record this match. */
- matchcount++;
+ matchcount += matchcount <= 1;
if (all_flag)
bestmatch = Fcons (name, bestmatch);
{
Lisp_Object zero = make_number (0);
/* FIXME: This is a copy of the code in Ftry_completion. */
- int compare = min (bestmatchsize, SCHARS (name));
+ ptrdiff_t compare = min (bestmatchsize, SCHARS (name));
Lisp_Object cmp
= Fcompare_strings (bestmatch, zero,
make_number (compare),
name, zero,
make_number (compare),
completion_ignore_case ? Qt : Qnil);
- int matchsize
+ ptrdiff_t matchsize
= (EQ (cmp, Qt) ? compare
: XINT (cmp) < 0 ? - XINT (cmp) - 1
: XINT (cmp) - 1);
Return -1 if strings match,
else number of chars that match at the beginning. */
-static int
-scmp (const char *s1, const char *s2, int len)
+static ptrdiff_t
+scmp (const char *s1, const char *s2, ptrdiff_t len)
{
- register int l = len;
+ register ptrdiff_t l = len;
if (completion_ignore_case)
{
static int
file_name_completion_stat (Lisp_Object dirname, DIRENTRY *dp, struct stat *st_addr)
{
- int len = NAMLEN (dp);
- int pos = SCHARS (dirname);
+ ptrdiff_t len = NAMLEN (dp);
+ ptrdiff_t pos = SCHARS (dirname);
int value;
- char *fullname = (char *) alloca (len + pos + 2);
+ char *fullname;
+ USE_SAFE_ALLOCA;
+ SAFE_ALLOCA (fullname, char *, len + pos + 2);
#ifdef MSDOS
/* Some fields of struct stat are *very* expensive to compute on MS-DOS,
#ifdef MSDOS
_djstat_flags = save_djstat_flags;
#endif /* MSDOS */
+ SAFE_FREE ();
return value;
}
\f
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.
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
values[10] = INTEGER_TO_CONS (s.st_ino);
values[11] = INTEGER_TO_CONS (s.st_dev);
- return Flist (sizeof(values) / sizeof(values[0]), values);
+ return Flist (sizeof (values) / sizeof (values[0]), values);
}
DEFUN ("file-attributes-lessp", Ffile_attributes_lessp, Sfile_attributes_lessp, 2, 2, 0,
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.