VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / sound / core / info.c
index 0b08203..1eb7d91 100644 (file)
@@ -181,30 +181,37 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
        struct snd_info_entry *entry;
        snd_info_buffer_t *buf;
        size_t size = 0;
+       loff_t pos;
 
        data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
        snd_assert(data != NULL, return -ENXIO);
+       pos = *offset;
+       if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
+               return -EIO;
+       if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos)
+               return -EIO;
        entry = data->entry;
        switch (entry->content) {
        case SNDRV_INFO_CONTENT_TEXT:
                buf = data->rbuffer;
                if (buf == NULL)
                        return -EIO;
-               if (file->f_pos >= (long)buf->size)
+               if (pos >= buf->size)
                        return 0;
-               size = buf->size - file->f_pos;
+               size = buf->size - pos;
                size = min(count, size);
-               if (copy_to_user(buffer, buf->buffer + file->f_pos, size))
+               if (copy_to_user(buffer, buf->buffer + pos, size))
                        return -EFAULT;
-               file->f_pos += size;
                break;
        case SNDRV_INFO_CONTENT_DATA:
                if (entry->c.ops->read)
-                       return entry->c.ops->read(entry,
+                       size = entry->c.ops->read(entry,
                                                  data->file_private_data,
-                                                 file, buffer, count);
+                                                 file, buffer, count, pos);
                break;
        }
+       if ((ssize_t) size > 0)
+               *offset = pos + size;
        return size;
 }
 
@@ -215,34 +222,39 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer
        struct snd_info_entry *entry;
        snd_info_buffer_t *buf;
        size_t size = 0;
+       loff_t pos;
 
        data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
        snd_assert(data != NULL, return -ENXIO);
        entry = data->entry;
+       pos = *offset;
+       if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
+               return -EIO;
+       if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos)
+               return -EIO;
        switch (entry->content) {
        case SNDRV_INFO_CONTENT_TEXT:
                buf = data->wbuffer;
                if (buf == NULL)
                        return -EIO;
-               if (file->f_pos < 0)
-                       return -EINVAL;
-               if (file->f_pos >= (long)buf->len)
+               if (pos >= buf->len)
                        return -ENOMEM;
-               size = buf->len - file->f_pos;
+               size = buf->len - pos;
                size = min(count, size);
-               if (copy_from_user(buf->buffer + file->f_pos, buffer, size))
+               if (copy_from_user(buf->buffer + pos, buffer, size))
                        return -EFAULT;
-               if ((long)buf->size < file->f_pos + size)
-                       buf->size = file->f_pos + size;
-               file->f_pos += size;
+               if ((long)buf->size < pos + size)
+                       buf->size = pos + size;
                break;
        case SNDRV_INFO_CONTENT_DATA:
                if (entry->c.ops->write)
-                       return entry->c.ops->write(entry,
+                       size = entry->c.ops->write(entry,
                                                   data->file_private_data,
-                                                  file, buffer, count);
+                                                  file, buffer, count, pos);
                break;
        }
+       if ((ssize_t) size > 0)
+               *offset = pos + size;
        return size;
 }