Skip to content

Commit

Permalink
Merge pull request #2167 from ghaerr/fat
Browse files Browse the repository at this point in the history
[kernel] Fix FAT filesystem adding blocks when seeking past EOF
  • Loading branch information
ghaerr authored Dec 31, 2024
2 parents 1d9d41f + bf7110b commit a0dca9c
Show file tree
Hide file tree
Showing 7 changed files with 19 additions and 12 deletions.
1 change: 1 addition & 0 deletions elks/fs/msdos/fat.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ cluster_t FATPROC get_cluster(register struct inode *inode, cluster_t cluster)
cluster_t this, count;

if (!(this = inode->u.msdos_i.i_start)) return 0;
debug("get_cluster %ld = %ld\n", cluster, this);
if (!cluster) return this;
count = 0;
for (cache_lookup(inode,cluster,&count,&this); count < cluster; count++) {
Expand Down
8 changes: 6 additions & 2 deletions elks/fs/msdos/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ static size_t msdos_file_write(register struct inode *inode,register struct file
int error;
char *start;
struct buffer_head *bh;
int dontuseisize;

debug_fat("file_write\n");
if (!inode) {
Expand All @@ -119,8 +120,11 @@ static size_t msdos_file_write(register struct inode *inode,register struct file
if (count <= 0) return 0;
error = 0;
for (start = buf; count; count -= size) {
while (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS(inode))))
if ((error = msdos_add_cluster(inode)) < 0) break;
while (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS(inode)))) {
/* don't use inode size in add_cluster if lseek past EOF */
dontuseisize = filp->f_pos > inode->i_size;
if ((error = msdos_add_cluster(inode, dontuseisize)) < 0) break;
}
if (error) break;
offset = (int)filp->f_pos & (SECTOR_SIZE(inode)-1);
size = MIN(SECTOR_SIZE(inode)-offset,count);
Expand Down
12 changes: 6 additions & 6 deletions elks/fs/msdos/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void FATPROC unlock_creation(void)
}


int FATPROC msdos_add_cluster(register struct inode *inode)
int FATPROC msdos_add_cluster(struct inode *inode, int dontuseisize)
{
static struct wait_queue wait;
static int lock = 0;
Expand All @@ -84,7 +84,7 @@ int FATPROC msdos_add_cluster(register struct inode *inode)
this = ((count+prev) % limit)+2;
if (fat_access(inode->i_sb,this,-1L) == 0) break;
}
debug("free cluster: %d\r\n",this);
debug_fat("free cluster: %d\r\n",this);

prev = (count+prev+1) % limit;
sb->previous_cluster = prev;
Expand All @@ -102,7 +102,7 @@ int FATPROC msdos_add_cluster(register struct inode *inode)
wake_up(&wait);
debug("set to %x\r\n",fat_access(inode->i_sb,this,-1L));

if (!S_ISDIR(inode->i_mode)) {
if (!S_ISDIR(inode->i_mode) && !dontuseisize) {
last = inode->i_size?
get_cluster(inode,(inode->i_size-1) / SECTOR_SIZE(inode) / sb->cluster_size)
: 0;
Expand All @@ -117,15 +117,15 @@ int FATPROC msdos_add_cluster(register struct inode *inode)
}
}
}
debug("last = %d\r\n",last);
debug_fat("last = %d\r\n",last);

if (last)
fat_access(inode->i_sb,last,this);
else {
inode->u.msdos_i.i_start = this;
inode->i_dirt = 1;
}
if (last) debug("next set to %d\r\n",fat_access(inode->i_sb,last,-1L));
if (last) debug_fat("next set to %d\r\n",fat_access(inode->i_sb,last,-1L));

for (curr = 0; curr < sb->cluster_size; curr++) {
sector = sb->data_start + (this - 2) * sb->cluster_size + curr;
Expand All @@ -151,7 +151,7 @@ int FATPROC msdos_add_cluster(register struct inode *inode)
}
}
if (bh) {
debug_fat("add_cluster block write %lu\n", buffer_blocknr(bh));
debug("add_cluster block write %lu\n", buffer_blocknr(bh));
mark_buffer_dirty(bh);
brelse(bh);
}
Expand Down
4 changes: 2 additions & 2 deletions elks/fs/msdos/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ static int FATPROC msdos_create_entry(struct inode *dir,const char *name,int is_
/* if rootdir return no space*/
if (dir->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
/* try adding space to directory*/
if ((res = msdos_add_cluster(dir)) < 0) return res;
if ((res = msdos_add_cluster(dir, 0)) < 0) return res;
/* if can't find empty entry return error*/
if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) return res;
}
Expand Down Expand Up @@ -259,7 +259,7 @@ int msdos_mkdir(struct inode *dir,const const char *name,size_t len,mode_t mode)
}

inode->u.msdos_i.i_busy = 1; /* prevent lookups */
if ((res = msdos_add_cluster(inode)) < 0) goto mkdir_error;
if ((res = msdos_add_cluster(inode, 0)) < 0) goto mkdir_error;
if ((res = msdos_create_entry(inode,MSDOS_DOT,1,&dot)) < 0)
goto mkdir_error;

Expand Down
2 changes: 1 addition & 1 deletion elks/fs/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ int sys_open(const char *filename, int flags, mode_t mode)
if ((flags + 1) & O_ACCMODE) flag++;
if (flag & (O_TRUNC | O_CREAT)) flag |= FMODE_WRITE;

debug_cache("\nOPEN '%t' flags %02x ", filename, flags);
debug_file("\nOPEN '%t' flags %02x ", filename, flags);
error = open_namei(filename, flag, mode, &inode, NULL);
if (!error) {
if ((error = open_fd(flags, inode)) < 0)
Expand Down
2 changes: 2 additions & 0 deletions elks/fs/read_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ int sys_lseek(unsigned int fd, loff_t * p_offset, unsigned int origin)
loff_t offset;

offset = (loff_t) get_user_long(p_offset);
debug_file("lseek %d, %ld, %d\n", fd, offset, origin);
if (fd >= NR_OPEN || !(file = current->files.fd[fd]) || !(file->f_inode))
return -EBADF;
if (origin > 2) return -EINVAL;
Expand Down Expand Up @@ -97,6 +98,7 @@ int sys_write(unsigned int fd, char *buf, size_t count)
register struct inode *inode;
int written;

debug_file("write %d, buf, %u\n", fd, count);
if (((written = fd_check(fd, buf, count, FMODE_WRITE, &file)) == 0) && count) {
written = -EINVAL;
fop = file->f_op;
Expand Down
2 changes: 1 addition & 1 deletion elks/include/linuxmt/msdos_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ struct buffer_head * FATPROC msdos_sread_nomap(struct super_block *s, sector_t s
struct buffer_head * FATPROC msdos_sread(struct super_block *s, sector_t sector, void **start);
void FATPROC lock_creation(void);
void FATPROC unlock_creation(void);
int FATPROC msdos_add_cluster(struct inode *inode);
int FATPROC msdos_add_cluster(struct inode *inode, int dontuseisize);
long FATPROC date_dos2unix(unsigned short time,unsigned short date);
void FATPROC date_unix2dos(long unix_date,unsigned short *time, unsigned short *date);
ino_t FATPROC msdos_get_entry(struct inode *dir,loff_t *pos,struct buffer_head **bh,
Expand Down

0 comments on commit a0dca9c

Please sign in to comment.