static int filldir64(void * __buf, const char * name, int namlen, loff_t offset, u64 ino, unsigned int d_type) { struct linux_dirent64 * dirent, d; struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf; int reclen = ROUND_UP64(NAME_OFFSET(dirent) + namlen + 1); int err; buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; dirent = buf->previous; if (dirent) { d.d_off = offset; err = copy_to_user(&dirent->d_off, &d.d_off, sizeof(d.d_off)); BUG_ON(err); } dirent = buf->current_dir; buf->previous = dirent; memset(&d, 0, NAME_OFFSET(&d)); d.d_ino = ino; d.d_reclen = reclen; d.d_type = d_type; err = copy_to_user(dirent, &d, NAME_OFFSET(&d)); BUG_ON(err); err = copy_to_user(dirent->d_name, name, namlen); BUG_ON(err); err = put_user(0, dirent->d_name + namlen); BUG_ON(err); dirent = (void *)dirent + reclen; buf->current_dir = dirent; buf->count -= reclen; return 0; }
static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, unsigned int d_type) { struct linux_dirent __user * dirent; struct getdents_callback * buf = (struct getdents_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) { if (__put_user(offset, &dirent->d_off)) goto efault; } dirent = buf->current_dir; if (__put_user(ino, &dirent->d_ino)) goto efault; if (__put_user(reclen, &dirent->d_reclen)) goto efault; if (copy_to_user(dirent->d_name, name, namlen)) goto efault; if (__put_user(0, dirent->d_name + namlen)) goto efault; buf->previous = dirent; ((char *) dirent) += reclen; buf->current_dir = dirent; buf->count -= reclen; return 0; efault: buf->error = -EFAULT; return -EFAULT; }
static int sunos_filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, unsigned int d_type) { 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); copy_to_user(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 filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino, unsigned int d_type) { struct linux32_dirent __user * dirent; struct getdents32_callback * buf = (struct getdents32_callback *) __buf; int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4); u32 d_ino; buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) return -EOVERFLOW; dirent = buf->previous; if (dirent) put_user(offset, &dirent->d_off); dirent = buf->current_dir; buf->previous = dirent; put_user(d_ino, &dirent->d_ino); put_user(reclen, &dirent->d_reclen); copy_to_user(dirent->d_name, name, namlen); put_user(0, dirent->d_name + namlen); dirent = ((void __user *)dirent) + reclen; buf->current_dir = dirent; buf->count -= reclen; return 0; }
static int sunos_filldirentry(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, unsigned int d_type) { struct sunos_direntry __user *dirent; struct sunos_direntry_callback * buf = (struct sunos_direntry_callback *) __buf; int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); u32 d_ino; buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) return -EOVERFLOW; dirent = buf->previous; dirent = buf->curr; buf->previous = dirent; put_user(d_ino, &dirent->d_ino); put_user(namlen, &dirent->d_namlen); put_user(reclen, &dirent->d_reclen); if (copy_to_user(dirent->d_name, name, namlen)) return -EFAULT; put_user(0, dirent->d_name + namlen); dirent = (void __user *) dirent + reclen; buf->curr = dirent; buf->count -= reclen; return 0; }
static int filldir(void * __buf, const char * name, int namlen, loff_t offset, u64 ino, unsigned d_type) { struct hpux_dirent __user * dirent; struct getdents_callback * buf = (struct getdents_callback *) __buf; ino_t d_ino; int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, sizeof(long)); buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { buf->error = -EOVERFLOW; return -EOVERFLOW; } dirent = buf->previous; if (dirent) if (put_user(offset, &dirent->d_off)) goto Efault; dirent = buf->current_dir; if (put_user(d_ino, &dirent->d_ino) || put_user(reclen, &dirent->d_reclen) || put_user(namlen, &dirent->d_namlen) || copy_to_user(dirent->d_name, name, namlen) || put_user(0, dirent->d_name + namlen)) goto Efault; buf->previous = dirent; buf->current_dir = (void __user *)dirent + reclen; buf->count -= reclen; return 0; Efault: buf->error = -EFAULT; return -EFAULT; }
static int filldir(void * __buf, const char * name, int namlen, loff_t offset, u64 ino, unsigned int d_type) { struct linux_dirent __user * dirent; struct getdents_callback * buf = (struct getdents_callback *) __buf; unsigned long d_ino; int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 2, sizeof(long)); int ret; buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { buf->error = -EOVERFLOW; return -EOVERFLOW; } dirent = buf->previous; if (dirent) { if (__put_user(offset, &dirent->d_off)) goto efault; } dirent = buf->current_dir; scribe_data_non_det(); ret = __put_user(d_ino, &dirent->d_ino); scribe_data_pop_flags(); if (ret) goto efault; if (__put_user(reclen, &dirent->d_reclen)) goto efault; if (copy_to_user(dirent->d_name, name, namlen)) goto efault; if (__put_user(0, dirent->d_name + namlen)) goto efault; if (__put_user(d_type, (char __user *) dirent + reclen - 1)) goto efault; buf->previous = dirent; dirent = (void __user *)dirent + reclen; buf->current_dir = dirent; buf->count -= reclen; return 0; efault: buf->error = -EFAULT; return -EFAULT; }
/* * Stupid Pico/Pilot/Pine!!! They are assuming that the returned st_size * field from a stat() syscall for a directory is the actual size of the * directory. But Cygwin returns zero and they don't check for that. * * The unfortunate result is that a diretory stat() is _very_ expensive... */ static void get_dir_size(char *name, struct linux_stat *ls) { DIR *dir; struct dirent *d; int size = 0; char file[MAX_PATH]; change_path_to_relative(file, (char*)name); my_print("[ender]get dir size %s \n", file); dir = opendir(file); if (NULL == dir) return; while (NULL != (d = readdir(dir))) { size += ROUND_UP(NAME_OFFSET(d) + strlen(d->d_name)+1); } ls->st_size = size; }
static int filldir64(void * __buf, const char * name, int namlen, loff_t offset, u64 ino, unsigned int d_type) { struct linux_dirent64 __user *dirent; struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf; int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, sizeof(u64)); buf->error = -EINVAL; /* only used if we fail.. */ if (reclen > buf->count) return -EINVAL; if (!gr_acl_handle_filldir(buf->file, name, namlen, ino)) return 0; dirent = buf->previous; if (dirent) { if (__put_user(offset, &dirent->d_off)) goto efault; } dirent = buf->current_dir; if (__put_user(ino, &dirent->d_ino)) goto efault; if (__put_user(0, &dirent->d_off)) goto efault; if (__put_user(reclen, &dirent->d_reclen)) goto efault; if (__put_user(d_type, &dirent->d_type)) goto efault; if (copy_to_user(dirent->d_name, name, namlen)) goto efault; if (__put_user(0, dirent->d_name + namlen)) goto efault; buf->previous = dirent; dirent = (void __user *)dirent + reclen; buf->current_dir = dirent; buf->count -= reclen; return 0; efault: buf->error = -EFAULT; return -EFAULT; }
static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino) { struct linux_dirent * dirent; struct getdents_callback * buf = (struct getdents_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->current_dir; buf->previous = dirent; put_user(ino, &dirent->d_ino); put_user(reclen, &dirent->d_reclen); memcpy_tofs(dirent->d_name, name, namlen); put_user(0, dirent->d_name + namlen); ((char *) dirent) += reclen; buf->current_dir = dirent; buf->count -= reclen; return 0; }
static int osf_filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino) { struct osf_dirent * dirent; struct osf_dirent_callback * buf = (struct osf_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; if (buf->basep) { put_user(offset, buf->basep); buf->basep = NULL; } dirent = buf->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_fs_byte(0, dirent->d_name + namlen); ((char *) dirent) += reclen; buf->dirent = dirent; buf->count -= reclen; return 0; }
static int ext2_readdir (struct inode * inode, struct file * filp, struct dirent * dirent, int count) { unsigned long offset, blk; int i, num, stored, dlen; struct buffer_head * bh, * tmp, * bha[16]; struct ext2_dir_entry * de; struct super_block * sb; int err, version; if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; sb = inode->i_sb; stored = 0; bh = NULL; offset = filp->f_pos & (sb->s_blocksize - 1); while (count > 0 && !stored && filp->f_pos < inode->i_size) { blk = (filp->f_pos) >> EXT2_BLOCK_SIZE_BITS(sb); bh = ext2_bread (inode, blk, 0, &err); if (!bh) { filp->f_pos += sb->s_blocksize - offset; continue; } /* * Do the readahead */ if (!offset) { for (i = 16 >> (EXT2_BLOCK_SIZE_BITS(sb) - 9), num = 0; i > 0; i--) { tmp = ext2_getblk (inode, ++blk, 0, &err); if (tmp && !tmp->b_uptodate && !tmp->b_lock) bha[num++] = tmp; else brelse (tmp); } if (num) { ll_rw_block (READA, num, bha); for (i = 0; i < num; i++) brelse (bha[i]); } } revalidate: /* If the dir block has changed since the last call to * readdir(2), then we might be pointing to an invalid * dirent right now. Scan from the start of the block * to make sure. */ if (filp->f_version != inode->i_version) { for (i = 0; i < sb->s_blocksize && i < offset; ) { de = (struct ext2_dir_entry *) (bh->b_data + i); /* It's too expensive to do a full * dirent test each time round this * loop, but we do have to test at * least that it is non-zero. A * failure will be detected in the * dirent test below. */ if (de->rec_len < EXT2_DIR_REC_LEN(1)) break; i += de->rec_len; } offset = i; filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | offset; filp->f_version = inode->i_version; } while (count > 0 && filp->f_pos < inode->i_size && offset < sb->s_blocksize) { de = (struct ext2_dir_entry *) (bh->b_data + offset); if (!ext2_check_dir_entry ("ext2_readdir", inode, de, bh, offset)) { /* On error, skip the f_pos to the next block. */ filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) + sb->s_blocksize; brelse (bh); return stored; } if (de->inode) { dlen = ROUND_UP(NAME_OFFSET(dirent) + de->name_len + 1); /* Old libc libraries always use a count of 1. */ if (count == 1 && !stored) count = dlen; if (count < dlen) { count = 0; break; } /* We might block in the next section * if the data destination is * currently swapped out. So, use a * version stamp to detect whether or * not the directory has been modified * during the copy operation. */ version = inode->i_version; i = de->name_len; memcpy_tofs (dirent->d_name, de->name, i); put_fs_long (de->inode, &dirent->d_ino); put_fs_byte (0, dirent->d_name + i); put_fs_word (i, &dirent->d_reclen); put_fs_long (dlen, &dirent->d_off); if (version != inode->i_version) goto revalidate; dcache_add(inode, de->name, de->name_len, de->inode); stored += dlen; count -= dlen; ((char *) dirent) += dlen; } offset += de->rec_len; filp->f_pos += de->rec_len; } offset = 0; brelse (bh); } if (!IS_RDONLY(inode)) { inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; } return stored; }
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <stddef.h> #include "panic.h" #include "settings.h" static struct name_to_offset { const char *name; int offset; } name_to_offset[] = { #define NAME_OFFSET(name, field) { name, offsetof(struct settings, field) }, NAME_OFFSET("control-type", control_type) NAME_OFFSET("pad-keysyms-0", pad_keysyms[0]) NAME_OFFSET("pad-keysyms-1", pad_keysyms[1]) NAME_OFFSET("pad-keysyms-2", pad_keysyms[2]) NAME_OFFSET("pad-keysyms-3", pad_keysyms[3]) NAME_OFFSET("pad-keysyms-4", pad_keysyms[4]) NAME_OFFSET("pad-keysyms-5", pad_keysyms[5]) NAME_OFFSET("pad-keysyms-6", pad_keysyms[6]) NAME_OFFSET("pad-keysyms-7", pad_keysyms[7]) NAME_OFFSET("pad-sticks-0", pad_sticks[0]) NAME_OFFSET("pad-sticks-1", pad_sticks[1]) NAME_OFFSET("pad-sticks-2", pad_sticks[2]) NAME_OFFSET("pad-sticks-3", pad_sticks[3]) NAME_OFFSET("pad-sticks-4", pad_sticks[4]) NAME_OFFSET("pad-sticks-5", pad_sticks[5]) NAME_OFFSET("pad-sticks-6", pad_sticks[6]) NAME_OFFSET("pad-sticks-7", pad_sticks[7])