static ssize_t ospfs_read(struct file *filp, char __user *buffer, size_t count, loff_t *f_pos) { ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino); int retval = 0; size_t amount = 0; // Make sure we don't read past the end of the file! // Change 'count' so we never read past the end of the file. if(*f_pos > oi->oi_size) return 0; //we do not read past the end of the file if(*f_pos + count > oi->oi_size) count = oi->oi_size - *f_pos; /* EXERCISE: Your code here */ // Copy the data to user block by block while (amount < count && retval >= 0) { uint32_t blockno = ospfs_inode_blockno(oi, *f_pos); uint32_t n; char *data; //eprintk("reading!!"); // ospfs_inode_blockno returns 0 on error if (blockno == 0) { retval = -EIO; goto done; } data = ospfs_block(blockno); int offs = *f_pos % OSPFS_BLKSIZE; n = OSPFS_BLKSIZE - offs; int left = count - amount; n = (n > left) ? left : n; if(copy_to_user (buffer, data, n)) //if copy success return 0; { retval = -EFAULT; goto done; } //to: Destination address, in user space. //from: Source address, in kernel space. //n: Number of bytes to copy. // Figure out how much data is left in this block to read. // Copy data into user space. Return -EFAULT if unable to write // into user space. // Use variable 'n' to track number of bytes moved. /* EXERCISE: Your code here */ //retval = -EIO; // Replace these lines //goto done; buffer += n; amount += n; *f_pos += n; } done: return (retval >= 0 ? amount : retval); }
static ssize_t ospfs_read(struct file *filp, char __user *buffer, size_t count, loff_t *f_pos) { ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino); int retval = 0; size_t amount = 0; // Make sure we don't read past the end of the file! // Change 'count' so we never read past the end of the file. /* DONE: Your code here */ if (count > oi->oi_size - *f_pos) { count = oi->oi_size - *f_pos; } // Copy the data to user block by block while (amount < count && retval >= 0) { uint32_t blockno = ospfs_inode_blockno(oi, *f_pos); uint32_t n; char *data; // ospfs_inode_blockno returns 0 on error if (blockno == 0) { retval = -EIO; goto done; } data = ospfs_block(blockno); // Figure out how much data is left in this block to read. // Copy data into user space. Return -EFAULT if unable to write // into user space. // Use variable 'n' to track number of bytes moved. //goto done; long block_pos = *f_pos % OSPFS_BLKSIZE; if (count - amount > OSPFS_BLKSIZE - block_pos) { n = OSPFS_BLKSIZE - block_pos; } else { n = count - amount; } retval = copy_to_user(buffer, data + block_pos, n); if (retval != 0) { return -EFAULT; } buffer += n; amount += n; *f_pos += n; } done: return (retval >= 0 ? amount : retval); }
static ssize_t ospfs_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) { ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino); int retval = 0; size_t amount = 0; // Support files opened with the O_APPEND flag. To detect O_APPEND, // use struct file's f_flags field and the O_APPEND bit. /* EXERCISE: Your code here */ int append = filp->f_flags & O_APPEND; if (append) *f_pos = oi->oi_size; // If the user is writing past the end of the file, change the file's // size to accomodate the request. (Use change_size().) /* EXERCISE: Your code here */ if (count > oi->oi_size - *f_pos) { change_size(oi, count + oi->oi_size); } // Copy data block by block while (amount < count && retval >= 0) { uint32_t blockno = ospfs_inode_blockno(oi, *f_pos); uint32_t n; char *data; if (blockno == 0) { retval = -EIO; goto done; } data = ospfs_block(blockno); // Figure out how much data is left in this block to write. // Copy data from user space. Return -EFAULT if unable to read // read user space. // Keep track of the number of bytes moved in 'n'. /* EXERCISE: Your code here */ n = count - amount; //left to write! if (n > OSPFS_BLKSIZE) n = OSPFS_BLKSIZE; if (copy_from_user(data + *f_pos, buffer, n) != 0) { return -EFAULT; } buffer += n; amount += n; *f_pos += n; } done: return (retval >= 0 ? amount : retval); }
static ssize_t ospfs_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) { ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino); int retval = 0; size_t amount = 0; // Support files opened with the O_APPEND flag. To detect O_APPEND, // use struct file's f_flags field and the O_APPEND bit. /* EXERCISE: Your code here */ // If the user is writing past the end of the file, change the file's // size to accomodate the request. (Use change_size().) /* EXERCISE: Your code here */ // Copy data block by block while (amount < count && retval >= 0) { uint32_t blockno = ospfs_inode_blockno(oi, *f_pos); uint32_t n; char *data; if (blockno == 0) { retval = -EIO; goto done; } data = ospfs_block(blockno); //unsigned long copy_from_user ( (void *) ,(const void __user *) buffer, unsigned long count); // Returns: a pointer to that block's data //to Destination address, in kernel space. //from: Source address, in user space. //n: Number of bytes to copy. // Figure out how much data is left in this block to write. // Copy data from user space. Return -EFAULT if unable to read // read user space. // Keep track of the number of bytes moved in 'n'. /* EXERCISE: Your code here */ retval = -EIO; // Replace these lines goto done; buffer += n; amount += n; *f_pos += n; } done: return (retval >= 0 ? amount : retval); }
static ssize_t ospfs_read(struct file *filp, char __user *buffer, size_t count, loff_t *f_pos) { ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino); int retval = 0; size_t amount = 0; /* EXERCISE: Your code here */ //Never let count request more data than the file size if(count > oi->oi_size - *f_pos) count = oi->oi_size - *f_pos; // Copy the data to user block by block while (amount < count && retval >= 0) { uint32_t blockno = ospfs_inode_blockno(oi, *f_pos); uint32_t n; char *data; // ospfs_inode_blockno returns 0 on error if (blockno == 0) { retval = -EIO; goto done; } data = ospfs_block(blockno); /* EXERCISE: Your code here */ //Calulate amount of block left needed to copy n = count-amount; //Calculate offset of f_pos from a multiple of blocksize uint32_t offset = *f_pos % OSPFS_BLKSIZE; if(count-amount > OSPFS_BLKSIZE - offset){ n = OSPFS_BLKSIZE - offset; } if(copy_to_user(buffer, data + offset, n) != 0){ //eprintk("Unable to write into user space.\n"); retval = -EFAULT; goto done; } buffer += n; amount += n; *f_pos += n; } done: return (retval >= 0 ? amount : retval); }
static inline void * ospfs_inode_data(ospfs_inode_t *oi, uint32_t offset) { uint32_t blockno = ospfs_inode_blockno(oi, offset); return (uint8_t *) ospfs_block(blockno) + (offset % OSPFS_BLKSIZE); }
static ssize_t ospfs_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) { ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino); int retval = 0; size_t amount = 0; //eprintk("writing ~~~~~~~~~~~~~~~~~~"); // Support files opened with the O_APPEND flag. To detect O_APPEND, // use struct file's f_flags field and the O_APPEND bit. /* EXERCISE: Your code here */ if (filp->f_flags & O_APPEND) //if has the flag { *f_pos = oi->oi_size; } // If the user is writing past the end of the file, change the file's // size to accomodate the request. (Use change_size().) /* EXERCISE: Your code here */ if ((*f_pos+count) > oi->oi_size) { //static int change_size(ospfs_inode_t *oi, uint32_t want_size); int change = change_size(oi, (*f_pos+count)); if (change < 0) goto done; } // Copy data block by block while (amount < count && retval >= 0) { uint32_t blockno = ospfs_inode_blockno(oi, *f_pos); uint32_t n; char *data; if (blockno == 0) { retval = -EIO; goto done; } data = ospfs_block(blockno); // Figure out how much data is left in this block to write. // Copy data from user space. Return -EFAULT if unable to read // read user space. // Keep track of the number of bytes moved in 'n'. /* EXERCISE: Your code here */ //retval = -EIO; // Replace these lines //goto done; uint32_t blk_left = OSPFS_BLKSIZE - (*f_pos) % OSPFS_BLKSIZE; data = data + (*f_pos) % OSPFS_BLKSIZE; if (blk_left > (count-amount)) { blk_left = count - amount; } //unsigned long copy_from_user (void * to,const void __user * from,unsigned long n); if (copy_from_user(data,buffer,blk_left)!=0) return -EFAULT; buffer += n; amount += n; *f_pos += n; } done: return (retval >= 0 ? amount : retval); }
static ssize_t ospfs_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) { ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino); int retval = 0; size_t amount = 0; /* EXERCISE: Your code here */ //Detecting if appending to end of a file if(filp->f_flags & O_APPEND) *f_pos = oi->oi_size; /* EXERCISE: Your code here */ // If the user is writing past the end of the file, change the file's // size to accomodate the request. (Use change_size().) if(count > oi->oi_size - *f_pos) retval = change_size(oi, count + *f_pos); if(retval < 0){ //eprintk("Error changing file size.\n"); return retval; } // Copy data block by block while(amount < count && retval >= 0){ uint32_t blockno = ospfs_inode_blockno(oi, *f_pos); uint32_t n; char *data; if (blockno == 0){ retval = -EIO; goto done; } data = ospfs_block(blockno); // Figure out how much data is left in this block to write. // Copy data from user space. Return -EFAULT if unable to read // read user space. // Keep track of the number of bytes moved in 'n'. /* EXERCISE: Your code here */ uint32_t offset = *f_pos % OSPFS_BLKSIZE; n = count-amount; if(count-amount > OSPFS_BLKSIZE - offset){ n = OSPFS_BLKSIZE - offset; } if(copy_from_user(data + offset, buffer, n) != 0){ //eprintk("Unable to read from user space.\n"); retval = -EFAULT; goto done; } buffer += n; amount += n; *f_pos += n; } done: return (retval >= 0 ? amount : retval); }
static ssize_t ospfs_read(struct file *filp, char __user *buffer, size_t count, loff_t *f_pos) { ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino); int retval = 0; size_t amount = 0; // Make sure we don't read past the end of the file! // Change 'count' so we never read past the end of the file. /* EXERCISE: Your code here */ //SQ_additions if(*f_pos > oi->oi_size) { //check to make sure f_pos is not beyond end of file count = 0; } else if (count > oi->oi_size - *f_pos) { // else set count to size of remaining file count = oi->oi_size - *f_pos; } //end_SQ_additions // Copy the data to user block by block while (amount < count && retval >= 0) { uint32_t blockno = ospfs_inode_blockno(oi, *f_pos); uint32_t n; char *data; // ospfs_inode_blockno returns 0 on error if (blockno == 0) { retval = -EIO; goto done; } data = ospfs_block(blockno); // Figure out how much data is left in this block to read. // Copy data into user space. Return -EFAULT if unable to write // into user space. // Use variable 'n' to track number of bytes moved. /* EXERCISE: Your code here */ n = OSPFS_BLKSIZE - *f_pos % OSPFS_BLKSIZE; // If in the last block, make sure not to read past n = (n > count - amount) ? (count - amount) : n; if(copy_to_user((void*)buffer, (void*)data, n) != 0) { retval = -EFAULT; goto done; } /* END of SQ add*/ //retval = -EIO; // Replace these lines //goto done; buffer += n; amount += n; *f_pos += n; } done: return (retval >= 0 ? amount : retval); }
static ssize_t ospfs_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) { ospfs_inode_t *oi = ospfs_inode(filp->f_dentry->d_inode->i_ino); int retval = 0; size_t amount = 0; if (!count) return 0; if (count < 0 ) return -EIO; // Support files opened with the O_APPEND flag. To detect O_APPEND, // use struct file's f_flags field and the O_APPEND bit. /* DONE: Your code here */ if ((filp->f_flags & O_APPEND) == O_APPEND) { *f_pos = oi->oi_size; } // If the user is writing past the end of the file, change the file's // size to accomodate the request. (Use change_size().) /* DONE: Your code here */ if (count > oi->oi_size - *f_pos) { retval = change_size(oi, *f_pos + count); if (retval) return retval; } // Copy data block by block while (amount < count && retval >= 0) { uint32_t blockno = ospfs_inode_blockno(oi, *f_pos); uint32_t n; char *data; if (blockno == 0) { retval = -EIO; goto done; } data = ospfs_block(blockno); // Figure out how much data is left in this block to write. // Copy data from user space. Return -EFAULT if unable to // read user space. // Keep track of the number of bytes moved in 'n'. /* DONE: Your code here */ long block_pos = *f_pos % OSPFS_BLKSIZE; // if the amount to write is greater than the amount left in this block if (count - amount > OSPFS_BLKSIZE - block_pos) { n = OSPFS_BLKSIZE - block_pos; } // if amt to write is less than amt left else { n = count - amount; } retval = copy_from_user(data + block_pos, buffer, n); if (retval != 0) { return -EFAULT; } buffer += n; amount += n; *f_pos += n; } done: return (retval >= 0 ? amount : retval); }