linux kernel write()

C
 ssize_t read(struct file *filp, char *buff,
     size_t count, loff_t *offp);
 ssize_t write(struct file *filp, const char *buff,
     size_t count, loff_t *offp);ssize_t scull_write(struct file *filp, const char *buf, size_t count,
    loff_t *f_pos)
{
 Scull_Dev *dev = filp->private_data;
 Scull_Dev *dptr;
 int quantum = dev->quantum;
 int qset = dev->qset;
 int itemsize = quantum * qset;
 int item, s_pos, q_pos, rest;
 ssize_t ret = -ENOMEM; /* value used in "goto out" statements */

 if (down_interruptible(&dev->sem))
   return -ERESTARTSYS;

 /* find list item, qset index and offset in the quantum */
 item = (long)*f_pos / itemsize;
 rest = (long)*f_pos % itemsize;
 s_pos = rest / quantum; q_pos = rest % quantum;

 /* follow the list up to the right position */
 dptr = scull_follow(dev, item);
 if (!dptr->data) {
  dptr->data = kmalloc(qset * sizeof(char *), GFP_KERNEL);
  if (!dptr->data)
   goto out;
  memset(dptr->data, 0, qset * sizeof(char *));
 }
 if (!dptr->data[s_pos]) {
  dptr->data[s_pos] = kmalloc(quantum, GFP_KERNEL);
  if (!dptr->data[s_pos])
   goto out;
 }
 /* write only up to the end of this quantum */
 if (count > quantum - q_pos)
  count = quantum - q_pos;

 if (copy_from_user(dptr->data[s_pos]+q_pos, buf, count)) {
  ret = -EFAULT;
	goto out;
 }
 *f_pos += count;
 ret = count;

 /* update the size */
 if (dev->size < *f_pos)
  dev-> size = *f_pos;

 out:
 up(&dev->sem);
 return ret;
} unsigned long copy_to_user(void *to, const void *from, 
        unsigned long count);
 unsigned long copy_from_user(void *to, const void *from, 
        unsigned long count); ssize_t (*readv) (struct file *filp, const struct iovec *iov, 
      unsigned long count, loff_t *ppos);
 ssize_t (*writev) (struct file *filp, const struct iovec *iov, 
      unsigned long count, loff_t *ppos);ssize_t scull_read(struct file *filp, char *buf, size_t count,
    loff_t *f_pos)
{
 Scull_Dev *dev = filp->private_data; /* the first list item */
 Scull_Dev *dptr;
 int quantum = dev->quantum;
 int qset = dev->qset;
 int itemsize = quantum * qset; /* how many bytes in the list item */
 int item, s_pos, q_pos, rest;
 ssize_t ret = 0;

 if (down_interruptible(&dev->sem))
   return -ERESTARTSYS;
 if (*f_pos >= dev->size)
  goto out;
 if (*f_pos + count > dev->size)
  count = dev->size - *f_pos;
 /* find list item, qset index, and offset in the quantum */
 item = (long)*f_pos / itemsize;
 rest = (long)*f_pos % itemsize;
 s_pos = rest / quantum; q_pos = rest % quantum;

 /* follow the list up to the right position (defined elsewhere) */
 dptr = scull_follow(dev, item);

 if (!dptr->data)
  goto out; /* don't fill holes */
 if (!dptr->data[s_pos])
  goto out;
 /* read only up to the end of this quantum */
 if (count > quantum - q_pos)
  count = quantum - q_pos;


 if (copy_to_user(buf, dptr->data[s_pos]+q_pos, count)) {
  ret = -EFAULT;
	goto out;
 }
 *f_pos += count;
 ret = count;

 out:
 up(&dev->sem);
 return ret;
}

Source

Also in C: