/* * Writes to a file. */ PUBLIC ssize_t sys_write(int fd, const void *buf, size_t n) { dev_t dev; /* Device number. */ struct file *f; /* File. */ struct inode *i; /* Inode. */ ssize_t count = 0; /* Bytes actually written. */ /* Invalid file descriptor. */ if ((fd < 0) || (fd >= OPEN_MAX) || ((f = curr_proc->ofiles[fd]) == NULL)) return (-EBADF); /* File not opened for writing. */ if (ACCMODE(f->oflag) == O_RDONLY) return (-EBADF); /* Invalid buffer. */ if (!chkmem(buf, n, MAY_READ)) return (-EINVAL); i = f->inode; /* Append mode. */ if (f->oflag & O_APPEND) f->pos = i->size; /* Character special file. */ if (S_ISCHR(i->mode)) { dev = i->blocks[0]; count = cdev_write(dev, buf, n); return (count); } /* Block special file. */ else if (S_ISBLK(i->mode)) { dev = i->blocks[0]; count = bdev_write(dev, buf, n, f->pos); } /* Pipe file. */ else if (S_ISFIFO(i->mode)) { kprintf("write to pipe"); count = pipe_write(i, buf, n); } /* Regular file. */ else if (S_ISREG(i->mode)) count = file_write(i, buf, n, f->pos); /* Failed to write. */ if (count < 0) return (curr_proc->errno); f->pos += count; return (count); }
/*===========================================================================* * rw_block * *===========================================================================*/ static void rw_block( register struct buf *bp, /* buffer pointer */ int rw_flag /* READING or WRITING */ ) { /* Read or write a disk block. This is the only routine in which actual disk * I/O is invoked. If an error occurs, a message is printed here, but the error * is not reported to the caller. If the error occurred while purging a block * from the cache, it is not clear what the caller could do about it anyway. */ int r, op_failed = 0; u64_t pos; dev_t dev; if ( (dev = bp->b_dev) != NO_DEV) { pos = mul64u(bp->b_blocknr, fs_block_size); if (rw_flag == READING) r = bdev_read(dev, pos, bp->b_data, fs_block_size, BDEV_NOFLAGS); else r = bdev_write(dev, pos, bp->b_data, fs_block_size, BDEV_NOFLAGS); if (r < 0) { printf("Ext2(%d) I/O error on device %d/%d, block %u\n", SELF_E, major(dev), minor(dev), bp->b_blocknr); op_failed = 1; } else if (r != (ssize_t) fs_block_size) { r = END_OF_FILE; op_failed = 1; } if (op_failed) { bp->b_dev = NO_DEV; /* invalidate block */ /* Report read errors to interested parties. */ if (rw_flag == READING) rdwt_err = r; } } bp->b_dirt = CLEAN; }