Esempio n. 1
0
File: pipe.c Progetto: jbruchon/elks
static size_t pipe_read(register struct inode *inode, struct file *filp,
		     char *buf, size_t count)
{
    register char *chars;

    debug("PIPE: read called.\n");
    while (!(inode->u.pipe_i.q.len) || (inode->u.pipe_i.lock)) {
	if (!(inode->u.pipe_i.lock) && !(inode->u.pipe_i.writers)) return 0;
	if (filp->f_flags & O_NONBLOCK) return -EAGAIN;
	if (current->signal) return -ERESTARTSYS;
	interruptible_sleep_on(&(inode->u.pipe_i.q.wait));
    }
    (inode->u.pipe_i.lock)++;
    if (count > inode->u.pipe_i.q.len) count = inode->u.pipe_i.q.len;
    chars = (char *)(PIPE_BUF - inode->u.pipe_i.q.start);
    if ((size_t)chars > count) chars = (char *)count;
    memcpy_tofs(buf, (inode->u.pipe_i.q.base+inode->u.pipe_i.q.start), (size_t)chars);
    if ((size_t)chars < count)
	memcpy_tofs(buf + (size_t)chars, inode->u.pipe_i.q.base, count - (size_t)chars);
    inode->u.pipe_i.q.start = (inode->u.pipe_i.q.start + count) & (PIPE_BUF - 1);
    inode->u.pipe_i.q.len -= count;
    (inode->u.pipe_i.lock)--;
    wake_up_interruptible(&(inode->u.pipe_i.q.wait));
    if (count) inode->i_atime = CURRENT_TIME;
    else if ((inode->u.pipe_i.writers)) count = (size_t)(-EAGAIN);
    return count;
}
Esempio n. 2
0
int fcntl_getlk(unsigned int fd, struct flock *l)
{
	int error;
	struct flock flock;
	struct file *filp;
	struct file_lock *fl,file_lock;

	if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
		return -EBADF;
	error = verify_area(VERIFY_WRITE,l, sizeof(*l));
	if (error)
		return error;
	memcpy_fromfs(&flock, l, sizeof(flock));
	if (flock.l_type == F_UNLCK)
		return -EINVAL;
	if (!copy_flock(filp, &file_lock, &flock, fd))
		return -EINVAL;

	for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) {
		if (conflict(&file_lock, fl)) {
			flock.l_pid = fl->fl_owner->pid;
			flock.l_start = fl->fl_start;
			flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
				fl->fl_end - fl->fl_start + 1;
			flock.l_whence = fl->fl_whence;
			flock.l_type = fl->fl_type;
			memcpy_tofs(l, &flock, sizeof(flock));
			return 0;
		}
	}

	flock.l_type = F_UNLCK;			/* no conflict found */
	memcpy_tofs(l, &flock, sizeof(flock));
	return 0;
}
Esempio n. 3
0
static int read_core(struct inode * inode, struct file * file,char * buf, int count)
{
    unsigned long p = file->f_pos, memsize;
    int read;
    int count1;
    char * pnt;
    struct user dump;
#ifdef __i386__
#	define FIRST_MAPPED	PAGE_SIZE	/* we don't have page 0 mapped on x86.. */
#else
#	define FIRST_MAPPED	0
#endif

    memset(&dump, 0, sizeof(struct user));
    dump.magic = CMAGIC;
    dump.u_dsize = MAP_NR(high_memory);
#ifdef __alpha__
    dump.start_data = PAGE_OFFSET;
#endif

    if (count < 0)
        return -EINVAL;
    memsize = MAP_NR(high_memory + PAGE_SIZE) << PAGE_SHIFT;
    if (p >= memsize)
        return 0;
    if (count > memsize - p)
        count = memsize - p;
    read = 0;

    if (p < sizeof(struct user) && count > 0) {
        count1 = count;
        if (p + count1 > sizeof(struct user))
            count1 = sizeof(struct user)-p;
        pnt = (char *) &dump + p;
        memcpy_tofs(buf,(void *) pnt, count1);
        buf += count1;
        p += count1;
        count -= count1;
        read += count1;
    }

    while (count > 0 && p < PAGE_SIZE + FIRST_MAPPED) {
        put_user(0,buf);
        buf++;
        p++;
        count--;
        read++;
    }
    memcpy_tofs(buf, (void *) (PAGE_OFFSET + p - PAGE_SIZE), count);
    read += count;
    file->f_pos += read;
    return read;
}
Esempio n. 4
0
asmlinkage int osf_utsname(char * name)
{
	int error = verify_area(VERIFY_WRITE, name, 5*32);
	if (error)
		return error;
	memcpy_tofs(name +   0, system_utsname.sysname, 32);
	memcpy_tofs(name +  32, system_utsname.nodename, 32);
	memcpy_tofs(name +  64, system_utsname.release, 32);
	memcpy_tofs(name +  96, system_utsname.version, 32);
	memcpy_tofs(name + 128, system_utsname.machine, 32);
	return 0;
}
Esempio n. 5
0
/*
 * Copy the kernel symbol table to user space.  If the argument is null,
 * just return the size of the table.
 *
 * Note that the transient module symbols are copied _first_,
 * in lifo order!!!
 *
 * The symbols to "insmod" are according to the "old" format: struct kernel_sym,
 * which is actually quite handy for this purpose.
 * Note that insmod inserts a struct symbol_table later on...
 * (as that format is quite handy for the kernel...)
 *
 * For every module, the first (pseudo)symbol copied is the module name
 * and the address of the module struct.
 * This lets "insmod" keep track of references, and build the array of
 * struct module_refs in the symbol table.
 * The format of the module name is "#module", so that "insmod" can easily
 * notice when a module name comes along. Also, this will make it possible
 * to use old versions of "insmod", albeit with reduced functionality...
 * The "kernel" module has an empty name.
 */
