diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2011-03-31 23:28:48 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2011-03-31 23:28:48 -0700 |
commit | d1fdcab7425f36a34ddeaf304e2c6e3c471ba8db (patch) | |
tree | f59643a560ce58433a9a92dfe615dd18aecc0457 /src | |
parent | 63139bfa89692ec666815f57d0658996577a80d3 (diff) | |
download | emacs-d1fdcab7425f36a34ddeaf304e2c6e3c471ba8db.tar.gz |
Replace two copies of readlink code with single gnulib version.
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 12 | ||||
-rw-r--r-- | src/fileio.c | 36 | ||||
-rw-r--r-- | src/filelock.c | 38 | ||||
-rw-r--r-- | src/lisp.h | 2 | ||||
-rw-r--r-- | src/sysdep.c | 18 |
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 /* |