fs: fix standard zero, full devices
The standard devices are currently broken since they have the size ~0. As now files use loff_t as file size which is a signed type the read implementation gets confused and now returns -1. The current implementation also has the (somewhat theorical) problem that we do not have real streaming devices, so /dev/zero went out of zeroes after reading 4GB (or now LLONG_MAX). This patch introduces a new cdev flag DEVFS_IS_CHARACTER_DEV and a new file size flag FILE_SIZE_STREAM which makes it possible to create real stream devices instead. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
cca17e25bf
commit
8d064097eb
|
@ -40,7 +40,7 @@ static int zero_init(void)
|
|||
cdev = xzalloc(sizeof (*cdev));
|
||||
|
||||
cdev->name = "zero";
|
||||
cdev->size = ~0;
|
||||
cdev->flags = DEVFS_IS_CHARACTER_DEV;
|
||||
cdev->ops = &zeroops;
|
||||
|
||||
devfs_create(cdev);
|
||||
|
@ -68,7 +68,7 @@ static int full_init(void)
|
|||
cdev = xzalloc(sizeof (*cdev));
|
||||
|
||||
cdev->name = "full";
|
||||
cdev->size = ~0;
|
||||
cdev->flags = DEVFS_IS_CHARACTER_DEV;
|
||||
cdev->ops = &fullops;
|
||||
|
||||
devfs_create(cdev);
|
||||
|
@ -95,7 +95,7 @@ static int null_init(void)
|
|||
cdev = xzalloc(sizeof (*cdev));
|
||||
|
||||
cdev->name = "null";
|
||||
cdev->size = 0;
|
||||
cdev->flags = DEVFS_IS_CHARACTER_DEV;
|
||||
cdev->ops = &nullops;
|
||||
|
||||
devfs_create(cdev);
|
||||
|
|
|
@ -121,7 +121,8 @@ static int devfs_open(struct device_d *_dev, FILE *f, const char *filename)
|
|||
if (!cdev)
|
||||
return -ENOENT;
|
||||
|
||||
f->size = cdev->size;
|
||||
f->size = cdev->flags & DEVFS_IS_CHARACTER_DEV ?
|
||||
FILE_SIZE_STREAM : cdev->size;
|
||||
f->inode = cdev;
|
||||
|
||||
if (cdev->ops->open) {
|
||||
|
|
8
fs/fs.c
8
fs/fs.c
|
@ -643,7 +643,7 @@ int read(int fd, void *buf, size_t count)
|
|||
|
||||
fsdrv = dev_to_fs_driver(dev);
|
||||
|
||||
if (f->pos + count > f->size)
|
||||
if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size)
|
||||
count = f->size - f->pos;
|
||||
|
||||
if (!count)
|
||||
|
@ -672,7 +672,7 @@ ssize_t write(int fd, const void *buf, size_t count)
|
|||
dev = f->dev;
|
||||
|
||||
fsdrv = dev_to_fs_driver(dev);
|
||||
if (f->pos + count > f->size) {
|
||||
if (f->size != FILE_SIZE_STREAM && f->pos + count > f->size) {
|
||||
ret = fsdrv->truncate(dev, f, f->pos + count);
|
||||
if (ret) {
|
||||
if (ret != -ENOSPC)
|
||||
|
@ -740,12 +740,12 @@ loff_t lseek(int fildes, loff_t offset, int whence)
|
|||
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
if (offset > f->size)
|
||||
if (f->size != FILE_SIZE_STREAM && offset > f->size)
|
||||
goto out;
|
||||
pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
if (offset + f->pos > f->size)
|
||||
if (f->size != FILE_SIZE_STREAM && offset + f->pos > f->size)
|
||||
goto out;
|
||||
pos = f->pos + offset;
|
||||
break;
|
||||
|
|
|
@ -417,6 +417,7 @@ int cdev_erase(struct cdev *cdev, size_t count, loff_t offset);
|
|||
#define DEVFS_PARTITION_FIXED (1 << 0)
|
||||
#define DEVFS_PARTITION_READONLY (1 << 1)
|
||||
#define DEVFS_IS_PARTITION (1 << 2)
|
||||
#define DEVFS_IS_CHARACTER_DEV (1 << 3)
|
||||
|
||||
int devfs_add_partition(const char *devname, loff_t offset, loff_t size,
|
||||
int flags, const char *name);
|
||||
|
|
|
@ -24,6 +24,7 @@ typedef struct dir {
|
|||
typedef struct filep {
|
||||
struct device_d *dev; /* The device this FILE belongs to */
|
||||
loff_t pos; /* current position in stream */
|
||||
#define FILE_SIZE_STREAM ((loff_t) -1)
|
||||
loff_t size; /* The size of this inode */
|
||||
ulong flags; /* the O_* flags from open */
|
||||
|
||||
|
|
Loading…
Reference in New Issue