示例#1
0
/**
 * This is called when vfs wants to populate internal buffers with
 * directory [dir]s contents. [opaque] is an argument to the
 * [filldir]. [filldir] magically modifies it's argument - [opaque]
 * and takes following additional arguments (which i in turn get from
 * the host via sf_getdent):
 *
 * name : name of the entry (i must also supply it's length huh?)
 * type : type of the entry (FILE | DIR | etc) (i ellect to use DT_UNKNOWN)
 * pos : position/index of the entry
 * ino : inode number of the entry (i fake those)
 *
 * [dir] contains:
 * f_pos : cursor into the directory listing
 * private_data : mean of communication with the host side
 *
 * Extract elements from the directory listing (incrementing f_pos
 * along the way) and feed them to [filldir] until:
 *
 * a. there are no more entries (i.e. sf_getdent set done to 1)
 * b. failure to compute fake inode number
 * c. filldir returns an error (see comment on that)
 */
static int sf_dir_read (struct file *dir, void *opaque, filldir_t filldir)
{
    TRACE();
    for (;;)
    {
        int err;
        ino_t fake_ino;
        loff_t sanity;
        char d_name[NAME_MAX];

        err = sf_getdent(dir, d_name);
        switch (err)
        {
            case 1:
                return 0;

            case 0:
                break;

            case -1:
            default:
                /* skip erroneous entry and proceed */
                LogFunc(("sf_getdent error %d\n", err));
                dir->f_pos += 1;
                continue;
        }

        /* d_name now contains a valid entry name */

        sanity = dir->f_pos + 0xbeef;
        fake_ino = sanity;
        if (sanity - fake_ino)
        {
            LogRelFunc(("can not compute ino\n"));
            return -EINVAL;
        }

        err = filldir(opaque, d_name, strlen(d_name),
                      dir->f_pos, fake_ino, DT_UNKNOWN);
        if (err)
        {
            LogFunc(("filldir returned error %d\n", err));
            /* Rely on the fact that filldir returns error
               only when it runs out of space in opaque */
            return 0;
        }

        dir->f_pos += 1;
    }

    BUG();
}
示例#2
0
static int sf_dir_read(struct file *dir, void *opaque, filldir_t filldir)
#endif
{
    TRACE();
    for (;;)
    {
        int err;
        ino_t fake_ino;
        loff_t sanity;
        char d_name[NAME_MAX];
        int d_type = DT_UNKNOWN;

        err = sf_getdent(dir, d_name, &d_type);
        switch (err)
        {
            case 1:
                return 0;

            case 0:
                break;

            case -1:
            default:
                /* skip erroneous entry and proceed */
                LogFunc(("sf_getdent error %d\n", err));
                dir->f_pos += 1;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
                ctx->pos += 1;
#endif
                continue;
        }

        /* d_name now contains a valid entry name */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
        sanity = ctx->pos + 0xbeef;
#else
        sanity = dir->f_pos + 0xbeef;
#endif
        fake_ino = sanity;
        if (sanity - fake_ino)
        {
            LogRelFunc(("can not compute ino\n"));
            return -EINVAL;
        }

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
        if (!dir_emit(ctx, d_name, strlen(d_name), fake_ino, d_type))
        {
            LogFunc(("dir_emit failed\n"));
            return 0;
        }
#else
        err = filldir(opaque, d_name, strlen(d_name), dir->f_pos, fake_ino, d_type);
        if (err)
        {
            LogFunc(("filldir returned error %d\n", err));
            /* Rely on the fact that filldir returns error
               only when it runs out of space in opaque */
            return 0;
        }
#endif

        dir->f_pos += 1;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
        ctx->pos += 1;
#endif
    }

    BUG();
}