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