asmlinkage int
sys_get_kernel_syms(struct kernel_sym *table)
{
	struct internal_symbol *from;
	struct kernel_sym isym;
	struct kernel_sym *to;
	struct module *mp = module_list;
	int i;
	int nmodsyms = 0;

	for (mp = module_list; mp; mp = mp->next) {
		if (mp->symtab && mp->symtab->n_symbols) {
			/* include the count for the module name! */
			nmodsyms += mp->symtab->n_symbols + 1;
		}
		else
			/* include the count for the module name! */
			nmodsyms += 1; /* return modules without symbols too */
	}

	if (table != NULL) {
		to = table;

		if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
			return i;

		/* copy all module symbols first (always LIFO order) */
		for (mp = module_list; mp; mp = mp->next) {
			if (mp->state == MOD_RUNNING) {
				/* magic: write module info as a pseudo symbol */
				isym.value = (unsigned long)mp;
				sprintf(isym.name, "#%s", mp->name);
				memcpy_tofs(to, &isym, sizeof isym);
				++to;

				if (mp->symtab != NULL) {
					for (i = mp->symtab->n_symbols,
						from = mp->symtab->symbol;
						i > 0; --i, ++from, ++to) {

						isym.value = (unsigned long)from->addr;
						strncpy(isym.name, from->name, sizeof isym.name);
						memcpy_tofs(to, &isym, sizeof isym);
					}
				}
			}
		}
	}

	return nmodsyms;
}
Esempio n. 6
0
static int array_read(struct inode * inode, struct file * file,char * buf, int count)
{
    unsigned long page;
    char *start;
    int length;
    int end;
    unsigned int type, pid;
    struct proc_dir_entry *dp;

    if (count < 0)
        return -EINVAL;
    if (count > PROC_BLOCK_SIZE)
        count = PROC_BLOCK_SIZE;
    if (!(page = __get_free_page(GFP_KERNEL)))
        return -ENOMEM;
    type = inode->i_ino;
    pid = type >> 16;
    type &= 0x0000ffff;
    start = NULL;
    dp = (struct proc_dir_entry *) inode->u.generic_ip;
    if (dp->get_info)
        length = dp->get_info((char *)page, &start, file->f_pos,
                              count, 0);
    else
        length = fill_array((char *) page, pid, type,
                            &start, file->f_pos, count);
    if (length < 0) {
        free_page(page);
        return length;
    }
    if (start != NULL) {
        /* We have had block-adjusting processing! */
        memcpy_tofs(buf, start, length);
        file->f_pos += length;
        count = length;
    } else {
        /* Static 4kB (or whatever) block capacity */
        if (file->f_pos >= length) {
            free_page(page);
            return 0;
        }
        if (count + file->f_pos > length)
            count = length - file->f_pos;
        end = count + file->f_pos;
        memcpy_tofs(buf, (char *) page + file->f_pos, count);
        file->f_pos = end;
    }
    free_page(page);
    return count;
}
Esempio n. 7
0
/*
 * This function accesses profiling information. The returned data is
 * binary: the sampling step and the actual contents of the profile
 * buffer. Use of the program readprofile is recommended in order to
 * get meaningful info out of these data.
 */
