static int proc_readbase(struct inode * inode, struct file * filp, struct dirent * dirent, int count) { struct proc_dir_entry * de; unsigned int pid, ino; int i,j; if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; ino = inode->i_ino; pid = ino >> 16; for (i = 0 ; i < NR_TASKS ; i++) if (task[i] && task[i]->pid == pid) break; if (!pid || i >= NR_TASKS) return 0; if (((unsigned) filp->f_pos) < NR_BASE_DIRENTRY) { de = base_dir + filp->f_pos; filp->f_pos++; i = de->namelen; ino = de->low_ino; if (ino != 1) ino |= (pid << 16); put_fs_long(ino, &dirent->d_ino); put_fs_word(i,&dirent->d_reclen); put_fs_byte(0,i+dirent->d_name); j = i; while (i--) put_fs_byte(de->name[i], i+dirent->d_name); return j; } return 0; }
static int read_mouse(struct inode * inode, struct file * file, char * buffer, int count) { int i; if (count < 3) return -EINVAL; if (!mouse.ready) return -EAGAIN; ATIXL_MSE_DISABLE_UPDATE(); /* Allowed interrupts to occur during data gathering - shouldn't hurt */ put_fs_byte((char)(~mouse.latch_buttons&7) | 0x80 , buffer); if (mouse.dx < -127) mouse.dx = -127; if (mouse.dx > 127) mouse.dx = 127; put_fs_byte((char)mouse.dx, buffer + 1); if (mouse.dy < -127) mouse.dy = -127; if (mouse.dy > 127) mouse.dy = 127; put_fs_byte((char)-mouse.dy, buffer + 2); for(i = 3; i < count; i++) put_fs_byte(0x00, buffer + i); mouse.dx = 0; mouse.dy = 0; mouse.latch_buttons = mouse.buttons; mouse.ready = 0; ATIXL_MSE_ENABLE_UPDATE(); return i; /* i data bytes returned */ }
int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) { int left,chars,nr; struct buffer_head * bh; if ((left=count)<=0) return 0; while (left) { if ((nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE))) { if (!(bh=bread(inode->i_dev,nr))) break; } else bh = NULL; nr = filp->f_pos % BLOCK_SIZE; chars = MIN( BLOCK_SIZE-nr , left ); filp->f_pos += chars; left -= chars; if (bh) { char * p = nr + bh->b_data; while (chars-->0) put_fs_byte(*(p++),buf++); brelse(bh); } else { while (chars-->0) put_fs_byte(0,buf++); } } inode->i_atime = CURRENT_TIME; return (count-left)?(count-left):-ERROR; }
static int xiafs_readdir(struct inode * inode, struct file * filp, struct dirent * dirent, int count) { u_int offset, i; struct buffer_head * bh; struct xiafs_direct * de; if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode)) return -EBADF; if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) ) return -EBADF; while (filp->f_pos < inode->i_size) { offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1); bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0); if (!bh) { filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset; continue; } de = (struct xiafs_direct *) (offset + bh->b_data); while (offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) { if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes || de->d_rec_len < 12 || (char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data || de->d_name_len < 1 || de->d_name_len + 8 > de->d_rec_len || de->d_name_len > _XIAFS_NAME_LEN || de->d_name[de->d_name_len] ) { printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR); brelse(bh); return 0; } offset += de->d_rec_len; filp->f_pos += de->d_rec_len; if (de->d_ino) { for (i = 0; i < de->d_name_len ; i++) put_fs_byte(de->d_name[i],i+dirent->d_name); put_fs_byte(0,i+dirent->d_name); put_fs_long(de->d_ino,&dirent->d_ino); put_fs_word(i,&dirent->d_reclen); brelse(bh); if (!IS_RDONLY (inode)) { inode->i_atime=CURRENT_TIME; inode->i_dirt=1; } return i; } de = (struct xiafs_direct *) (offset + bh->b_data); } brelse(bh); if (offset > XIAFS_ZSIZE(inode->i_sb)) { printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR); return 0; } } if (!IS_RDONLY (inode)) { inode->i_atime=CURRENT_TIME; inode->i_dirt=1; } return 0; }
static int ext_readdir(struct inode * inode, struct file * filp, struct dirent * dirent, int count) { unsigned int offset,i; char c; struct buffer_head * bh; struct ext_dir_entry * de; if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; if (filp->f_pos % 8 != 0) return -EBADF; while (filp->f_pos < inode->i_size) { offset = filp->f_pos & 1023; bh = ext_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0); if (!bh) { filp->f_pos += 1024-offset; continue; } de = (struct ext_dir_entry *) (offset + bh->b_data); while (offset < 1024 && filp->f_pos < inode->i_size) { if (de->rec_len < 8 || de->rec_len % 8 != 0 || de->rec_len < de->name_len + 8 || (de->rec_len + filp->f_pos - 1) / 1024 > (filp->f_pos / 1024)) { printk ("ext_readdir: bad dir entry, skipping\n"); printk ("dev=%d, dir=%d, offset=%d, rec_len=%d, name_len=%d\n", inode->i_dev, inode->i_ino, offset, de->rec_len, de->name_len); filp->f_pos += 1024-offset; if (filp->f_pos > inode->i_size) filp->f_pos = inode->i_size; continue; } offset += de->rec_len; filp->f_pos += de->rec_len; if (de->inode) { for (i = 0; i < de->name_len; i++) if ((c = de->name[i]) != 0) put_fs_byte(c,i+dirent->d_name); else break; if (i) { put_fs_long(de->inode,&dirent->d_ino); put_fs_byte(0,i+dirent->d_name); put_fs_word(i,&dirent->d_reclen); brelse(bh); return i; } } de = (struct ext_dir_entry *) ((char *) de + de->rec_len); } brelse(bh); } return 0; }
int block_read(int dev, unsigned long * pos, char * buf, int count) { int block = *pos >> BLOCK_SIZE_BITS; int offset = *pos & (BLOCK_SIZE-1); int chars; int read = 0; struct buffer_head * bh; register char * p; while (count > 0) { chars = BLOCK_SIZE-offset; if (chars > count) chars = count; if (!(bh = breada(dev, block, block + 1, block + 2, -1))) { return read?read:-EIO; } block++; p = offset + bh->b_data; offset = 0; *pos += chars; read += chars; count -= chars; while (chars-- > 0) { put_fs_byte(*(p++),buf++); } brelse(bh); } return read; }
static int ext2_readlink (struct inode * inode, char * buffer, int buflen) { struct buffer_head * bh = NULL; char * link; int i, err; char c; if (!S_ISLNK(inode->i_mode)) { iput (inode); return -EINVAL; } if (buflen > inode->i_sb->s_blocksize - 1) buflen = inode->i_sb->s_blocksize - 1; if (inode->i_blocks) { bh = ext2_bread (inode, 0, 0, &err); if (!bh) { iput (inode); return 0; } link = bh->b_data; } else link = (char *) inode->u.ext2_i.i_data; i = 0; while (i < buflen && (c = link[i])) { i ++; put_fs_byte (c, buffer++); } iput (inode); if (bh) brelse (bh); return i; }
static int sysv_readlink(struct inode * inode, char * buffer, int buflen) { struct buffer_head * bh; char * bh_data; int i; char c; if (!S_ISLNK(inode->i_mode)) { iput(inode); return -EINVAL; } if (buflen > inode->i_sb->sv_block_size_1) buflen = inode->i_sb->sv_block_size_1; bh = sysv_file_bread(inode, 0, 0); iput(inode); if (!bh) return 0; bh_data = bh->b_data; i = 0; while (i<buflen && (c = bh_data[i])) { i++; put_fs_byte(c,buffer++); } brelse(bh); return i; }
static int do_get_ps_info(int arg) { struct tstruct { int flag; int present[NR_TASKS]; struct task_struct tasks[NR_TASKS]; }; struct tstruct *ts = (struct tstruct *)arg; struct task_struct **p; char *c, *d; int i, n = 0; verify_area((void *)arg, sizeof(struct tstruct)); for (p = &FIRST_TASK ; p <= &LAST_TASK ; p++, n++) if (*p) { c = (char *)(*p); d = (char *)(ts->tasks+n); for (i=0 ; i<sizeof(struct task_struct) ; i++) put_fs_byte(*c++, d++); put_fs_long(1, (unsigned long *)(ts->present+n)); } else put_fs_long(0, (unsigned long *)(ts->present+n)); return(0); }
int read_pipe(struct m_inode * inode, char * buf, int count) { int chars, size, read = 0; while (count>0) { while (!(size=PIPE_SIZE(*inode))) { wake_up(&inode->i_wait); if (inode->i_count != 2) /* are there any writers? */ return read; sleep_on(&inode->i_wait); } chars = PAGE_SIZE-PIPE_TAIL(*inode); if (chars > count) chars = count; if (chars > size) chars = size; count -= chars; read += chars; size = PIPE_TAIL(*inode); PIPE_TAIL(*inode) += chars; PIPE_TAIL(*inode) &= (PAGE_SIZE-1); while (chars-->0) put_fs_byte(((char *)inode->i_size)[size++],buf++); } wake_up(&inode->i_wait); return read; }
int tty_read(unsigned channel, char * buf, int nr) { struct tty_struct * tty; char c, * b=buf; int minimum,time,flag=0; long oldalarm; if (channel>2 || nr<0) return -1; tty = &tty_table[channel]; oldalarm = current->alarm; time = 10L*tty->termios.c_cc[VTIME]; minimum = tty->termios.c_cc[VMIN]; if (time && !minimum) { minimum=1; if (0 != (flag=(!oldalarm || time+jiffies<oldalarm))) current->alarm = time+jiffies; } if (minimum>nr) minimum=nr; while (nr>0) { if (flag && (current->signal & ALRMMASK)) { current->signal &= ~ALRMMASK; break; } if (current->signal) break; if (EMPTY(tty->secondary) || (L_CANON(tty) && !tty->secondary.data && LEFT(tty->secondary)>20)) { sleep_if_empty(&tty->secondary); continue; } do { GETCH(tty->secondary,c); if (c==EOF_CHAR(tty) || c==10) tty->secondary.data--; if (c==EOF_CHAR(tty) && L_CANON(tty)) return (b-buf); else { put_fs_byte(c,b++); if (!--nr) break; } } while (nr>0 && !EMPTY(tty->secondary)); if (time && !L_CANON(tty)) { if (0 != (flag=(!oldalarm || time+jiffies<oldalarm))) current->alarm = time+jiffies; else current->alarm = oldalarm; } if (L_CANON(tty)) { if (b-buf) break; } else if (b-buf >= minimum) break; } current->alarm = oldalarm; if (current->signal && !(b-buf)) return -EINTR; return (b-buf); }
static int clear_memory (unsigned long addr, unsigned long size) { int status; size = (PAGE_SIZE - (addr & ~PAGE_MASK)) & ~PAGE_MASK; if (size == 0) status = 0; else { #ifdef COFF_DEBUG printk ("un-initialized storage in last page %d\n", size); #endif status = verify_area (VERIFY_WRITE, (void *) addr, size); #ifdef COFF_DEBUG printk ("result from verify_area = %d\n", status); #endif if (status >= 0) while (size-- != 0) put_fs_byte (0, addr++); } return status; }
static int isofs_readlink(struct inode * inode, char * buffer, int buflen) { char * pnt; int i; char c; if (!S_ISLNK(inode->i_mode)) { iput(inode); return -EINVAL; } if (buflen > 1023) buflen = 1023; pnt = get_rock_ridge_symlink(inode); iput(inode); if (!pnt) return 0; i = 0; while (i<buflen && (c = pnt[i])) { i++; put_fs_byte(c,buffer++); } kfree(pnt); return i; }
/* 块设备读 读的原理类似与写(从高速缓存中读) */ int block_read(int dev, unsigned long * pos, char * buf, int count) { int block = *pos >> BLOCK_SIZE_BITS; int offset = *pos & (BLOCK_SIZE-1); int chars; int size; int read = 0; struct buffer_head * bh; register char * p; if (blk_size[MAJOR(dev)]) size = blk_size[MAJOR(dev)][MINOR(dev)]; else size = 0x7fffffff; while (count>0) { if (block >= size) return read?read:-EIO; chars = BLOCK_SIZE-offset; if (chars > count) chars = count; if (!(bh = breada(dev,block,block+1,block+2,-1))) return read?read:-EIO; block++; p = offset + bh->b_data; offset = 0; *pos += chars; read += chars; count -= chars; while (chars-->0) put_fs_byte(*(p++),buf++); brelse(bh); } return read; }
static int proc_readlink(struct inode * inode, char * buffer, int buflen) { int i; unsigned int dev,ino; char buf[64]; if (!S_ISLNK(inode->i_mode)) { iput(inode); return -EINVAL; } i = proc_follow_link(NULL, inode, 0, 0, &inode); if (i) return i; if (!inode) return -EIO; dev = inode->i_dev; ino = inode->i_ino; iput(inode); i = sprintf(buf,"[%04x]:%u", dev, ino); if (buflen > i) buflen = i; i = 0; while (i < buflen) put_fs_byte(buf[i++],buffer++); return i; }
//// 文件读函数 - 根据i节点和文件结构,读取文件中数据。 // 由i节点我们可以知道设备号,由filp结构可以知道文件中当前读写指针位置。buf指定 // 用户空间中缓冲区位置,count是需要读取字节数。返回值是实际读取的字节数,或出错号(小于0). int file_read(struct m_inode * inode, struct file * filp, char * buf, int count) { int left,chars,nr; struct buffer_head * bh; // 首先判断参数的有效性。若需要读取的字节数count小于等于0,则返回0.若还需要读 // 取的字节数不等于0,就循环执行下面操作,直到数据全部读出或遇到问题。在读循环 // 操作过程中,我们根据i节点和文件表结构信息,并利用bmap()得到包含文件当前读写 // 位置的数据块在设备上对应的逻辑块号nr。若nr不为0,则从i节点指定的设备上读取该 // 逻辑块。如果读操作是吧则退出循环。若nr为0,表示指定的数据块不存在,置缓冲块 // 指针为NULL。(filp->f_pos)/BLOCK_SIZE用于计算出文件当前指针所在的数据块号。 if ((left=count)<=0) return 0; while (left) { if ((nr = bmap(inode,(filp->f_pos)/BLOCK_SIZE))) { if (!(bh=bread(inode->i_dev,nr))) break; } else bh = NULL; // 接着我们计算文件读写指针在数据块中的偏移值nr,则在该数据块中我们希望读取的 // 字节数为(BLOCK_SIZE-nr)。然后和现在还需读取的字节数left做比较。其中小值 // 即为本次操作需读取的字节数chars。如果(BLOCK_SIZE-nr) > left,则说明该块 // 是需要读取的最后一块数据。反之还需要读取下一块数据。之后调整读写文件指针。 // 指针前移此次将读取的字节数chars,剩余字节计数left相应减去chars。 nr = filp->f_pos % BLOCK_SIZE; chars = MIN( BLOCK_SIZE-nr , left ); filp->f_pos += chars; left -= chars; // 若上面从设备上读到了数据,则将p指向缓冲块中开始读取数据的位置,并且复制chars // 字节到用户缓冲区buf中。否则往用户缓冲区中填入chars个0值字节。 if (bh) { char * p = nr + bh->b_data; while (chars-->0) put_fs_byte(*(p++),buf++); brelse(bh); } else { while (chars-->0) put_fs_byte(0,buf++); } } // 修改该i节点的访问时间为当前时间。返回读取的字节数,若读取字节数为0,则返回 // 出错号。CURRENT_TIME是定义在include/linux/sched.h中的宏,用于计算UNIX时间。 // 即从1970年1月1日0时0分0秒开始,到当前的时间,单位是秒。 inode->i_atime = CURRENT_TIME; return (count-left)?(count-left):-ERROR; }
static int get_termios(struct tty_struct * tty, struct termios * termios) { int i; verify_area(termios, sizeof (*termios)); for (i=0 ; i< (sizeof (*termios)) ; i++) put_fs_byte( ((char *)tty->termios)[i] , i+(char *)termios ); return 0; }
static int minix_readdir(struct inode * inode, struct file * filp, struct dirent * dirent, int count) { unsigned int offset,i; char c; struct buffer_head * bh; struct minix_dir_entry * de; struct minix_sb_info * info; if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode)) return -EBADF; info = &inode->i_sb->u.minix_sb; if (filp->f_pos & (info->s_dirsize - 1)) return -EBADF; while (filp->f_pos < inode->i_size) { offset = filp->f_pos & 1023; bh = minix_bread(inode,(filp->f_pos)>>BLOCK_SIZE_BITS,0); if (!bh) { filp->f_pos += 1024-offset; continue; } while (offset < 1024 && filp->f_pos < inode->i_size) { de = (struct minix_dir_entry *) (offset + bh->b_data); offset += info->s_dirsize; filp->f_pos += info->s_dirsize; if (de->inode) { for (i = 0; i < info->s_namelen; i++) if ((c = de->name[i]) != 0) put_fs_byte(c,i+dirent->d_name); else break; if (i) { put_fs_long(de->inode,&dirent->d_ino); put_fs_byte(0,i+dirent->d_name); put_fs_word(i,&dirent->d_reclen); brelse(bh); return i; } } } brelse(bh); } return 0; }
static int read_zero(struct inode * node,struct file * file,char * buf,int count) { int left; for (left = count; left > 0; left--) { put_fs_byte(0,buf); buf++; } return count; }
static int minix_readdir(struct inode * inode, struct file * filp, struct dirent * dirent, int count) { unsigned int block,offset,i; char c; struct buffer_head * bh; struct minix_dir_entry * de; if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; if (filp->f_pos & (sizeof (struct minix_dir_entry) - 1)) return -EBADF; while (filp->f_pos < inode->i_size) { offset = filp->f_pos & 1023; block = minix_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS); if (!block || !(bh = bread(inode->i_dev,block))) { filp->f_pos += 1024-offset; continue; } de = (struct minix_dir_entry *) (offset + bh->b_data); while (offset < 1024 && filp->f_pos < inode->i_size) { offset += sizeof (struct minix_dir_entry); filp->f_pos += sizeof (struct minix_dir_entry); if (de->inode) { for (i = 0; i < MINIX_NAME_LEN; i++) if (c = de->name[i]) put_fs_byte(c,i+dirent->d_name); else break; if (i) { put_fs_long(de->inode,&dirent->d_ino); put_fs_byte(0,i+dirent->d_name); put_fs_word(i,&dirent->d_reclen); brelse(bh); return i; } } de++; } brelse(bh); } return 0; }
asmlinkage int sys_olduname(struct oldold_utsname * name) { int error; if (!name) return -EFAULT; error = verify_area(VERIFY_WRITE, name,sizeof *name); if (error) return error; memcpy_tofs(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); put_fs_byte(0,name->sysname+__OLD_UTS_LEN); memcpy_tofs(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); put_fs_byte(0,name->nodename+__OLD_UTS_LEN); memcpy_tofs(&name->release,&system_utsname.release,__OLD_UTS_LEN); put_fs_byte(0,name->release+__OLD_UTS_LEN); memcpy_tofs(&name->version,&system_utsname.version,__OLD_UTS_LEN); put_fs_byte(0,name->version+__OLD_UTS_LEN); memcpy_tofs(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); put_fs_byte(0,name->machine+__OLD_UTS_LEN); return 0; }
static int get_termios(struct tty_struct * tty, struct termios * termios) { int i; i = verify_area(VERIFY_WRITE, termios, sizeof (*termios)); if (i) return i; for (i=0 ; i< (sizeof (*termios)) ; i++) put_fs_byte( ((char *)tty->termios)[i] , i+(char *)termios ); return 0; }
static inline void save_old(char * from,char * to) { int i; verify_area(to, sizeof(struct sigaction)); for (i=0 ; i< sizeof(struct sigaction) ; i++) { put_fs_byte(*from,to); from++; to++; } }
static int read_mouse(struct inode * inode, struct file * file, char * buffer, int count) { int i, dx, dy; if (count < 3) return -EINVAL; if (!mouse.ready) return -EAGAIN; put_fs_byte(mouse.buttons | 0x80, buffer); dx = mouse.dx < -127 ? -127 : mouse.dx > 127 ? 127 : mouse.dx; dy = mouse.dy < -127 ? 127 : mouse.dy > 127 ? -127 : -mouse.dy; put_fs_byte((char)dx, buffer + 1); put_fs_byte((char)dy, buffer + 2); for (i = 3; i < count; i++) put_fs_byte(0x00, buffer + i); mouse.dx -= dx; mouse.dy += dy; mouse.ready = 0; return i; }
static int read_port(struct inode * inode,struct file * file,char * buf, int count) { unsigned int i = file->f_pos; char * tmp = buf; while (count-- > 0 && i < 65536) { put_fs_byte(inb(i),tmp); i++; tmp++; } file->f_pos = i; return tmp-buf; }
static int get_window_size(struct tty_struct * tty, struct winsize * ws) { int i; char * tmp; if (!ws) return -EINVAL; verify_area(ws, sizeof (*ws)); tmp = (char *) ws; for (i = 0; i < sizeof (struct winsize) ; i++,tmp++) put_fs_byte(((char *) &tty->winsize)[i], tmp); return 0; }
static inline void save_old(char * from,char * to) { int i; // 判断用户虚拟空间是否被影射到物理内存 // 如果没有, 就进行影射操作 verify_area(to, sizeof(struct sigaction)); for (i=0 ; i< sizeof(struct sigaction) ; i++) { put_fs_byte(*from,to); from++; to++; } }
// 复制sigaction 数据到fs 数据段to 处。。 static inline void save_old (char *from, char *to) { int i; verify_area (to, sizeof (struct sigaction)); // 验证to 处的内存是否足够。 for (i = 0; i < sizeof (struct sigaction); i++) { put_fs_byte (*from, to); // 复制到fs 段。一般是用户数据段。 from++; // put_fs_byte()在include/asm/segment.h 中。 to++; } }
int sys_uname(struct utsname * name) { static struct utsname thisname = { "linux .0","nodename","release ","version ","machine " }; int i; if (!name) return -ERROR; verify_area(name,sizeof *name); for(i=0;i<sizeof *name;i++) put_fs_byte(((char *) &thisname)[i],i+(char *) name); return 0; }
static int msdos_readdir(struct inode *inode,struct file *filp, struct dirent *dirent,int count) { int ino,i,i2,last; char c,*walk; struct buffer_head *bh; struct msdos_dir_entry *de; if (!inode || !S_ISDIR(inode->i_mode)) return -EBADF; if (inode->i_ino == MSDOS_ROOT_INO) { /* Fake . and .. for the root directory. */ if (filp->f_pos == 2) filp->f_pos = 0; else if (filp->f_pos < 2) { walk = filp->f_pos++ ? ".." : "."; for (i = 0; *walk; walk++) put_fs_byte(*walk,dirent->d_name+i++); put_fs_long(MSDOS_ROOT_INO,&dirent->d_ino); put_fs_byte(0,dirent->d_name+i); put_fs_word(i,&dirent->d_reclen); return i; } } if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1)) return -ENOENT; bh = NULL; while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) { if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) { for (i = last = 0; i < 8; i++) { if (!(c = de->name[i])) break; if (c >= 'A' && c <= 'Z') c += 32; if (c != ' ') last = i+1; put_fs_byte(c,i+dirent->d_name); } i = last; put_fs_byte('.',i+dirent->d_name); i++; for (i2 = 0; i2 < 3; i2++) { if (!(c = de->ext[i2])) break; if (c >= 'A' && c <= 'Z') c += 32; if (c != ' ') last = i+1; put_fs_byte(c,i+dirent->d_name); i++; } if ((i = last) != 0) { if (!strcmp(de->name,MSDOS_DOT)) ino = inode->i_ino; else if (!strcmp(de->name,MSDOS_DOTDOT)) ino = msdos_parent_ino(inode,0); put_fs_long(ino,&dirent->d_ino); put_fs_byte(0,i+dirent->d_name); put_fs_word(i,&dirent->d_reclen); brelse(bh); return i; } } } if (bh) brelse(bh); return 0; }