return res;
}
-struct fat_ioctl_filldir_callback {
- struct dirent __user *dirent;
- int result;
- /* for dir ioctl */
- const char *longname;
- int long_len;
- const char *shortname;
- int short_len;
-};
-
static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
- filldir_t filldir, int short_only, int both)
+ filldir_t filldir, int shortnames, int both)
{
struct super_block *sb = inode->i_sb;
struct buffer_head *bh;
struct msdos_dir_entry *de;
struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;
struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;
- unsigned char long_slots;
- const char *fill_name;
- int fill_len;
wchar_t bufuname[14];
+ unsigned char long_slots;
wchar_t *unicode = NULL;
unsigned char c, work[8], bufname[56], *ptname = bufname;
unsigned long lpos, dummy, *furrfu = &lpos;
unsigned char alias_checksum;
if (!unicode) {
- unicode = (wchar_t *)__get_free_page(GFP_KERNEL);
+ unicode = (wchar_t *)
+ __get_free_page(GFP_KERNEL);
if (!unicode) {
filp->f_pos = cpos;
brelse(bh);
: uni16_to_x8(bufname, bufuname, uni_xlate, nls_io);
}
- fill_name = bufname;
- fill_len = i;
- if (!short_only && long_slots) {
- /* convert the unicode long name. 261 is maximum size
- * of unicode buffer. (13 * slots + nul) */
- void *longname = unicode + 261;
- int buf_size = PAGE_SIZE - (261 * sizeof(unicode[0]));
+ if (!long_slots||shortnames) {
+ if (both)
+ bufname[i] = '\0';
+ if (filldir(dirent, bufname, i, *furrfu, inum,
+ (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)
+ goto FillFailed;
+ } else {
+ unsigned char longname[275];
int long_len = utf8
- ? utf8_wcstombs(longname, unicode, buf_size)
- : uni16_to_x8(longname, unicode, uni_xlate, nls_io);
-
- if (!both) {
- fill_name = longname;
- fill_len = long_len;
- } else {
- /* hack for fat_ioctl_filldir() */
- struct fat_ioctl_filldir_callback *p = dirent;
-
- p->longname = longname;
- p->long_len = long_len;
- p->shortname = bufname;
- p->short_len = i;
- fill_name = NULL;
- fill_len = 0;
+ ? utf8_wcstombs(longname, unicode, sizeof(longname))
+ : uni16_to_x8(longname, unicode, uni_xlate,
+ nls_io);
+ if (both) {
+ memcpy(&longname[long_len+1], bufname, i);
+ long_len += i;
}
+ if (filldir(dirent, longname, long_len, *furrfu, inum,
+ (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)
+ goto FillFailed;
}
- if (filldir(dirent, fill_name, fill_len, *furrfu, inum,
- (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)
- goto FillFailed;
RecEnd:
furrfu = &lpos;
FillFailed:
if (bh)
brelse(bh);
- if (unicode)
- free_page((unsigned long)unicode);
+ if (unicode) {
+ free_page((unsigned long) unicode);
+ }
out:
unlock_kernel();
return ret;
return fat_readdirx(inode, filp, dirent, filldir, 0, 0);
}
-static int fat_ioctl_filldir(void *__buf, const char *name, int name_len,
+struct fat_ioctl_filldir_callback {
+ struct dirent __user *dirent;
+ int result;
+};
+
+static int fat_ioctl_filldir(void *__buf, const char * name, int name_len,
loff_t offset, ino_t ino, unsigned int d_type)
{
struct fat_ioctl_filldir_callback *buf = __buf;
struct dirent __user *d1 = buf->dirent;
struct dirent __user *d2 = d1 + 1;
+ int len, slen;
+ int dotdir;
if (buf->result)
return -EINVAL;
buf->result++;
- if (name != NULL) {
- /* dirent has only short name */
- if (name_len >= sizeof(d1->d_name))
- name_len = sizeof(d1->d_name) - 1;
-
- if (put_user(0, d2->d_name) ||
- put_user(0, &d2->d_reclen) ||
- copy_to_user(d1->d_name, name, name_len) ||
- put_user(0, d1->d_name + name_len) ||
- put_user(name_len, &d1->d_reclen))
+ if ((name_len == 1 && name[0] == '.') ||
+ (name_len == 2 && name[0] == '.' && name[1] == '.')) {
+ dotdir = 1;
+ len = name_len;
+ } else {
+ dotdir = 0;
+ len = strlen(name);
+ }
+ if (len != name_len) {
+ slen = name_len - len;
+ if (copy_to_user(d2->d_name, name, len) ||
+ put_user(0, d2->d_name + len) ||
+ put_user(len, &d2->d_reclen) ||
+ put_user(ino, &d2->d_ino) ||
+ put_user(offset, &d2->d_off) ||
+ copy_to_user(d1->d_name, name+len+1, slen) ||
+ put_user(0, d1->d_name+slen) ||
+ put_user(slen, &d1->d_reclen))
goto efault;
} else {
- /* dirent has short and long name */
- const char *longname = buf->longname;
- int long_len = buf->long_len;
- const char *shortname = buf->shortname;
- int short_len = buf->short_len;
-
- if (long_len >= sizeof(d1->d_name))
- long_len = sizeof(d1->d_name) - 1;
- if (short_len >= sizeof(d1->d_name))
- short_len = sizeof(d1->d_name) - 1;
-
- if (copy_to_user(d2->d_name, longname, long_len) ||
- put_user(0, d2->d_name + long_len) ||
- put_user(long_len, &d2->d_reclen) ||
- put_user(ino, &d2->d_ino) ||
- put_user(offset, &d2->d_off) ||
- copy_to_user(d1->d_name, shortname, short_len) ||
- put_user(0, d1->d_name + short_len) ||
- put_user(short_len, &d1->d_reclen))
+ if (put_user(0, d2->d_name) ||
+ put_user(0, &d2->d_reclen) ||
+ copy_to_user(d1->d_name, name, len) ||
+ put_user(0, d1->d_name+len) ||
+ put_user(len, &d1->d_reclen))
goto efault;
}
return 0;
{
struct fat_ioctl_filldir_callback buf;
struct dirent __user *d1;
- int ret, short_only, both;
+ int ret, shortname, both;
switch (cmd) {
case VFAT_IOCTL_READDIR_SHORT:
- short_only = 1;
- both = 0;
+ shortname = 1;
+ both = 1;
break;
case VFAT_IOCTL_READDIR_BOTH:
- short_only = 0;
+ shortname = 0;
both = 1;
break;
default:
ret = -ENOENT;
if (!IS_DEADDIR(inode)) {
ret = fat_readdirx(inode, filp, &buf, fat_ioctl_filldir,
- short_only, both);
+ shortname, both);
}
up(&inode->i_sem);
if (ret >= 0)
de[0].adate = de[0].cdate =
de[1].adate = de[1].cdate = date;
}
- de[0].start = cpu_to_le16(MSDOS_I(dir)->i_logstart);
- de[0].starthi = cpu_to_le16(MSDOS_I(dir)->i_logstart>>16);
- de[1].start = cpu_to_le16(MSDOS_I(parent)->i_logstart);
- de[1].starthi = cpu_to_le16(MSDOS_I(parent)->i_logstart>>16);
+ de[0].start = CT_LE_W(MSDOS_I(dir)->i_logstart);
+ de[0].starthi = CT_LE_W(MSDOS_I(dir)->i_logstart>>16);
+ de[1].start = CT_LE_W(MSDOS_I(parent)->i_logstart);
+ de[1].starthi = CT_LE_W(MSDOS_I(parent)->i_logstart>>16);
mark_buffer_dirty(bh);
brelse(bh);
dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;