bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

xreadlink (was: Re: first draft of "relocatable" module)


From: Bruno Haible
Subject: xreadlink (was: Re: first draft of "relocatable" module)
Date: Sun, 25 Feb 2007 20:00:28 +0100
User-agent: KMail/1.5.4

Hi Jim,

Ben Pfaff noticed that there two versions of xreadlink in gnulib and gettext
  
http://cvs.savannah.gnu.org/viewcvs/*checkout*/gnulib/lib/xreadlink.c?content-type=text%2Fplain&rev=1.23&root=gnulib
  
http://cvs.savannah.gnu.org/viewcvs/*checkout*/gettext/gnulib-local/lib/xreadlink.c?content-type=text%2Fplain&rev=1.3&root=gettext
are not compatible.

The one in gettext is derived from your code from coreutils. The difference
is that the one in gnulib has a 'size' argument, the one in gettext
doesn't.

The one in gnulib assumes that stat() has been called before, and minimizes
the readlink() and malloc() calls accordingly: 1 readlink(), 1 malloc() in
the normal case.

The one in gettext assumes no previous operation. It minimizes operations
for this situation: 1 readlink(), 1 malloc(), 1 memcpy() in the normal case.

If the gnulib xreadlink is called when no stat has been done before, like
Ben proposes:

@@ -174,7 +172,7 @@ find_executable (const char *argv0)
   {
     char *link;
 
-    link = xreadlink ("/proc/self/exe");
+    link = xreadlink ("/proc/self/exe", 4096);
     if (link != NULL && link[0] != '[')
       return link;
     if (executable_fd < 0)

then a buffer is allocated that is way too large: 4 KB even if the link's
contents is just 10 bytes.

Or if one does

     link = xreadlink ("/proc/self/exe", 1);

then the result will be several readlink() and several malloc() calls, which
is bad also.

If, on the other hand, the gettext xreadlink is called when stat was called
before, the result (1 readlink(), 1 malloc(), 1 memcpy() in the normal case)
is not as bad, but not optimal either: the memcpy() is unnecessary.

So, in summary, both uses are real use cases, and each has its optimal
implementation.

What can we do in gnulib?

(a) Have 2 xreadlink like functions. Since the one without prior stat is more
    natural, I would propose to rename the coreutils one, with the 'size'
    argument, to 'xreadlink_after_stat'.

Or

(b) Merge the two functions into one. For example, when the function is called
    with size = (size_t)(-1), let it mean "don't know" - and in this case,
    let the function use a stack allocated buffer and memcpy().

What do you think?

Bruno





reply via email to

[Prev in Thread] Current Thread [Next in Thread]