/* Truncate a file to 0 length. */ static void UMSDOS_truncate(struct inode *inode) { PRINTK (("UMSDOS_truncate\n")); msdos_truncate (inode); inode->i_ctime = inode->i_mtime = CURRENT_TIME; inode->i_dirt = 1; }
/* Write to a file either from user space */ int msdos_file_write( struct inode *inode, struct file *filp, const char *buf, int count) { struct super_block *sb = inode->i_sb; int sector,offset,size,left,written; int error,carry; char *start,*to,ch; struct buffer_head *bh; int binary_mode = MSDOS_I(inode)->i_binary; if (!inode) { printk("msdos_file_write: inode = NULL\n"); return -EINVAL; } /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */ if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) { printk("msdos_file_write: mode = %07o\n",inode->i_mode); return -EINVAL; } /* * ok, append may not work when many processes are writing at the same time * but so what. That way leads to madness anyway. */ if (filp->f_flags & O_APPEND) filp->f_pos = inode->i_size; if (count <= 0) return 0; error = carry = 0; for (start = (char *)buf; count || carry; count -= size) { while (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS))) if ((error = msdos_add_cluster(inode)) < 0) break; if (error) { msdos_truncate(inode); break; } offset = filp->f_pos & (SECTOR_SIZE-1); size = MIN(SECTOR_SIZE-offset,MAX(carry,count)); if (binary_mode && offset == 0 && (size == SECTOR_SIZE || filp->f_pos + size >= inode->i_size)){ /* No need to read the block first since we will */ /* completely overwrite it */ /* or at least write past the end of file */ if (!(bh = getblk(inode->i_dev,sector,SECTOR_SIZE))){ error = -EIO; break; } }else if (!(bh = bread(inode->i_dev,sector,SECTOR_SIZE))) { error = -EIO; break; } if (binary_mode) { memcpy_fromfs(bh->b_data+offset,buf,written = size); buf += size; } else { written = left = SECTOR_SIZE-offset; to = (char *) bh->b_data+(filp->f_pos & (SECTOR_SIZE-1)); if (carry) { *to++ = '\n'; left--; carry = 0; } for (size = 0; size < count && left; size++) { if ((ch = get_fs_byte(buf++)) == '\n') { *to++ = '\r'; left--; } if (!left) carry = 1; else { *to++ = ch; left--; } } written -= left; } filp->f_pos += written; if (filp->f_pos > inode->i_size) { inode->i_size = filp->f_pos; inode->i_dirt = 1; } msdos_set_uptodate(sb,bh,1); mark_buffer_dirty(bh, 0); brelse(bh); } if (start == buf) return error; inode->i_mtime = inode->i_ctime = FS_CURRENT_TIME; MSDOS_I(inode)->i_attrs |= ATTR_ARCH; inode->i_dirt = 1; return buf-start; }