static int read_profile(struct inode *inode, struct file *file, char *buf, int count)
{
    unsigned long p = file->f_pos;
    int read;
    char * pnt;
    unsigned int sample_step = 1 << prof_shift;

    if (count < 0)
        return -EINVAL;
    if (p >= (prof_len+1)*sizeof(unsigned int))
        return 0;
    if (count > (prof_len+1)*sizeof(unsigned int) - p)
        count = (prof_len+1)*sizeof(unsigned int) - p;
    read = 0;

    while (p < sizeof(unsigned int) && count > 0) {
        put_user(*((char *)(&sample_step)+p),buf);
        buf++;
        p++;
        count--;
        read++;
    }
    pnt = (char *)prof_buffer + p - sizeof(unsigned int);
    memcpy_tofs(buf,(void *)pnt,count);
    read += count;
    file->f_pos += read;
    return read;
}
Esempio n. 8
0
static int minix_readlink(register struct inode *inode,
			  char *buffer, int buflen)
{
    register struct buffer_head *bh;
    size_t len;

    if (!S_ISLNK(inode->i_mode)) {
	iput(inode);
	return -EINVAL;
    }
    bh = minix_bread(inode, 0, 0);
    iput(inode);

    if (!bh)
	return 0;
    map_buffer(bh);

    if((len = strlen(bh->b_data) + 1) > buflen)
	len = buflen;
    if (len > 1023)
	len = 1023;
    memcpy_tofs(buffer, bh->b_data, len);
    unmap_brelse(bh);
    return len;
}
Esempio n. 9
0
static int sunos_filldir(void * __buf, const char * name, int namlen,
			 off_t offset, ino_t ino)
{
	struct sunos_dirent * dirent;
	struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;
	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);

	buf->error = -EINVAL;	/* only used if we fail.. */
	if (reclen > buf->count)
		return -EINVAL;
	dirent = buf->previous;
	if (dirent)
		put_user(offset, &dirent->d_off);
	dirent = buf->curr;
	buf->previous = dirent;
	put_user(ino, &dirent->d_ino);
	put_user(namlen, &dirent->d_namlen);
	put_user(reclen, &dirent->d_reclen);
	memcpy_tofs(dirent->d_name, name, namlen);
	put_user(0, dirent->d_name + namlen);
	((char *) dirent) += reclen;
	buf->curr = dirent;
	buf->count -= reclen;
	return 0;
}
Esempio n. 10
0
static int mem_read(struct inode * inode, struct file * file,char * buf, int count)
{
	struct task_struct * tsk;
	unsigned long addr;
	char *tmp;
	int i;
	
	if (count < 0)
		return -EINVAL;
	tsk = get_task(inode->i_ino >> 16);
	if (!tsk)
		return -ESRCH;
	addr = file->f_pos;
	tmp = buf;
	while (count > 0) {
		if (current->signal & ~current->blocked)
			break;
		i = count;
		memcpy_tofs(tmp, (void*)addr, i);
		addr += i;
		tmp += i;
		count -= i;
	}
	file->f_pos = addr;
	return tmp-buf;
}
Esempio n. 11
0
/*
 * Copy the kernel symbol table to user space.  If the argument is null,
 * just return the size of the table.
 */
