OSDN Git Service

Fix a couple of bugs in _fopen and fclose, plus change a few internals.
authorManuel Novoa III <mjn3@codepoet.org>
Mon, 19 Feb 2001 20:33:38 +0000 (20:33 -0000)
committerManuel Novoa III <mjn3@codepoet.org>
Mon, 19 Feb 2001 20:33:38 +0000 (20:33 -0000)
libc/stdio/Makefile
libc/stdio/stdio.c

index 7c6b911..3c0103e 100644 (file)
@@ -35,7 +35,9 @@ ifeq ($(HAS_LONG_LONG),true)
 endif
 
 MSRC=stdio.c
-MOBJ=_stdio_init.o _stdio_buffer.o  clearerr.o feof.o ferror.o fileno.o \
+MOBJ=_stdio_init.o \
+     _alloc_stdio_buffer.o _free_stdio_buffer.o _free_stdio_stream.o \
+     clearerr.o feof.o ferror.o fileno.o \
      setbuffer.o setvbuf.o setbuf.o setlinebuf.o \
      fclose.o _fopen.o fopen.o freopen.o fdopen.o fflush.o \
      fseek.o rewind.o ftell.o fgetpos.o fsetpos.o \
index b3d514c..7ed5457 100644 (file)
@@ -49,7 +49,7 @@ extern void _free_stdio_buffer(unsigned char *buf);
 extern void _free_stdio_stream(FILE *fp);
 #endif
 
-#ifdef L__stdio_buffer
+#ifdef L__alloc_stdio_buffer
 unsigned char *_alloc_stdio_buffer(size_t size)
 {
        if (size == BUFSIZ) {
@@ -63,7 +63,9 @@ unsigned char *_alloc_stdio_buffer(size_t size)
        }
        return malloc(size);
 }
+#endif
 
+#ifdef L__free_stdio_buffer
 void _free_stdio_buffer(unsigned char *buf)
 {
        int i;
@@ -117,8 +119,10 @@ FILE *_stderr = _stdio_streams + 2;
  */
 FILE *__IO_list = _stdio_streams;                      /* For fflush at exit */
 
-/* Call the stdio initiliser; it's main job it to call atexit */
-
+/*
+ * __stdio_close_all is automatically when exiting if stdio is used.
+ * See misc/internals/__uClibc_main.c and and stdlib/atexit.c.
+ */
 void __stdio_close_all(void)
 {
        FILE *fp;
@@ -129,6 +133,9 @@ void __stdio_close_all(void)
        }
 }
 
+/*
+ * __init_stdio is automatically by __uClibc_main if stdio is used.
+ */
 void __init_stdio(void)
 {
 #if (FIXED_BUFFERS > 2) || (FIXED_STREAMS > 3)
@@ -148,12 +155,13 @@ void __init_stdio(void)
        _fixed_buffers[0].used = 1;
        _fixed_buffers[1].used = 1;
 
-       if (isatty(1)) {
-               stdout->mode |= _IOLBF;
-       }
+#if _IOFBF != 0 || _IOLBF != 1
+#error Assumption violated -- values of _IOFBF and/or _IOLBF
+/* This asssumption is also made in _fopen. */
+#endif
 
-       /* Cleanup is now taken care of in __uClibc_main. */
-       /* atexit(__stdio_close_all); */
+       /* stdout uses line buffering when connected to a tty. */
+       _stdio_streams[1].mode |= isatty(1);
 }
 #endif
 
@@ -206,9 +214,18 @@ FILE *fp;
        if (fp->mode & __MODE_WRITING)
                fflush(fp);
 
+#if 1
+#warning Need to check out tie between stdin and stdout.
+       /*
+        * This bit of code needs checking.  The way I read the C89 standard,
+        * there is no guarantee that stdout is flushed before reading stdin.
+        * Plus, this is broken if either stdin or stdout has been closed and
+        * reopend.
+        */
        if ( (fp == stdin) && (stdout->fd != -1) 
                 && (stdout->mode & __MODE_WRITING) ) 
            fflush(stdout);
