Пример #1
0
static int filldir(char *buf, int buflen, const char *name, int namelen,
		   loff_t offset, ino_t ino, unsigned int d_type, int *filled)
{
	struct dirent64 *dirent = (struct dirent64 *)(buf + *filled);
	struct dirent64  holder;
	int reclen = ROUND_UP64(NAME_OFFSET(dirent) + namelen + 1);

        /*
         * @buf is not guaranteed to be properly aligned. To work around,
         * first fill stack-allocated @holder, then copy @holder into @buf by
         * memmove().
         */

        /* check overflow */
        if ((*filled + reclen) > buflen)
                return 1;

        holder.d_ino = ino;
#ifdef _DIRENT_HAVE_D_OFF
        holder.d_off = offset;
#endif
        holder.d_reclen = reclen;
#ifdef _DIRENT_HAVE_D_TYPE
        holder.d_type = (unsigned short) d_type;
#endif
        /* gcc unrolls memcpy() of structs into field-wise assignments,
         * assuming proper alignment. Humor it. */
        (*memmover)(dirent, &holder, NAME_OFFSET(dirent));
        memcpy(dirent->d_name, name, namelen);
        dirent->d_name[namelen] = 0;

        *filled += reclen;

        return 0;
}
Пример #2
0
static int filldir64(void * __buf, const char * name, int namlen, loff_t offset,
		     ino_t 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);

	buf->error = -EINVAL;	/* only used if we fail.. */
	if (reclen > buf->count)
		return -EINVAL;
	dirent = buf->previous;
	if (dirent) {
		d.d_off = offset;
		copy_to_user(&dirent->d_off, &d.d_off, sizeof(d.d_off));
	}
	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;
	copy_to_user(dirent, &d, NAME_OFFSET(&d));
	copy_to_user(dirent->d_name, name, namlen);
	put_user(0, dirent->d_name + namlen);
	((char *) dirent) += reclen;
	buf->current_dir = dirent;
	buf->count -= reclen;
	return 0;
}
Пример #3
0
static int filldir64(void * __buf, const char * name, int namlen, loff_t offset,
		     ino_t ino, unsigned int d_type)
{
	struct linux_dirent64 __user *dirent;
	struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf;
	int reclen = ROUND_UP64(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(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;
	((char *) dirent) += reclen;
	buf->current_dir = dirent;
	buf->count -= reclen;
	return 0;
efault:
	buf->error = -EFAULT;
	return -EFAULT;
}