asmlinkage int
sys_get_kernel_syms(struct kernel_sym *table)
{
	struct symbol {
		unsigned long addr;
		char *name;
	};
	extern int symbol_table_size;
	extern struct symbol symbol_table[];
	int i;
	struct symbol *from;
	struct kernel_sym *to;
	struct kernel_sym sym;

	if (table != NULL) {
		from = symbol_table;
		to = table;
		i = verify_area(VERIFY_WRITE, to, symbol_table_size * sizeof *table);
		if (i)
			return i;
		for (i = symbol_table_size ; --i >= 0 ; ) {
			sym.value = from->addr;
			strncpy(sym.name, from->name, sizeof sym.name);
			memcpy_tofs(to, &sym, sizeof sym);
			from++, to++;
		}
	}
	return symbol_table_size;
}
Esempio n. 12
0
/*
 * gets the current name or the name of the connected socket.
 */
static int
unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
		   int *usockaddr_len, int peer)
{
	struct unix_proto_data *upd;
	int len;

	PRINTK("unix_proto_getname: socket 0x%x for %s\n", sock,
	       peer ? "peer" : "self");
	if (peer) {
		if (sock->state != SS_CONNECTED) {
			PRINTK("unix_proto_getname: socket not connected\n");
			return -EINVAL;
		}
		upd = UN_DATA(sock->conn);
	}
	else
		upd = UN_DATA(sock);
	verify_area(usockaddr_len, sizeof(*usockaddr_len));
	if ((len = get_fs_long(usockaddr_len)) <= 0)
		return -EINVAL;
	if (len > upd->sockaddr_len)
		len = upd->sockaddr_len;
	if (len) {
		verify_area(usockaddr, len);
		memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
	}
	put_fs_long(len, usockaddr_len);
	return 0;
}
Esempio n. 13
0
static int ioctl_probe(struct Scsi_Host * host, void *buffer)
{
    int temp, result;
    unsigned int len,slen;
    const char * string;
    
    if ((temp = host->hostt->present) && buffer) {
        result = verify_area(VERIFY_READ, buffer, sizeof(long));
        if (result) return result;

	len = get_user ((unsigned int *) buffer);
	if(host->hostt->info)
	    string = host->hostt->info(host);
	else 
	    string = host->hostt->name;
	if(string) {
	    slen = strlen(string);
	    if (len > slen)
		len = slen + 1;
            result = verify_area(VERIFY_WRITE, buffer, len);
            if (result) return result;

	    memcpy_tofs (buffer, string, len);
	}
    }
    return temp;
}
Esempio n. 14
0
/*
 * I don't know what the parameters are: the first one
 * seems to be a timeval pointer, and I suspect the second
 * one is the time remaining.. Ho humm.. No documentation.
 */
asmlinkage int osf_usleep_thread(struct timeval * sleep, struct timeval * remain)
{
	struct timeval tmp;
	unsigned long ticks;
	int retval;

	retval = verify_area(VERIFY_READ, sleep, sizeof(*sleep));
	if (retval)
		return retval;
	if (remain && (retval = verify_area(VERIFY_WRITE, remain, sizeof(*remain))))
		return retval;
	memcpy_fromfs(&tmp, sleep, sizeof(*sleep));
	ticks = tmp.tv_usec;
	ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
	ticks += tmp.tv_sec * HZ;
	current->timeout = ticks + jiffies;
	current->state = TASK_INTERRUPTIBLE;
	schedule();
	if (!remain)
		return 0;
	ticks = jiffies;
	if (ticks < current->timeout)
		ticks = current->timeout - ticks;
	else
		ticks = 0;
	current->timeout = 0;
	tmp.tv_sec = ticks / HZ;
	tmp.tv_usec = ticks % HZ;
	memcpy_tofs(remain, &tmp, sizeof(*remain));
	return 0;
}
Esempio n. 15
0
int sys_sysinfo(struct sysinfo *info)
{
	int error;
	struct sysinfo val;
	struct task_struct **p;

	error = verify_area(VERIFY_WRITE, info, sizeof(struct sysinfo));
	if (error)
		return error;
	memset((char *)&val, 0, sizeof(struct sysinfo));

	val.uptime = (jiffies + jiffies_offset) / HZ;

	val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
	val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
	val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);

	for (p = &LAST_TASK; p > &FIRST_TASK; p--)
		if (*p) val.procs++;

	si_meminfo(&val);
	si_swapinfo(&val);

	memcpy_tofs(info, &val, sizeof(struct sysinfo));
	return 0;
}
Esempio n. 16
0
void ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
{
	unsigned long overhead;
	unsigned long overhead_per_group;
	struct statfs tmp;

	if (test_opt (sb, MINIX_DF))
		overhead = 0;
	else {
		/*
		 * Compute the overhead (FS structures)
		 */
		overhead_per_group = 1 /* super block */ +
				     sb->u.ext2_sb.s_db_per_group /* descriptors */ +
				     1 /* block bitmap */ +
				     1 /* inode bitmap */ +
				     sb->u.ext2_sb.s_itb_per_group /* inode table */;
		overhead = sb->u.ext2_sb.s_es->s_first_data_block +
			   sb->u.ext2_sb.s_groups_count * overhead_per_group;
	}

	tmp.f_type = EXT2_SUPER_MAGIC;
	tmp.f_bsize = sb->s_blocksize;
	tmp.f_blocks = sb->u.ext2_sb.s_es->s_blocks_count - overhead;
	tmp.f_bfree = ext2_count_free_blocks (sb);
	tmp.f_bavail = tmp.f_bfree - sb->u.ext2_sb.s_es->s_r_blocks_count;
	if (tmp.f_bfree < sb->u.ext2_sb.s_es->s_r_blocks_count)
		tmp.f_bavail = 0;
	tmp.f_files = sb->u.ext2_sb.s_es->s_inodes_count;
	tmp.f_ffree = ext2_count_free_inodes (sb);
	tmp.f_namelen = EXT2_NAME_LEN;
	memcpy_tofs(buf, &tmp, bufsiz);
}
Esempio n. 17
0
static int netlink_read(struct inode * inode, struct file * file, char * buf, int count)
{
	unsigned int minor = MINOR(inode->i_rdev);
	struct sk_buff *skb;
	cli();
	while((skb=skb_dequeue(&skb_queue_rd[minor]))==NULL)
	{
		if(file->f_flags&O_NONBLOCK)
		{
			sti();
			return -EAGAIN;
		}
		interruptible_sleep_on(&read_space_wait[minor]);
		if(current->signal & ~current->blocked)
		{
			sti();
			return -ERESTARTSYS;
		}
	}
	rdq_size[minor]-=skb->len;
	sti();
	if(skb->len<count)
		count=skb->len;
	memcpy_tofs(buf,skb->data,count);
	kfree_skb(skb, FREE_READ);
	return count;
}
Esempio n. 18
0
static void 
smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
	int error;
	struct smb_dskattr attr;
	struct statfs tmp;
	
	error = smb_proc_dskattr(sb, &attr);

	if (error) {
		printk("smb_statfs: dskattr error = %d\n", -error);
		attr.total = attr.allocblocks = attr.blocksize =
                        attr.free = 0;
	}

	tmp.f_type = SMB_SUPER_MAGIC;
	tmp.f_bsize = attr.blocksize*attr.allocblocks;
	tmp.f_blocks = attr.total;
	tmp.f_bfree = attr.free;
	tmp.f_bavail = attr.free;
	tmp.f_files = -1;
	tmp.f_ffree = -1;
	tmp.f_namelen = SMB_MAXPATHLEN;
	memcpy_tofs(buf, &tmp, bufsiz);
}
Esempio n. 19
0
asmlinkage int sys_sysinfo(struct sysinfo *info)
{
	int error;
	struct sysinfo val;

	error = verify_area(VERIFY_WRITE, info, sizeof(struct sysinfo));
	if (error)
		return error;
	memset((char *)&val, 0, sizeof(struct sysinfo));

	val.uptime = jiffies / HZ;

#ifdef	CONFIG_OSFMACH3
	osfmach3_update_load_info();
#endif	/* CONFIG_OSFMACH3 */
	val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
	val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
	val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);

	val.procs = nr_tasks-1;

	si_meminfo(&val);
	si_swapinfo(&val);

	memcpy_tofs(info, &val, sizeof(struct sysinfo));
	return 0;
}
Esempio n. 20
0
read_write_t scullv_read (struct inode *inode, struct file *filp,
                char *buf, count_t count)
{
    ScullV_Dev *dev = filp->private_data; /* the first listitem */
    int quantum = PAGE_SIZE << dev->order;
    int qset = dev->qset;
    int itemsize = quantum * qset; /* how many bytes in the listitem */
    unsigned long f_pos = (unsigned long)(filp->f_pos);
    int item, s_pos, q_pos, rest;

    if (f_pos > dev->size)
        return 0;
    if (f_pos + count > dev->size)
        count = dev->size - f_pos;
    /* find listitem, qset index and offset in the quantum */
    item = f_pos / itemsize;
    rest = f_pos % itemsize;
    s_pos = rest / quantum; q_pos = rest % quantum;

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

    if (!dev->data)
        return 0; /* don't fill holes */
    if (!dev->data[s_pos])
        return 0;
    if (count > quantum - q_pos)
        count = quantum - q_pos; /* read only up to the end of this quantum */
    memcpy_tofs(buf, dev->data[s_pos]+q_pos, count);
    filp->f_pos += count;
    return count;
}
Esempio n. 21
0
static int eql_g_slave_cfg(struct device *dev, slave_config_t *scp)
{
	slave_t *slave;
	equalizer_t *eql;
	struct device *slave_dev;
	slave_config_t sc;
	int err;

	err = verify_area(VERIFY_READ, (void *)scp, sizeof (slave_config_t));
	if (err) 
		return err;

	memcpy_fromfs (&sc, scp, sizeof (slave_config_t));
#ifdef EQL_DEBUG
	if (eql_debug >= 20)
		printk ("%s: get config for slave `%s'\n", dev->name, sc.slave_name);
#endif
	eql = (equalizer_t *) dev->priv;
	slave_dev = dev_get (sc.slave_name);

	if ( eql_is_slave (slave_dev) )
	{
		slave = eql_find_slave_dev (eql->queue,  slave_dev);
		if (slave != 0)
		{
			sc.priority = slave->priority;
			err = verify_area(VERIFY_WRITE, (void *)scp, sizeof (slave_config_t));
			if (err) 
				return err;
			memcpy_tofs (scp, &sc, sizeof (slave_config_t));
			return 0;
		}
	}
	return -EINVAL;
}
Esempio n. 22
0
asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf)
{
        struct super_block *s;
        struct ustat tmp;
        struct statfs sbuf;
        unsigned long old_fs;
        int error;

        s = get_super(to_kdev_t(dev));
        if (s == NULL)
                return -EINVAL;

        if (!(s->s_op->statfs))
                return -ENOSYS;

        error = verify_area(VERIFY_WRITE,ubuf,sizeof(struct ustat));
        if (error)
                return error;

        old_fs = get_fs();
        set_fs(get_ds());
        s->s_op->statfs(s,&sbuf,sizeof(struct statfs));
        set_fs(old_fs);

        memset(&tmp,0,sizeof(struct ustat));
        tmp.f_tfree = sbuf.f_bfree;
        tmp.f_tinode = sbuf.f_ffree;

        memcpy_tofs(ubuf,&tmp,sizeof(struct ustat));
        return 0;
}
Esempio n. 23
0
extern inline int copy_to_user(void *to, const void *from, unsigned long n)
{
        int i = verify_area(VERIFY_WRITE, to, n);
        if (i)
                return i;
        memcpy_tofs(to, from, n);
        return 0;
}
Esempio n. 24
0
/*
 * we read from our own buf.
 */
