1.6 lseek, read und write
- lseek: verschiebt Dateipositionszeiger
- read: Liest Puffer bestimmter Größe aus Datei
- write: Schreibt Puffer bestimmter Größe in Datei
/* Ausschnitte aus /usr/src/linux/fs/read_write.c (Kernel 2.2.5) */
asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
unsigned long offset_low, loff_t * result,
unsigned int origin)
{
int retval;
struct file * file;
struct dentry * dentry;
struct inode * inode;
loff_t offset;
lock_kernel();
retval = -EBADF;
file = fget(fd); /*Filepointer holen*/
if (!file)
goto bad;
/* N.B. Shouldn't this be ENOENT?? */
if (!(dentry = file->f_dentry) ||
!(inode = dentry->d_inode))
goto out_putf;
retval = -EINVAL; /*falsche Zahl übergeben*/
if (origin > 2)
goto out_putf;
offset = llseek(file, ((loff_t) offset_high << 32) | offset_low,
origin); /*llseek*/
retval = (int)offset;
if (offset >= 0) {
retval = -EFAULT;
if (!copy_to_user(result, &offset, sizeof(offset)))
retval = 0; /*Rückgabe*/
}
out_putf:
fput(file);
bad:
unlock_kernel();
return retval;
}
static inline loff_t llseek(struct file *file, loff_t offset, int origin)
{
loff_t (*fn)(struct file *, loff_t, int);
fn = default_llseek; /*default_llseek*/
if (file->f_op && file->f_op->llseek) /*lssek von spez. FS oder von VFS*/
fn = file->f_op->llseek;
return fn(file, offset, origin);
}
static loff_t default_llseek(struct file *file, loff_t offset, int origin)
{ /*loff_t: 64 Bit-Datei-Positionstyp*/
long long retval;
switch (origin) { /*berechnen*/
case 2:
offset += file->f_dentry->d_inode->i_size;
break;
case 1:
offset += file->f_pos;
}
retval = -EINVAL;
if (offset >= 0) {
if (offset != file->f_pos) { /*setzen der*/
file->f_pos = offset; /*neuen Position*/
file->f_reada = 0;
file->f_version = ++event;
}
retval = offset;
}
return retval;
}
asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count)
{
ssize_t ret;
struct file * file;
ssize_t (*read)(struct file *, char *, size_t, loff_t *);
lock_kernel(); /*Kernel lock*/
ret = -EBADF;
file = fget(fd); /*Filepointer aus Filenr.*/
if (!file)
goto bad_file;
if (!(file->f_mode & FMODE_READ)) /*Leserechte ? */
goto out;
ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode,
file, file->f_pos, count); /*lock for read*/
if (ret)
goto out;
ret = -EINVAL;
if (!file->f_op || !(read = file->f_op->read)) /*Zeiger read auf
f_op read*/
goto out;
ret = read(file, buf, count, &file->f_pos); /*Buffer füllen*/
out:
fput(file); /*File-Pointer freigeben*/
bad_file:
unlock_kernel(); /*Kernel unlock*/
return ret;
}
asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t
count)
{ /*fast wie sys_read*/
ssize_t ret;
struct file * file;
struct inode * inode;
ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
lock_kernel();
ret = -EBADF;
file = fget(fd);
if (!file)
goto bad_file;
if (!(file->f_mode & FMODE_WRITE))
goto out;
inode = file->f_dentry->d_inode;
ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,
file->f_pos, count);
if (ret)
goto out;
ret = -EINVAL;
if (!file->f_op || !(write = file->f_op->write))
goto out;
down(&inode->i_sem);
ret = write(file, buf, count, &file->f_pos); /*Puffer in Datei schreiben*/
up(&inode->i_sem);
out:
fput(file);
bad_file:
unlock_kernel();
return ret;
}
Zurück
Weiter
Inhalt