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