From: "Michael Kerrisk (man-pages)" <mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: Ursache Vladimir <f35f22fan-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
linux-man-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: readlink() example sometimes fails
Date: Sat, 20 Aug 2016 15:32:41 +1200 [thread overview]
Message-ID: <28d2728c-e43c-dd90-3beb-fac899646ded@gmail.com> (raw)
In-Reply-To: <CAJbVpmwRAi1dEJw=zUtsJLE2RRMGtsjqBJk4x+_KsJGWnoRsMA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hello Vladimir,
On 08/18/2016 05:30 PM, Ursache Vladimir wrote:
> Hi,
> the readlink() example from:
>
> http://man7.org/linux/man-pages/man2/readlink.2.html
>
> relies on lstat()'s st_size, but that doesn't work for files contents
> created dynamically by the Linux kernel which often report a zero
> size, for example the link at:
> /sys/block/sda
>
> the example code will fail because stat.st_size reports zero and you
> try to read (stat.st_size + 1) which will succeed, which will generate
> the error : "symlink increased in size between lstat() and
> readlink()".
>
> Somewhat related, the same issue is true for reading regular text
> files, e.g: "/proc/filesystems" which will report stat.st_size = 0.
>
> My quick workaround:
>
> if (stat.st_size != 0)
> // work as usual
> else if (file_is_a_link)
> // malloc 4K of ram and try to readlink() into it
> else if (is_regular_file)
> // read() into a byte array that grows accordingly
>
> In case it matters, I'm using Ubuntu 16.04 amd64.
Thanks for this report. I agree that the page needs to be fixed.
I modified the example program to be as follows:
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
struct stat sb;
char *linkname;
ssize_t r, bufsiz;
if (argc != 2) {
fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (lstat(argv[1], &sb) == -1) {
perror("lstat");
exit(EXIT_FAILURE);
}
bufsiz = sb.st_size + 1;
/* Some magic symlinks under (for example) /proc and /sys
report 'st_size' as zero. In that case, take PATH_MAX as
a "good enough" estimate */
if (sb.st_size == 0)
bufsiz = PATH_MAX;
printf("%zd\n", bufsiz);
linkname = malloc(bufsiz);
if (linkname == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
r = readlink(argv[1], linkname, bufsiz);
if (r == -1) {
perror("readlink");
exit(EXIT_FAILURE);
}
linkname[r] = '\0';
printf("'%s' points to '%s'\n", argv[1], linkname);
if (r == bufsiz)
printf("(Returned buffer may have been truncated)\n");
free(linkname);
exit(EXIT_SUCCESS);
}
Seem okay?
Cheers,
Michael
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2016-08-20 3:32 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-18 5:30 readlink() example sometimes fails Ursache Vladimir
[not found] ` <CAJbVpmwRAi1dEJw=zUtsJLE2RRMGtsjqBJk4x+_KsJGWnoRsMA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-08-20 3:32 ` Michael Kerrisk (man-pages) [this message]
[not found] ` <28d2728c-e43c-dd90-3beb-fac899646ded-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-08-20 7:57 ` Ursache Vladimir
[not found] ` <CAJbVpmxJWuuO9-z=pavdnQh4ou0piJ72LK-T5fzt2QkJ+WZaAg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-08-26 17:47 ` Ursache Vladimir
[not found] ` <CAJbVpmwb1EU5J3jh0wKosQF9pxsS3dhwTaR5g=bzf9OL-Dr=SQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-08-28 20:48 ` Michael Kerrisk (man-pages)
[not found] ` <57aec2e3-be44-2389-46c8-dc62f7d2eefe-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-08-29 8:00 ` Ursache Vladimir
2016-08-29 15:17 ` Mats Wichmann
[not found] ` <daf306a0-3e0c-8edb-016d-8e68bac02c79-mBRmNHn34rVzbRFIqnYvSA@public.gmane.org>
2016-08-29 19:04 ` Michael Kerrisk (man-pages)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=28d2728c-e43c-dd90-3beb-fac899646ded@gmail.com \
--to=mtk.manpages-re5jqeeqqe8avxtiumwx3w@public.gmane.org \
--cc=f35f22fan-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=linux-man-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox