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; }
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; }
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; }
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; }
/* * 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; }
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; }
/* * 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; }
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; }
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; }
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; }
/* * 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; }
/* * 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; }
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; }
/* * 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; }
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; }
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); }
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; }
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); }
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; }
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; }
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; }
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; }
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; }
/* * 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; }
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)); }
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; }
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; }
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; }
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; }
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; }