static int
unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
{
	struct unix_proto_data *upd;
	int todo, avail;

	if ((todo = size) <= 0)
		return 0;
	upd = UN_DATA(sock);
	while (!(avail = UN_BUF_AVAIL(upd))) {
		if (sock->state != SS_CONNECTED) {
			PRINTK("unix_proto_read: socket not connected\n");
			return (sock->state == SS_DISCONNECTING) ? 0 : -EINVAL;
		}
		PRINTK("unix_proto_read: no data available...\n");
		if (nonblock)
			return -EAGAIN;
		interruptible_sleep_on(sock->wait);
		if (current->signal & ~current->blocked) {
			PRINTK("unix_proto_read: interrupted\n");
			return -ERESTARTSYS;
		}
		if (sock->state == SS_DISCONNECTING) {
			PRINTK("unix_proto_read: disconnected\n");
			return 0;
		}
	}

	/*
	 * copy from the read buffer into the user's buffer, watching for
	 * wraparound. then we wake up the writer
	 */
	do {
		int part, cando;

		if (avail <= 0) {
			PRINTK("unix_proto_read: AVAIL IS NEGATIVE!!!\n");
			send_sig(SIGKILL,current,1);
			return -EINTR;
		}

		if ((cando = todo) > avail)
			cando = avail;
		if (cando > (part = BUF_SIZE - upd->bp_tail))
			cando = part;
		PRINTK("unix_proto_read: avail=%d, todo=%d, cando=%d\n",
		       avail, todo, cando);
		verify_area(ubuf, cando);
		memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
		upd->bp_tail = (upd->bp_tail + cando) & (BUF_SIZE-1);
		ubuf += cando;
		todo -= cando;
		if (sock->state == SS_CONNECTED)
			wake_up(sock->conn->wait);
		avail = UN_BUF_AVAIL(upd);
	} while (todo && avail);
	return size - todo;
}
Esempio n. 25
0
static void cp_new_stat(struct inode * inode, struct new_stat * statbuf)
{
	struct new_stat tmp;
	unsigned int blocks, indirect;

	memset(&tmp, 0, sizeof(tmp));
	tmp.st_dev = kdev_t_to_nr(inode->i_dev);
	tmp.st_ino = inode->i_ino;
	tmp.st_mode = inode->i_mode;
	tmp.st_nlink = inode->i_nlink;
	tmp.st_uid = inode->i_uid;
	tmp.st_gid = inode->i_gid;
	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
	tmp.st_size = inode->i_size;
	if (inode->i_pipe)
		tmp.st_size = PIPE_SIZE(*inode);
	tmp.st_atime = inode->i_atime;
	tmp.st_mtime = inode->i_mtime;
	tmp.st_ctime = inode->i_ctime;
/*
 * st_blocks and st_blksize are approximated with a simple algorithm if
 * they aren't supported directly by the filesystem. The minix and msdos
 * filesystems don't keep track of blocks, so they would either have to
 * be counted explicitly (by delving into the file itself), or by using
 * this simple algorithm to get a reasonable (although not 100% accurate)
 * value.
 */

/*
 * Use minix fs values for the number of direct and indirect blocks.  The
 * count is now exact for the minix fs except that it counts zero blocks.
 * Everything is in BLOCK_SIZE'd units until the assignment to
 * tmp.st_blksize.
 */
#define D_B   7
#define I_B   (BLOCK_SIZE / sizeof(unsigned short))

	if (!inode->i_blksize) {
		blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
		if (blocks > D_B) {
			indirect = (blocks - D_B + I_B - 1) / I_B;
			blocks += indirect;
			if (indirect > 1) {
				indirect = (indirect - 1 + I_B - 1) / I_B;
				blocks += indirect;
				if (indirect > 1)
					blocks++;
			}
		}
		tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
		tmp.st_blksize = BLOCK_SIZE;
	} else {
		tmp.st_blocks = inode->i_blocks;
		tmp.st_blksize = inode->i_blksize;
	}
	memcpy_tofs(statbuf,&tmp,sizeof(tmp));
}
Esempio n. 26
0
static int read_core(struct inode * inode, struct file * file,char * buf, int count)
{
	unsigned long p = file->f_pos;
	int read;
	int count1;
	char * pnt;
	struct user dump;

	memset(&dump, 0, sizeof(struct user));
	dump.magic = CMAGIC;
	dump.u_dsize = high_memory >> 12;

	if (count < 0)
		return -EINVAL;
	if (p >= high_memory + PAGE_SIZE)
		return 0;
	if (count > high_memory + PAGE_SIZE - p)
		count = high_memory + PAGE_SIZE - p;
	read = 0;

	if (p < sizeof(struct user) && count > 0) {
		count1 = count;
		if (p + count1 > sizeof(struct user))
			count1 = sizeof(struct user)-p;
		pnt = (char *) &dump + p;
		memcpy_tofs(buf,(void *) pnt, count1);
		buf += count1;
		p += count1;
		count -= count1;
		read += count1;
	}

	while (p < 2*PAGE_SIZE && count > 0) {
		put_fs_byte(0,buf);
		buf++;
		p++;
		count--;
		read++;
	}
	memcpy_tofs(buf,(void *) (p - PAGE_SIZE),count);
	read += count;
	file->f_pos += read;
	return read;
}
Esempio n. 27
0
static int mem_read(struct inode * inode, struct file * file,char * buf, int count)
{
	pgd_t *page_dir;
	pmd_t *page_middle;
	pte_t pte;
	char * page;
	struct task_struct * tsk;
	unsigned long addr;
	char *tmp;
	int i;

	if (count < 0)
		return -EINVAL;
	tsk = get_task(inode->i_ino >> 16);
	if (!tsk)
		return -ESRCH;
	addr = file->f_pos;
	count = check_range(tsk->mm, addr, count);
	if (count < 0)
		return count;
	tmp = buf;
	while (count > 0) {
		if (current->signal & ~current->blocked)
			break;
		page_dir = pgd_offset(tsk->mm,addr);
		if (pgd_none(*page_dir))
			break;
		if (pgd_bad(*page_dir)) {
			printk("Bad page dir entry %08lx\n", pgd_val(*page_dir));
			pgd_clear(page_dir);
			break;
		}
		page_middle = pmd_offset(page_dir,addr);
		if (pmd_none(*page_middle))
			break;
		if (pmd_bad(*page_middle)) {
			printk("Bad page middle entry %08lx\n", pmd_val(*page_middle));
			pmd_clear(page_middle);
			break;
		}
		pte = *pte_offset(page_middle,addr);
		if (!pte_present(pte))
			break;
		page = (char *) pte_page(pte) + (addr & ~PAGE_MASK);
		i = PAGE_SIZE-(addr & ~PAGE_MASK);
		if (i > count)
			i = count;
		memcpy_tofs(tmp, page, i);
		addr += i;
		tmp += i;
		count -= i;
	}
	file->f_pos = addr;
	return tmp-buf;
}
Esempio n. 28
0
int verified_memcpy_tofs(void *daddr, void *saddr, size_t len)
{
    int err = verify_area(VERIFY_WRITE, daddr, len);

    if (err)
        return err;

    memcpy_tofs(daddr, saddr, len);

    return 0;
}
Esempio n. 29
0
asmlinkage int sys_olduname(struct oldold_utsname * name)
{
    int error;
    if (!name)
        return -EFAULT;
    error = verify_area(VERIFY_WRITE, name,sizeof *name);
    if (error)
        return error;
    memcpy_tofs(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
    put_user(0,name->sysname+__OLD_UTS_LEN);
    memcpy_tofs(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
    put_user(0,name->nodename+__OLD_UTS_LEN);
    memcpy_tofs(&name->release,&system_utsname.release,__OLD_UTS_LEN);
    put_user(0,name->release+__OLD_UTS_LEN);
    memcpy_tofs(&name->version,&system_utsname.version,__OLD_UTS_LEN);
    put_user(0,name->version+__OLD_UTS_LEN);
    memcpy_tofs(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
    put_user(0,name->machine+__OLD_UTS_LEN);
    return 0;
}
Esempio n. 30
0
asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
{
	int error;

	if (tv) {
		struct timeval ktv;
		error = verify_area(VERIFY_WRITE, tv, sizeof *tv);
		if (error)
			return error;
		do_gettimeofday(&ktv);
		memcpy_tofs(tv, &ktv, sizeof(ktv));
	}
	if (tz) {
		error = verify_area(VERIFY_WRITE, tz, sizeof *tz);
		if (error)
			return error;
		memcpy_tofs(tz, &sys_tz, sizeof(sys_tz));
	}
	return 0;
}