summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2011-03-31 23:28:48 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2011-03-31 23:28:48 -0700
commitd1fdcab7425f36a34ddeaf304e2c6e3c471ba8db (patch)
treef59643a560ce58433a9a92dfe615dd18aecc0457 /src
parent63139bfa89692ec666815f57d0658996577a80d3 (diff)
downloademacs-d1fdcab7425f36a34ddeaf304e2c6e3c471ba8db.tar.gz
Replace two copies of readlink code with single gnulib version.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog12
-rw-r--r--src/fileio.c36
-rw-r--r--src/filelock.c38
-rw-r--r--src/lisp.h2
-rw-r--r--src/sysdep.c18
5 files changed, 49 insertions, 57 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index c2e28251cb0..5649c8819d3 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,15 @@
+2011-04-01 Paul Eggert <eggert@cs.ucla.edu>
+
+ Replace two copies of readlink code with single gnulib version.
+ The gnulib version avoids calling malloc in the usual case,
+ and on 64-bit hosts doesn't have some arbitrary 32-bit limits.
+ * fileio.c (Ffile_symlink_p): Use emacs_readlink.
+ * filelock.c (current_lock_owner): Likewise.
+ * lisp.h (READLINK_BUFSIZE, emacs_readlink): New function.
+ * sysdep.c: Include allocator.h, careadlinkat.h.
+ (emacs_no_realloc_allocator): New static constant.
+ (emacs_readlink): New function.
+
2011-03-31 Juanma Barranquero <lekktu@gmail.com>
* xdisp.c (redisplay_internal): Fix prototype.
diff --git a/src/fileio.c b/src/fileio.c
index 85431dfd5b1..552044f7272 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2579,9 +2579,8 @@ points to a nonexistent file. */)
{
Lisp_Object handler;
char *buf;
- int bufsize;
- int valsize;
Lisp_Object val;
+ char readlink_buf[READLINK_BUFSIZE];
CHECK_STRING (filename);
filename = Fexpand_file_name (filename, Qnil);
@@ -2594,36 +2593,15 @@ points to a nonexistent file. */)
filename = ENCODE_FILE (filename);
- bufsize = 50;
- buf = NULL;
- do
- {
- bufsize *= 2;
- buf = (char *) xrealloc (buf, bufsize);
- memset (buf, 0, bufsize);
-
- errno = 0;
- valsize = readlink (SSDATA (filename), buf, bufsize);
- if (valsize == -1)
- {
-#ifdef ERANGE
- /* HP-UX reports ERANGE if buffer is too small. */
- if (errno == ERANGE)
- valsize = bufsize;
- else
-#endif
- {
- xfree (buf);
- return Qnil;
- }
- }
- }
- while (valsize >= bufsize);
+ buf = emacs_readlink (SSDATA (filename), readlink_buf);
+ if (! buf)
+ return Qnil;
- val = make_string (buf, valsize);
+ val = build_string (buf);
if (buf[0] == '/' && strchr (buf, ':'))
val = concat2 (build_string ("/:"), val);
- xfree (buf);
+ if (buf != readlink_buf)
+ xfree (buf);
val = DECODE_FILE (val);
return val;
}
diff --git a/src/filelock.c b/src/filelock.c
index 2138eaa502b..13b27c72f19 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -396,36 +396,16 @@ within_one_second (time_t a, time_t b)
static int
current_lock_owner (lock_info_type *owner, char *lfname)
{
- int len, ret;
+ int ret;
+ size_t len;
int local_owner = 0;
char *at, *dot, *colon;
- char *lfinfo = 0;
- int bufsize = 50;
- /* Read arbitrarily-long contents of symlink. Similar code in
- file-symlink-p in fileio.c. */
- do
- {
- bufsize *= 2;
- lfinfo = (char *) xrealloc (lfinfo, bufsize);
- errno = 0;
- len = readlink (lfname, lfinfo, bufsize);
-#ifdef ERANGE
- /* HP-UX reports ERANGE if the buffer is too small. */
- if (len == -1 && errno == ERANGE)
- len = bufsize;
-#endif
- }
- while (len >= bufsize);
+ char readlink_buf[READLINK_BUFSIZE];
+ char *lfinfo = emacs_readlink (lfname, readlink_buf);
/* If nonexistent lock file, all is well; otherwise, got strange error. */
- if (len == -1)
- {
- xfree (lfinfo);
- return errno == ENOENT ? 0 : -1;
- }
-
- /* Link info exists, so `len' is its length. Null terminate. */
- lfinfo[len] = 0;
+ if (!lfinfo)
+ return errno == ENOENT ? 0 : -1;
/* Even if the caller doesn't want the owner info, we still have to
read it to determine return value, so allocate it. */
@@ -441,7 +421,8 @@ current_lock_owner (lock_info_type *owner, char *lfname)
dot = strrchr (lfinfo, '.');
if (!at || !dot)
{
- xfree (lfinfo);
+ if (lfinfo != readlink_buf)
+ xfree (lfinfo);
return -1;
}
len = at - lfinfo;
@@ -467,7 +448,8 @@ current_lock_owner (lock_info_type *owner, char *lfname)
owner->host[len] = 0;
/* We're done looking at the link info. */
- xfree (lfinfo);
+ if (lfinfo != readlink_buf)
+ xfree (lfinfo);
/* On current host? */
if (STRINGP (Fsystem_name ())
diff --git a/src/lisp.h b/src/lisp.h
index 85838d111db..63f346f6a25 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3340,6 +3340,8 @@ extern int emacs_open (const char *, int, int);
extern int emacs_close (int);
extern int emacs_read (int, char *, unsigned int);
extern int emacs_write (int, const char *, unsigned int);
+enum { READLINK_BUFSIZE = 1024 };
+extern char *emacs_readlink (const char *, char [READLINK_BUFSIZE]);
#ifndef HAVE_MEMSET
extern void *memset (void *, int, size_t);
#endif
diff --git a/src/sysdep.c b/src/sysdep.c
index 1bb400421f0..a165a9ca52f 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -31,6 +31,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#endif /* HAVE_LIMITS_H */
#include <unistd.h>
+#include <allocator.h>
+#include <careadlinkat.h>
#include <ignore-value.h>
#include "lisp.h"
@@ -1866,6 +1868,22 @@ emacs_write (int fildes, const char *buf, unsigned int nbyte)
}
return (bytes_written);
}
+
+static struct allocator const emacs_norealloc_allocator =
+ { xmalloc, NULL, xfree, memory_full };
+
+/* Get the symbolic link value of FILENAME. Return a pointer to a
+ NUL-terminated string. If readlink fails, return NULL and set
+ errno. If the value fits in INITIAL_BUF, return INITIAL_BUF.
+ Otherwise, allocate memory and return a pointer to that memory. If
+ memory allocation fails, diagnose and fail without returning. If
+ successful, store the length of the symbolic link into *LINKLEN. */
+char *
+emacs_readlink (char const *filename, char initial_buf[READLINK_BUFSIZE])
+{
+ return careadlinkat (AT_FDCWD, filename, initial_buf, READLINK_BUFSIZE,
+ &emacs_norealloc_allocator, careadlinkatcwd);
+}
#ifdef USG
/*