+#endif
 
        /* Can't read or there's been an EOF or error then return EOF */
        if ((fp->mode & (__MODE_READ | __MODE_EOF | __MODE_ERR)) !=
@@ -572,32 +589,32 @@ const char *mode;
        int fopen_mode;
        int i;
 
-       fopen_mode = 0;
+       nfp = fp;
 
-       /* If we've got an fp close the old one (freopen) */
-       if (fp) {                                       /* We don't want to deallocate fp. */
-               fopen_mode |=
-                       (fp->mode & (__MODE_BUF | __MODE_FREEFIL | __MODE_FREEBUF));
-               fp->mode &= ~(__MODE_FREEFIL | __MODE_FREEBUF);
-               fclose(fp);
+       /* If we've got an fp, flush it and close the old fd (freopen) */
+       if (nfp) {                                      /* We don't want to deallocate fp. */
+               fflush(nfp);
+               close(nfp->fd);
+               nfp->mode &= (__MODE_FREEFIL | __MODE_FREEBUF);
        }
 
-       /* decode the new open mode */
+       /* Parse the mode string arg. */
        switch (*mode++) {
                case 'r':                               /* read */
-                       fopen_mode |= __MODE_READ;
+                       fopen_mode = __MODE_READ;
                        open_mode = O_RDONLY;
                        break;
                case 'w':                               /* write (create or truncate)*/
-                       fopen_mode |= __MODE_WRITE;
+                       fopen_mode = __MODE_WRITE;
                        open_mode = (O_WRONLY | O_CREAT | O_TRUNC);
                        break;
                case 'a':                               /* write (create or append) */
-                       fopen_mode |= __MODE_WRITE;
+                       fopen_mode = __MODE_WRITE;
                        open_mode = (O_WRONLY | O_CREAT | O_APPEND);
                        break;
                default:                                /* illegal mode */
-                       return 0;
+                       errno = EINVAL;
+                       goto _fopen_ERROR;
        }
 
        if ((*mode == 'b')) {           /* binary mode (nop for uClibc) */
@@ -618,7 +635,6 @@ const char *mode;
                ++mode;
        }
 
-       nfp = 0;
        if (fp == 0) {                          /* We need a FILE so allocate it before */
                for (i = 0; i < FIXED_STREAMS; i++) { /* we potentially call open. */
                        if (_stdio_streams[i].fd == -1) {
@@ -629,46 +645,46 @@ const char *mode;
                if ((i == FIXED_STREAMS) && (!(nfp = malloc(sizeof(FILE))))) {
                        return 0;
                }
+               nfp->mode = __MODE_FREEFIL;
+               /* Initially set to use 8 byte buffer in FILE structure */
+               nfp->bufstart = nfp->unbuf;
+               nfp->bufend = nfp->unbuf + sizeof(nfp->unbuf);
        }
 
-
        if (fname) {                            /* Open the file itself */
                fd = open(fname, open_mode, 0666);
        }
-       if (fd < 0) {                           /* Error from open or bad arg. */
+#warning fdopen should check that modes are compatible with existing fd.
+
+       if (fd < 0) {                           /* Error from open or bad arg passed. */
+       _fopen_ERROR:
                if (nfp) {
+                       if (nfp->mode & __MODE_FREEBUF) {
+                               _free_stdio_buffer(nfp->bufstart);
+                       }
                        _free_stdio_stream(nfp);
                }
                return 0;
        }
 
+       nfp->fd = fd;                           /* Set FILE's fd before adding to open list. */
+
        if (fp == 0) {                          /* Not freopen so... */
-               fp = nfp;                               /* use newly created FILE and */
-               fp->next = __IO_list;   /* add it to the list of open files. */
-               __IO_list = fp;
-
-               fp->mode = __MODE_FREEFIL;
-               if (!(fp->bufstart = _alloc_stdio_buffer(BUFSIZ))) {
-                       /* Allocation failed so use 8 byte buffer in FILE structure */
-                       fp->bufstart = fp->unbuf;
-                       fp->bufend = fp->unbuf + sizeof(fp->unbuf);
-               } else {
-                       fp->bufend = fp->bufstart + BUFSIZ;
-                       fp->mode |= __MODE_FREEBUF;
-               }
-       }
+               nfp->next = __IO_list;  /* use newly created FILE and */
+               __IO_list = nfp;                /* add it to the list of open files. */
 
-       if (isatty(fd)) {
-               fp->mode |= _IOLBF;
-       } else {                                        /* Note: the following should be optimized */
-               fp->mode |= _IOFBF;             /* away since we should have _IOFBF = 0. */
+               if ((nfp->bufstart = _alloc_stdio_buffer(BUFSIZ)) != 0) {
+                       nfp->bufend = nfp->bufstart + BUFSIZ;
+                       nfp->mode |= __MODE_FREEBUF;
+               }
        }
 
        /* Ok, file's ready clear the buffer and save important bits */
-       fp->bufpos = fp->bufread = fp->bufwrite = fp->bufstart;
-       fp->mode |= fopen_mode;
-       fp->fd = fd;
-       return fp;
+       nfp->bufpos = nfp->bufread = nfp->bufwrite = nfp->bufstart;
+       nfp->mode |= fopen_mode;
+       nfp->mode |= isatty(fd);
+
+       return nfp;
 }
 #endif
 
@@ -688,33 +704,38 @@ FILE *fp;
                rv = EOF;
        }
 
-       if (fp->mode & __MODE_FREEBUF) {
+       if (fp->mode & __MODE_FREEBUF) { /* Free buffer if necessary. */
                _free_stdio_buffer(fp->bufstart);
        }
 
-       if (fp->mode & __MODE_FREEFIL) {
-               prev = 0;
-               for (ptr = __IO_list; ptr ; ptr = ptr->next) {
-                       if (ptr == fp) {
-                               if (prev == 0) {
-                                       __IO_list = fp->next;
-                               } else {
-                                       prev->next = fp->next;
-                               }
-                               _free_stdio_stream(fp);
-                               break;
+       prev = 0;                                       /* Remove file from open list. */
+       for (ptr = __IO_list; ptr ; ptr = ptr->next) {
+               if (ptr == fp) {
+                       if (prev == 0) {
+                               __IO_list = fp->next;
+                       } else {
+                               prev->next = fp->next;
                        }
-                       prev = ptr;
+                       break;
                }
+               prev = ptr;
        }
 
+       _free_stdio_stream(fp);         /* Finally free the stream if necessary. */
+
        return rv;
 }
+#endif
 
-/* The following is only called by fclose and _fopen (which calls fclose) */
+#ifdef L__free_stdio_stream
+/* The following is only called by fclose and _fopen. */
 void _free_stdio_stream(FILE *fp)
 {
        int i;
+       
+       if (!(fp->mode & __MODE_FREEFIL)) {
+               return;
+       }
 
        for (i = 0; i < FIXED_STREAMS; i++) {
                if (fp == _stdio_streams + i) {