You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by GitBox <gi...@apache.org> on 2021/04/05 17:06:11 UTC

[GitHub] [incubator-nuttx] v01d opened a new issue #3438: FAT: CAN'T SEEK TO END OF FILE IF READ-ONLY

v01d opened a new issue #3438:
URL: https://github.com/apache/incubator-nuttx/issues/3438


   ```
     Description: If the size of the underlying file is an exact multiple of the
                  FAT cluster size, then you cannot seek to the end of the file
                  if the file was opened read-only.  In that case, the FAT lseek
                  logic will return ENOSPC.
   
                  This is because seeking to the end of the file involves seeking
                  to an offset that is the size of the file (number of bytes
                  allocated for file + 1).  In order to seek to a position, the
                  current FAT implementation insists that there be allocated file
                  space at the seek position.  Seeking beyond the end of the file
                  has the side effect of extending the file.
   
                  [NOTE: This automatic extension of the file cluster allocation
                   is probably unnecessary and another issue of its own.]
   
                  For example, suppose you have a cluster size that is 4096 bytes
                  and a file that is 8192 bytes long.  Then the file will consist
                  of 2 allocated clusters at offsets 0 through 8191.
   
                  If the file is opened O_RDWR or O_WRONLY, then the statement:
   
                    offset = lseek(fd, 0, SET_SEEK);
   
                  will seek to offset 8192 which beyond the end of the file so a
                  new (empty) cluster will be added.  Now the file consists of
                  three clusters and the file position refers to the first byte of
                  the third cluster.
   
                  If the file is open O_RDONLY, however, then that same lseek
                  statement will fail.  It is not possible to seek to position
                  8192.  That is beyond the end of the allocated cluster chain
                  and since the file is read-only, it is not permitted to extend
                  the cluster chain.  Hence, the error ENOSPC is returned.
   
                  This code snippet will duplicate the problem. It assumes a
                  cluster size of 512 and that /tmp is a mounted FAT file system:
   
                    #define BUFSIZE 1024 //8192, depends on cluster size
                    static char buffer[BUFSIZE];
   
                    #if defined(BUILD_MODULE)
                    int main(int argc, FAR char *argv[])
                    #else
                    int hello_main(int argc, char *argv[])
                    #endif
                    {
                      ssize_t nwritten;
                      off_t pos;
                      int fd;
                      int ch;
                      int i;
   
                      for (i = 0, ch = ' '; i < BUFSIZE; i++)
                        {
                          buffer[i] = ch;
   
                          if (++ch == 0x7f)
                            {
                              ch = ' ';
                            }
                        }
   
                      fd = open("/tmp/testfile", O_WRONLY | O_CREAT | O_TRUNC, 0644);
                      if (fd < 0)
                        {
                          printf("open failed: %d\n", errno);
                          return 1;
                        }
   
                      nwritten = write(fd, buffer, BUFSIZE);
                      if (nwritten < 0)
                        {
                          printf("write failed: %d\n", errno);
                          return 1;
                        }
   
                      close(fd);
   
                      fd = open("/tmp/testfile", O_RDONLY);
                      if (fd < 0)
                        {
                          printf("open failed: %d\n", errno);
                          return 1;
                        }
   
                      pos = lseek(fd, 0, SEEK_END);
                      if (pos < 0)
                        {
                          printf("lseek failed: %d\n", errno);
                          return 1;
                        }
                      else if (pos != BUFSIZE)
                        {
                          printf("lseek failed: %d\n", pos);
                          return 1;
                        }
   
                      close(fd);
                      return 0;
                    }
   
     Status:      Open
     Priority:    Medium.  Although this is a significant design error, the problem
                  has existed for 11 years without being previously reported.  I
                  conclude, then that the exposure from this problem is not great.
   
                  Why would you seek to the end of a file using a read=only file
                  descriptor anyway?  Only one reason I can think of:  To get the
                  size of the file.  The alternative (and much more efficient) way
                  to do that is via stat().
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org