This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: short fread(), but no ferror/feof


>> I've discovered that fread(ptr, size, nitems, stream) sometimes returns a
>> value less than "nitems", but does not set feof() nor ferror(). As I

>A simple, compilable test case with results shown on both linux and
>cygwin would prove your theory.

Here you go; example follows. Test run on Linux:

---
Got 66 bytes:
/bin/ls: /somebogus: Filen eller katalogen finns inte
/etc/passwd
|EOF has been reached.
---

Test run on Cygwin:

---
$ ./a.exe
Got 9 bytes:
/bin/ls: |
---

As you can see, the result is partial, and there is no EOF nor error.

I guess this is the problem described at
http://sources.redhat.com/ml/newlib/2004/msg00477.html. Perhaps you can
apply the suggested patch?

Example code follows.


#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>


void checked_close(int fd)
{
    if (close(fd) == -1) {
	perror("close");
	exit(1);
    }
}


void checked_pipe(int filedes[2])
{
    if (pipe(filedes) == -1) {
	perror("filedes");
	exit(1);
    }
}


int checked_dup2(int oldfd, int newfd)
{
    int ret;
    if ((ret = dup2(oldfd, newfd)) == -1) {
	perror("dup2");
	exit(1);
    }
    return ret;
}


int main()
{
    int c2p[2];
    int errpipe[2];
    pid_t pid;
    char errpipe_buf[16];
    char buf[16394];
    ssize_t errpipe_count;
    size_t count;
    FILE *output;

    checked_pipe(c2p);
    checked_pipe(errpipe);
    fcntl(errpipe[1], F_SETFD, FD_CLOEXEC);

    pid = fork();
    switch (pid) {
    case -1:
	perror("fork");
	exit(1);
	break;

    case 0:
	/* child */
	checked_close(c2p[0]);
	checked_close(errpipe[0]);
	dup2(c2p[1], 1);
	dup2(c2p[1], 2);
	checked_close(c2p[1]);
	execlp("/bin/ls", "/bin/ls", "/etc/passwd", "/somebogus");
	/* If we are still around, exec failed */
	write(errpipe[1], "1", 1);
	_exit(255);
	break;

    default:
	/* parent */
	break;
    }

    checked_close(errpipe[1]);
    checked_close(c2p[1]);

    errpipe_count = read(errpipe[0], errpipe_buf, 1);
    switch (errpipe_count) {
    case -1:
	perror("read");
	exit(1);
	break;
    case 0:
	/* EOF, good */
	break;
    default:
	/* Our "1", exec failed */
	fprintf(stderr, "exec in child failed\n");
	exit(1);
	break;
    }

    /* now read output from child, via a FILE stream */
    if ((output = fdopen(c2p[0], "rb")) == NULL) {
	perror("fdopen");
	exit(1);
    }

    setvbuf(output, 0, _IONBF, 0);
    clearerr(output);
    count = fread(buf, 1, sizeof(buf), output);
    if (count >= 0) {
	fprintf(stderr, "Got %d bytes:\n", count);
	fprintf(stderr, "%s|", buf);
    }
    if (feof(output)) {
	fprintf(stderr, "EOF has been reached.\n");
    }
    if (ferror(output)) {
	fprintf(stderr, "An error occured.\n");
    }

    return 0;
}

/Peter Åstrand <astrand@lysator.liu.se>


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]