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:
[email protected]


Reply via email to