home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / kernel-s / umsdos / umsdos-0.001 / umsdos-0.3.diff
Text File  |  1994-05-21  |  161KB  |  5,275 lines

  1. diff -rc2P linux.1.1.12/config.in linux/config.in
  2. *** linux.1.1.12/config.in    Fri May 20 23:49:24 1994
  3. --- linux/config.in    Mon May 16 22:12:53 1994
  4. ***************
  5. *** 113,116 ****
  6. --- 113,117 ----
  7.   bool 'xiafs filesystem support' CONFIG_XIA_FS n
  8.   bool 'msdos fs support' CONFIG_MSDOS_FS y
  9. + bool 'umsdos: Unix like fs on top of std MSDOS FAT fs' CONFIG_UMSDOS_FS y
  10.   bool '/proc filesystem support' CONFIG_PROC_FS y
  11.   bool 'NFS filesystem support' CONFIG_NFS_FS y
  12. diff -rc2P linux.1.1.12/fs/Makefile linux/fs/Makefile
  13. *** linux.1.1.12/fs/Makefile    Tue Dec 21 05:30:23 1993
  14. --- linux/fs/Makefile    Wed May 11 23:38:29 1994
  15. ***************
  16. *** 34,37 ****
  17. --- 34,40 ----
  18.   FS_SUBDIRS := $(FS_SUBDIRS) xiafs
  19.   endif
  20. + ifdef CONFIG_UMSDOS_FS
  21. + FS_SUBDIRS := $(FS_SUBDIRS) umsdos
  22. + endif
  23.   ifdef CONFIG_SYSV_FS
  24.   FS_SUBDIRS := $(FS_SUBDIRS) sysv
  25. diff -rc2P linux.1.1.12/fs/filesystems.c linux/fs/filesystems.c
  26. *** linux.1.1.12/fs/filesystems.c    Fri May 20 23:49:07 1994
  27. --- linux/fs/filesystems.c    Wed May 11 23:38:29 1994
  28. ***************
  29. *** 27,30 ****
  30. --- 27,33 ----
  31.   {
  32.       static int callable = 1;
  33. + #ifdef CONFIG_UMSDOS_FS
  34. + #include <linux/umsdos_fs.h>
  35. + #endif
  36.   
  37.       if (!callable)
  38. ***************
  39. *** 52,55 ****
  40. --- 55,62 ----
  41.       register_filesystem(&(struct file_system_type)
  42.           {xiafs_read_super, "xiafs", 1, NULL});
  43. + #endif
  44. + #ifdef CONFIG_UMSDOS_FS
  45. +     register_filesystem(&(struct file_system_type)
  46. +     {UMSDOS_read_super,    "umsdos",    1, NULL});
  47.   #endif
  48.   
  49. diff -rc2P linux.1.1.12/fs/msdos/Makefile linux/fs/msdos/Makefile
  50. *** linux.1.1.12/fs/msdos/Makefile    Wed Dec  1 07:44:15 1993
  51. --- linux/fs/msdos/Makefile    Wed May 11 23:48:19 1994
  52. ***************
  53. *** 15,19 ****
  54.       $(AS) -o $*.o $<
  55.   
  56. ! OBJS=    namei.o inode.o file.o dir.o misc.o fat.o
  57.   
  58.   msdos.o: $(OBJS)
  59. --- 15,19 ----
  60.       $(AS) -o $*.o $<
  61.   
  62. ! OBJS=    namei.o inode.o file.o dir.o misc.o fat.o mmap.o
  63.   
  64.   msdos.o: $(OBJS)
  65. diff -rc2P linux.1.1.12/fs/msdos/dir.c linux/fs/msdos/dir.c
  66. *** linux.1.1.12/fs/msdos/dir.c    Wed Dec  1 07:44:15 1993
  67. --- linux/fs/msdos/dir.c    Wed May 11 23:48:19 1994
  68. ***************
  69. *** 13,16 ****
  70. --- 13,17 ----
  71.   #include <linux/errno.h>
  72.   #include <linux/stat.h>
  73. + #include <linux/string.h>
  74.   
  75.   
  76. ***************
  77. *** 20,24 ****
  78.   }
  79.   
  80. ! static int msdos_readdir(struct inode *inode,struct file *filp,
  81.       struct dirent *dirent,int count);
  82.   
  83. --- 21,25 ----
  84.   }
  85.   
  86. ! int msdos_readdir(struct inode *inode,struct file *filp,
  87.       struct dirent *dirent,int count);
  88.   
  89. ***************
  90. *** 55,60 ****
  91.   };
  92.   
  93. ! static int msdos_readdir(struct inode *inode,struct file *filp,
  94. !     struct dirent *dirent,int count)
  95.   {
  96.       int ino,i,i2,last;
  97. --- 56,65 ----
  98.   };
  99.   
  100. ! static int msdos_readdir_x(
  101. !     struct inode *inode,
  102. !     struct file *filp,
  103. !     struct dirent *dirent,
  104. !     int count,
  105. !     int dirent_in_fs)
  106.   {
  107.       int ino,i,i2,last;
  108. ***************
  109. *** 69,78 ****
  110.           else if (filp->f_pos < 2) {
  111.                   walk = filp->f_pos++ ? ".." : ".";
  112. !                 for (i = 0; *walk; walk++)
  113. !                     put_fs_byte(*walk,dirent->d_name+i++);
  114. !                 put_fs_long(MSDOS_ROOT_INO,&dirent->d_ino);
  115. !                 put_fs_byte(0,dirent->d_name+i);
  116. !                 put_fs_word(i,&dirent->d_reclen);
  117. !                 return i;
  118.               }
  119.       }
  120. --- 74,90 ----
  121.           else if (filp->f_pos < 2) {
  122.                   walk = filp->f_pos++ ? ".." : ".";
  123. !                 if (dirent_in_fs){
  124. !                     for (i = 0; *walk; walk++)
  125. !                         put_fs_byte(*walk,dirent->d_name+i++);
  126. !                     put_fs_long(MSDOS_ROOT_INO,&dirent->d_ino);
  127. !                     put_fs_byte(0,dirent->d_name+i);
  128. !                     put_fs_word(i,&dirent->d_reclen);
  129. !                     return i;
  130. !                 }else{
  131. !                     dirent->d_ino = MSDOS_ROOT_INO;
  132. !                     strcpy (dirent->d_name,walk);
  133. !                     dirent->d_reclen = filp->f_pos;
  134. !                     return dirent->d_reclen;
  135. !                 }
  136.               }
  137.       }
  138. ***************
  139. *** 81,92 ****
  140.       while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) {
  141.           if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) {
  142.               for (i = last = 0; i < 8; i++) {
  143.                   if (!(c = de->name[i])) break;
  144.                   if (c >= 'A' && c <= 'Z') c += 32;
  145. !                 if (c != ' ') last = i+1;
  146. !                 put_fs_byte(c,i+dirent->d_name);
  147.               }
  148.               i = last;
  149. !             put_fs_byte('.',i+dirent->d_name);
  150.               i++;
  151.               for (i2 = 0; i2 < 3; i2++) {
  152. --- 93,108 ----
  153.       while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) {
  154.           if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) {
  155. +             char bufname[13];
  156. +             char *ptname = bufname;
  157.               for (i = last = 0; i < 8; i++) {
  158.                   if (!(c = de->name[i])) break;
  159.                   if (c >= 'A' && c <= 'Z') c += 32;
  160. !                 if (c != ' '){
  161. !                     last = i+1;
  162. !                     *ptname++ = c;
  163. !                 }
  164.               }
  165.               i = last;
  166. !             *ptname++ = '.';
  167.               i++;
  168.               for (i2 = 0; i2 < 3; i2++) {
  169. ***************
  170. *** 93,98 ****
  171.                   if (!(c = de->ext[i2])) break;
  172.                   if (c >= 'A' && c <= 'Z') c += 32;
  173. !                 if (c != ' ') last = i+1;
  174. !                 put_fs_byte(c,i+dirent->d_name);
  175.                   i++;
  176.               }
  177. --- 109,116 ----
  178.                   if (!(c = de->ext[i2])) break;
  179.                   if (c >= 'A' && c <= 'Z') c += 32;
  180. !                 if (c != ' '){
  181. !                     last = i+1;
  182. !                     *ptname++ = c;
  183. !                 }
  184.                   i++;
  185.               }
  186. ***************
  187. *** 102,108 ****
  188.                   else if (!strcmp(de->name,MSDOS_DOTDOT))
  189.                           ino = msdos_parent_ino(inode,0);
  190. !                 put_fs_long(ino,&dirent->d_ino);
  191. !                 put_fs_byte(0,i+dirent->d_name);
  192. !                 put_fs_word(i,&dirent->d_reclen);
  193.                   brelse(bh);
  194.                   return i;
  195. --- 120,133 ----
  196.                   else if (!strcmp(de->name,MSDOS_DOTDOT))
  197.                           ino = msdos_parent_ino(inode,0);
  198. !                 bufname[i] = '\0';
  199. !                 if (dirent_in_fs){
  200. !                     put_fs_long(ino,&dirent->d_ino);
  201. !                     memcpy_tofs(dirent->d_name,bufname,i+1);
  202. !                     put_fs_word(i,&dirent->d_reclen);
  203. !                 }else{
  204. !                     dirent->d_ino = ino;
  205. !                     memcpy (dirent->d_name,bufname,i+1);
  206. !                     dirent->d_reclen = i;
  207. !                 }
  208.                   brelse(bh);
  209.                   return i;
  210. ***************
  211. *** 112,114 ****
  212. --- 137,149 ----
  213.       if (bh) brelse(bh);
  214.       return 0;
  215. + }
  216. + int msdos_readdir(struct inode *inode,struct file *filp,
  217. +     struct dirent *dirent,int count)
  218. + {
  219. +     return msdos_readdir_x(inode,filp,dirent,count,1);
  220. + }
  221. + int msdos_readdir_kmem(struct inode *inode,struct file *filp,
  222. +     struct dirent *dirent,int count)
  223. + {
  224. +     return msdos_readdir_x(inode,filp,dirent,count,0);
  225.   }
  226. diff -rc2P linux.1.1.12/fs/msdos/file.c linux/fs/msdos/file.c
  227. *** linux.1.1.12/fs/msdos/file.c    Fri May 20 23:48:37 1994
  228. --- linux/fs/msdos/file.c    Wed May 11 23:48:20 1994
  229. ***************
  230. *** 16,19 ****
  231. --- 16,20 ----
  232.   #include <linux/fcntl.h>
  233.   #include <linux/stat.h>
  234. + #include <linux/string.h>
  235.   
  236.   #define MIN(a,b) (((a) < (b)) ? (a) : (b))
  237. ***************
  238. *** 20,29 ****
  239.   #define MAX(a,b) (((a) > (b)) ? (a) : (b))
  240.   
  241. - static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
  242. -     int count);
  243. - static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
  244. -     int count);
  245.   static struct file_operations msdos_file_operations = {
  246.       NULL,            /* lseek - default */
  247. --- 21,24 ----
  248. ***************
  249. *** 33,37 ****
  250.       NULL,            /* select - default */
  251.       NULL,            /* ioctl - default */
  252. !     NULL,            /* mmap */
  253.       NULL,            /* no special open is needed */
  254.       NULL,            /* release */
  255. --- 28,32 ----
  256.       NULL,            /* select - default */
  257.       NULL,            /* ioctl - default */
  258. !     msdos_mmap,        /* mmap */
  259.       NULL,            /* no special open is needed */
  260.       NULL,            /* release */
  261. ***************
  262. *** 54,58 ****
  263.       msdos_bmap,        /* bmap */
  264.       msdos_truncate,        /* truncate */
  265. !     NULL            /* permission */
  266.   };
  267.   
  268. --- 49,54 ----
  269.       msdos_bmap,        /* bmap */
  270.       msdos_truncate,        /* truncate */
  271. !     NULL,            /* permission */
  272. !     msdos_smap        /* smap */
  273.   };
  274.   
  275. ***************
  276. *** 74,83 ****
  277.       NULL,            /* bmap */
  278.       msdos_truncate,        /* truncate */
  279. !     NULL            /* permission */
  280.   };
  281.   
  282.   
  283. ! static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
  284. !     int count)
  285.   {
  286.       char *start;
  287. --- 70,87 ----
  288.       NULL,            /* bmap */
  289.       msdos_truncate,        /* truncate */
  290. !     NULL,            /* permission */
  291. !     msdos_smap        /* smap */
  292.   };
  293.   
  294.   
  295. ! /*
  296. !     Read a file into user space or kernel space
  297. ! */
  298. ! static int msdos_file_readx(
  299. !     struct inode *inode,
  300. !     struct file *filp,
  301. !     char *buf,
  302. !     int count,
  303. !     int from_fs)
  304.   {
  305.       char *start;
  306. ***************
  307. *** 92,96 ****
  308.           return -EINVAL;
  309.       }
  310. !     if (!S_ISREG(inode->i_mode)) {
  311.           printk("msdos_file_read: mode = %07o\n",inode->i_mode);
  312.           return -EINVAL;
  313. --- 96,101 ----
  314.           return -EINVAL;
  315.       }
  316. !     /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
  317. !     if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
  318.           printk("msdos_file_read: mode = %07o\n",inode->i_mode);
  319.           return -EINVAL;
  320. ***************
  321. *** 104,108 ****
  322.           if (!(bh = msdos_sread(inode->i_dev,sector,&data))) break;
  323.           filp->f_pos += (size = MIN(SECTOR_SIZE-offset,left));
  324. !         if (MSDOS_I(inode)->i_binary) {
  325.               memcpy_tofs(buf,data+offset,size);
  326.               buf += size;
  327. --- 109,116 ----
  328.           if (!(bh = msdos_sread(inode->i_dev,sector,&data))) break;
  329.           filp->f_pos += (size = MIN(SECTOR_SIZE-offset,left));
  330. !         if (!from_fs){
  331. !             memcpy (buf,data+offset,size);
  332. !             buf += size;
  333. !         }else if (MSDOS_I(inode)->i_binary) {
  334.               memcpy_tofs(buf,data+offset,size);
  335.               buf += size;
  336. ***************
  337. *** 132,139 ****
  338.   }
  339.   
  340. ! static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
  341.       int count)
  342.   {
  343.       int sector,offset,size,left,written;
  344.       int error,carry;
  345. --- 140,176 ----
  346.   }
  347.   
  348. ! /*
  349. !     Read a file into user space memory
  350. ! */
  351. ! int msdos_file_read(
  352. !     struct inode *inode,
  353. !     struct file *filp,
  354. !     char *buf,
  355.       int count)
  356.   {
  357. +     return msdos_file_readx(inode,filp,buf,count,1);
  358. + }
  359. + /*
  360. +     Read a file into kernel space memory
  361. + */
  362. + int msdos_file_read_kmem(
  363. +     struct inode *inode,
  364. +     struct file *filp,
  365. +     char *buf,
  366. +     int count)
  367. + {
  368. +     return msdos_file_readx(inode,filp,buf,count,0);
  369. + }
  370. + /*
  371. +     Write to a file either from kernel memory or user space
  372. + */
  373. + static int msdos_file_writex(
  374. +     struct inode *inode,
  375. +     struct file *filp,
  376. +     char *buf,
  377. +     int count,
  378. +     int from_fs)
  379. + {
  380.       int sector,offset,size,left,written;
  381.       int error,carry;
  382. ***************
  383. *** 146,150 ****
  384.           return -EINVAL;
  385.       }
  386. !     if (!S_ISREG(inode->i_mode)) {
  387.           printk("msdos_file_write: mode = %07o\n",inode->i_mode);
  388.           return -EINVAL;
  389. --- 183,188 ----
  390.           return -EINVAL;
  391.       }
  392. !     /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
  393. !     if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
  394.           printk("msdos_file_write: mode = %07o\n",inode->i_mode);
  395.           return -EINVAL;
  396. ***************
  397. *** 170,174 ****
  398.               break;
  399.           }
  400. !         if (MSDOS_I(inode)->i_binary) {
  401.               memcpy_fromfs(data+(filp->f_pos & (SECTOR_SIZE-1)),
  402.                   buf,written = size);
  403. --- 208,217 ----
  404.               break;
  405.           }
  406. !         if (!from_fs){
  407. !             /* Assume binary data when from kernel memory */
  408. !             memcpy(data+(filp->f_pos & (SECTOR_SIZE-1)),
  409. !                 buf,written = size);
  410. !             buf += size;
  411. !         }else if (MSDOS_I(inode)->i_binary) {
  412.               memcpy_fromfs(data+(filp->f_pos & (SECTOR_SIZE-1)),
  413.                   buf,written = size);
  414. ***************
  415. *** 212,216 ****
  416.   }
  417.   
  418.   void msdos_truncate(struct inode *inode)
  419.   {
  420. --- 255,274 ----
  421.   }
  422.   
  423. ! /*
  424. !     Write to a file from user space
  425. ! */
  426. ! int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
  427. !     int count)
  428. ! {
  429. !     return msdos_file_writex(inode,filp,buf,count,1);
  430. ! }
  431. ! /*
  432. !     Write to a file from kernel space
  433. ! */
  434. ! int msdos_file_write_kmem(struct inode *inode,struct file *filp,char *buf,
  435. !     int count)
  436. ! {
  437. !     return msdos_file_writex(inode,filp,buf,count,0);
  438. ! }
  439.   void msdos_truncate(struct inode *inode)
  440.   {
  441. diff -rc2P linux.1.1.12/fs/msdos/mmap.c linux/fs/msdos/mmap.c
  442. *** linux.1.1.12/fs/msdos/mmap.c
  443. --- linux/fs/msdos/mmap.c    Wed May 11 23:48:23 1994
  444. ***************
  445. *** 0 ****
  446. --- 1,156 ----
  447. + /*
  448. +  *    fs/msdos/mmap.c
  449. +  *
  450. +  *    Written by Jacques Gelinas (jacques@solucorp.qc.ca)
  451. +  *    Inspired by fs/nfs/mmap.c (Jaon Tombs 15 Aug 1993)
  452. +  *
  453. +  *    msdos mmap handling
  454. +  */
  455. + #include <linux/stat.h>
  456. + #include <linux/sched.h>
  457. + #include <linux/kernel.h>
  458. + #include <linux/mm.h>
  459. + #include <linux/shm.h>
  460. + #include <linux/errno.h>
  461. + #include <linux/mman.h>
  462. + #include <linux/string.h>
  463. + #include <linux/malloc.h>
  464. + #include <asm/segment.h>
  465. + #include <asm/system.h>
  466. + #include <linux/msdos_fs.h>
  467. + extern int share_page(struct vm_area_struct * area, struct task_struct * tsk,
  468. +     struct inode * inode, unsigned long address, unsigned long error_code,
  469. +     unsigned long newpage);
  470. + extern unsigned long put_page(struct task_struct * tsk,unsigned long page,
  471. +     unsigned long address,int prot);
  472. + extern void file_mmap_free(struct vm_area_struct * area);
  473. + extern int file_mmap_share(struct vm_area_struct * from, struct vm_area_struct * to,
  474. +                 unsigned long address);
  475. + /*
  476. +     Perform the mapping of an adresse in memory
  477. + */
  478. + static void msdos_file_mmap_nopage(
  479. +     int error_code,
  480. +     struct vm_area_struct * area,
  481. +     unsigned long address)
  482. + {
  483. +     struct inode * inode = area->vm_inode;
  484. +     unsigned int clear;
  485. +     unsigned long page;
  486. +     int pos;
  487. +     long gap;    /* distance from eof to pos */
  488. +     address &= PAGE_MASK;
  489. +     pos = address - area->vm_start + area->vm_offset;
  490. +     page = __get_free_page(GFP_KERNEL);
  491. +     if (share_page(area, area->vm_task, inode, address, error_code, page)) {
  492. +         ++area->vm_task->mm->min_flt;
  493. +         return;
  494. +     }
  495. +     ++area->vm_task->mm->maj_flt;
  496. +     if (!page) {
  497. +         oom(current);
  498. +         put_page(area->vm_task, BAD_PAGE, address, PAGE_PRIVATE);
  499. +         return;
  500. +     }
  501. +     clear = 0;
  502. +     gap = inode->i_size - pos;
  503. +     if (gap <= 0){
  504. +         /* mmaping beyong end of file */
  505. +         clear = PAGE_SIZE;
  506. +     }else{
  507. +         int cur_read;
  508. +         int need_read;
  509. +         struct file filp;
  510. +         if (gap < PAGE_SIZE){
  511. +             clear = PAGE_SIZE - gap;
  512. +         }
  513. +         filp.f_pos = pos;
  514. +         need_read = PAGE_SIZE - clear;
  515. +         cur_read = msdos_file_read_kmem (inode,&filp,(char*)page,need_read);
  516. +         if (cur_read != need_read){
  517. +             printk ("MSDOS: Error while reading an mmap file %d <> %d\n"
  518. +                 ,cur_read,need_read);
  519. +             free_page (page);
  520. +             oom(current);
  521. +             put_page(area->vm_task, BAD_PAGE, address, PAGE_PRIVATE);
  522. +             return;
  523. +         }
  524. +     }
  525. +     if (!(error_code & PAGE_RW)) {
  526. +         if (share_page(area, area->vm_task, inode, address, error_code, page))
  527. +             return;
  528. +     }
  529. +     if (clear > 0){
  530. +         #if 1
  531. +             memset ((char*)page+PAGE_SIZE-clear,0,clear);
  532. +         #else
  533. +             unsigned long tmp = page + PAGE_SIZE;
  534. +             while (clear--) {
  535. +                 *(char *)--tmp = 0;
  536. +             }
  537. +         #endif
  538. +     }
  539. +     if (put_page(area->vm_task,page,address,area->vm_page_prot))
  540. +         return;
  541. +     free_page(page);
  542. +     oom(current);
  543. + }
  544. + struct vm_operations_struct msdos_file_mmap = {
  545. +     NULL,            /* open */
  546. +     file_mmap_free,        /* close */
  547. +     msdos_file_mmap_nopage,/* nopage */
  548. +     NULL,            /* wppage */
  549. +     file_mmap_share,    /* share */
  550. +     NULL,            /* unmap */
  551. + };
  552. + /*
  553. +     Initialise a mmap operation on a file.    
  554. +     Return 0 if ok, or a negative error code if not.
  555. + */
  556. + int msdos_mmap(
  557. +     struct inode * inode,
  558. +     struct file * file,
  559. +     unsigned long addr,
  560. +     size_t len,
  561. +     int prot,
  562. +     unsigned long off)
  563. + {
  564. +     struct vm_area_struct * mpnt;
  565. +     if (prot & PAGE_RW)    /* only PAGE_COW or read-only supported now */
  566. +         return -EINVAL;
  567. +     if (off & (inode->i_sb->s_blocksize - 1))
  568. +         return -EINVAL;
  569. +     if (!inode->i_sb || !S_ISREG(inode->i_mode))
  570. +         return -EACCES;
  571. +     if (!IS_RDONLY(inode)) {
  572. +         inode->i_atime = CURRENT_TIME;
  573. +         inode->i_dirt = 1;
  574. +     }
  575. +     mpnt = (struct vm_area_struct * ) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
  576. +     if (!mpnt)
  577. +         return -ENOMEM;
  578. +     unmap_page_range(addr, len);
  579. +     mpnt->vm_task = current;
  580. +     mpnt->vm_start = addr;
  581. +     mpnt->vm_end = addr + len;
  582. +     mpnt->vm_page_prot = prot;
  583. +     mpnt->vm_share = NULL;
  584. +     mpnt->vm_inode = inode;
  585. +     inode->i_count++;
  586. +     mpnt->vm_offset = off;
  587. +     mpnt->vm_ops = &msdos_file_mmap;
  588. +     insert_vm_struct (current,mpnt);
  589. +     merge_segments (current->mm->mmap,NULL,NULL);
  590. +     return 0;
  591. + }
  592. diff -rc2P linux.1.1.12/fs/msdos/namei.c linux/fs/msdos/namei.c
  593. *** linux.1.1.12/fs/msdos/namei.c    Fri May 20 23:48:37 1994
  594. --- linux/fs/msdos/namei.c    Wed May 11 23:48:24 1994
  595. ***************
  596. *** 361,365 ****
  597.   
  598.   
  599. ! int msdos_unlink(struct inode *dir,const char *name,int len)
  600.   {
  601.       int res,ino;
  602. --- 361,369 ----
  603.   
  604.   
  605. ! static int msdos_unlinkx(
  606. !     struct inode *dir,
  607. !     const char *name,
  608. !     int len,
  609. !     int nospc)    /* Flag special file ? */
  610.   {
  611.       int res,ino;
  612. ***************
  613. *** 376,380 ****
  614.           goto unlink_done;
  615.       }
  616. !     if (!S_ISREG(inode->i_mode)) {
  617.           res = -EPERM;
  618.           goto unlink_done;
  619. --- 380,384 ----
  620.           goto unlink_done;
  621.       }
  622. !     if (!S_ISREG(inode->i_mode) && nospc){
  623.           res = -EPERM;
  624.           goto unlink_done;
  625. ***************
  626. *** 393,396 ****
  627. --- 397,411 ----
  628.   }
  629.   
  630. + int msdos_unlink(struct inode *dir,const char *name,int len)
  631. + {
  632. +     return msdos_unlinkx (dir,name,len,1);
  633. + }
  634. + /*
  635. +     Special entry for umsdos
  636. + */
  637. + int msdos_unlink_umsdos(struct inode *dir,const char *name,int len)
  638. + {
  639. +     return msdos_unlinkx (dir,name,len,0);
  640. + }
  641.   
  642.   static int rename_same_dir(struct inode *old_dir,char *old_name,
  643. diff -rc2P linux.1.1.12/fs/umsdos/Makefile linux/fs/umsdos/Makefile
  644. *** linux.1.1.12/fs/umsdos/Makefile
  645. --- linux/fs/umsdos/Makefile    Wed May 11 23:47:27 1994
  646. ***************
  647. *** 0 ****
  648. --- 1,40 ----
  649. + #
  650. + # Makefile for the umsdos unix-like filesystem routines.
  651. + #
  652. + # Note! Dependencies are done automagically by 'make dep', which also
  653. + # removes any old dependencies. DON'T put your own dependencies here
  654. + # unless it's something special (ie not a .c file).
  655. + #
  656. + # Note 2! The CFLAGS definitions are now in the main makefile...
  657. + .c.s:
  658. +     $(CC) $(CFLAGS) -S $<
  659. + .c.o:
  660. +     $(CC) $(CFLAGS) -c $<
  661. + .s.o:
  662. +     $(AS) -o $*.o $<
  663. + OBJS=    dir.o emd.o file.o inode.o ioctl.o mangle.o namei.o\
  664. +     rdir.o symlink.o #check.o
  665. + umsdos.o: $(OBJS)
  666. +     $(LD) -r -o umsdos.o $(OBJS)
  667. + clean:
  668. +     rm -f core *.o *.a *.s
  669. + dep:
  670. +     $(CPP) -M *.c > .depend
  671. + p:
  672. +     proto *.c >/usr/include/linux/umsdos_fs.p
  673. + doc:
  674. +     nadoc -i -p umsdos.doc - /tmp/umsdos.mpg
  675. + #
  676. + # include a dependency file if one exists
  677. + #
  678. + ifeq (.depend,$(wildcard .depend))
  679. + include .depend
  680. + endif
  681. diff -rc2P linux.1.1.12/fs/umsdos/check.c linux/fs/umsdos/check.c
  682. *** linux.1.1.12/fs/umsdos/check.c
  683. --- linux/fs/umsdos/check.c    Wed May 11 23:47:27 1994
  684. ***************
  685. *** 0 ****
  686. --- 1,55 ----
  687. + #include <asm/system.h>
  688. + #include <linux/signal.h>
  689. + #include <linux/sched.h>
  690. + #include <linux/head.h>
  691. + #include <linux/kernel.h>
  692. + #include <linux/errno.h>
  693. + #include <linux/string.h>
  694. + #include <linux/types.h>
  695. + #include <linux/ptrace.h>
  696. + #include <linux/mman.h>
  697. + extern unsigned long high_memory;
  698. + static int check_one_table(unsigned long * page_dir)
  699. + {
  700. +     unsigned long pg_table = *page_dir;
  701. +     if (!pg_table)
  702. +         return 0;
  703. +     if (pg_table >= high_memory || !(pg_table & PAGE_PRESENT)) {
  704. +         return 1;
  705. +     }
  706. +     return 0;
  707. + }
  708. + /*
  709. +  * This function frees up all page tables of a process when it exits.
  710. +  */
  711. + void check_page_tables(void)
  712. + {
  713. +     unsigned long pg_dir;
  714. +     static int err = 0;
  715. +     int stack_level = (long)(&pg_dir)-current->kernel_stack_page;
  716. +     if (stack_level < 1500) printk ("** %d ** ",stack_level);
  717. +     pg_dir = current->tss.cr3;
  718. +     if (mem_map[MAP_NR(pg_dir)] > 1) {
  719. +         return;
  720. +     }
  721. +     if (err == 0){
  722. +         unsigned long *page_dir = (unsigned long *) pg_dir;
  723. +         unsigned long *base = page_dir;
  724. +         int i;
  725. +         for (i = 0 ; i < PTRS_PER_PAGE ; i++,page_dir++){
  726. +             int notok = check_one_table(page_dir);
  727. +             if (notok){
  728. +                 err++;
  729. +                 printk ("|%d| ",page_dir-base);
  730. +             }
  731. +         }
  732. +         if (err) printk ("Erreur MM %d\n",err);
  733. +     }
  734. + }
  735. diff -rc2P linux.1.1.12/fs/umsdos/dir.c linux/fs/umsdos/dir.c
  736. *** linux.1.1.12/fs/umsdos/dir.c
  737. --- linux/fs/umsdos/dir.c    Thu May 12 00:29:23 1994
  738. ***************
  739. *** 0 ****
  740. --- 1,703 ----
  741. + /*
  742. +  *  linux/fs/umsdos/dir.c
  743. +  *
  744. +  *  Written 1993 by Jacques Gelinas
  745. +  *    Inspired from linux/fs/msdos/... : Werner Almesberger
  746. +  *
  747. +  *  Extended MS-DOS directory handling functions
  748. +  */
  749. + #include <asm/segment.h>
  750. + #include <linux/sched.h>
  751. + #include <linux/string.h>
  752. + #include <linux/fs.h>
  753. + #include <linux/msdos_fs.h>
  754. + #include <linux/errno.h>
  755. + #include <linux/stat.h>
  756. + #include <linux/limits.h>
  757. + #include <linux/umsdos_fs.h>
  758. + #include <linux/malloc.h>
  759. + #define PRINTK(x)
  760. + #define Printk(x) printk x
  761. + #define UMSDOS_SPECIAL_DIRFPOS    3
  762. + extern struct inode *pseudo_root;
  763. + /*
  764. +     So  grep *  doesn't complain in the presence of directories.
  765. + */
  766. + int UMSDOS_dir_read(struct inode *inode,struct file *filp,char *buf,
  767. +     int count)
  768. + {
  769. +     return -EISDIR;
  770. + }
  771. + /*
  772. +     Read count directory entries from directory filp
  773. +     Return a negative value from linux/errno.h.
  774. +     Return > 0 if success (the length of the file name).
  775. +     This function is used by the normal readdir VFS entry point and by
  776. +     some function who try to find out info on a file from a pure MSDOS
  777. +     inode. See umsdos_locate_ancestor() below.
  778. + */
  779. + static int umsdos_readdir_x(
  780. +     struct inode *dir,        /* Point to a description of the super block */
  781. +     struct file *filp,        /* Point to a directory which is read */
  782. +     struct dirent *dirent,    /* Will hold count directory entry */
  783. +     int dirent_in_fs,        /* dirent point in user's space ? */
  784. +     int count,
  785. +     struct umsdos_dirent *u_entry,    /* Optionnal umsdos entry */
  786. +     int follow_hlink,
  787. +     off_t *pt_f_pos)        /* will hold the offset of the entry in EMD */
  788. + {
  789. +     int ret = 0;
  790. +     
  791. +     umsdos_startlookup(dir);    
  792. +     if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS
  793. +         && dir == pseudo_root
  794. +         && dirent_in_fs){
  795. +         /*
  796. +             We don't need to simulate this pseudo directory
  797. +             when umsdos_readdir_x is called for internal operation
  798. +             of umsdos. This is why dirent_in_fs is tested
  799. +         */
  800. +         /* #Specification: pseudo root / directory /DOS
  801. +             When umsdos operates in pseudo root mode (C:\linux is the
  802. +             linux root), it simulate a directory /DOS which points to
  803. +             the real root of the file system.
  804. +         */
  805. +         put_fs_long(dir->i_sb->s_mounted->i_ino,&dirent->d_ino);
  806. +         memcpy_tofs (dirent->d_name,"DOS",3);
  807. +         put_fs_byte(0,dirent->d_name+3);
  808. +         put_fs_word (3,&dirent->d_reclen);
  809. +         if (u_entry != NULL) u_entry->flags = 0;
  810. +         ret = 3;
  811. +         filp->f_pos++;
  812. +     }else if (filp->f_pos < 2
  813. +         || (dir != dir->i_sb->s_mounted && filp->f_pos == 32)){
  814. +         /* #Specification: readdir / . and ..
  815. +             The msdos filesystem manage the . and .. entry properly
  816. +             so the EMD file won't hold any info about it.
  817. +             In readdir, we assume that for the root directory
  818. +             the read position will be 0 for ".", 1 for "..". For
  819. +             a non root directory, the read position will be 0 for "."
  820. +             and 32 for "..".
  821. +         */
  822. +         /*
  823. +             This is a trick used by the msdos file system (fs/msdos/dir.c)
  824. +             to manage . and .. for the root directory of a file system.
  825. +             Since there is no such entry in the root, fs/msdos/dir.c
  826. +             use the following:
  827. +             if f_pos == 0, return ".".
  828. +             if f_pos == 1, return "..".
  829. +             So let msdos handle it
  830. +             Since umsdos entries are much larger, we share the same f_pos.
  831. +             if f_pos is 0 or 1 or 32, we are clearly looking at . and
  832. +             ..
  833. +             As soon as we get f_pos == 2 or f_pos == 64, then back to
  834. +             0, but this time we are reading the EMD file.
  835. +             Well, not so true. The problem, is that UMSDOS_REC_SIZE is
  836. +             also 64, so as soon as we read the first record in the
  837. +             EMD, we are back at offset 64. So we set the offset
  838. +             to UMSDOS_SPECIAL_DIRFPOS(3) as soon as we have read the
  839. +             .. entry from msdos.
  840. +         */
  841. +         ret = msdos_readdir(dir,filp,dirent,count);
  842. +         if (filp->f_pos == 64) filp->f_pos = UMSDOS_SPECIAL_DIRFPOS;
  843. +         if (u_entry != NULL) u_entry->flags = 0;
  844. +     }else{
  845. +         struct inode *emd_dir = umsdos_emd_dir_lookup(dir,0);
  846. +         if (emd_dir != NULL){
  847. +             if (filp->f_pos <= UMSDOS_SPECIAL_DIRFPOS+1) filp->f_pos = 0;
  848. +             PRINTK (("f_pos %ld i_size %d\n",filp->f_pos,emd_dir->i_size));
  849. +             ret = 0;
  850. +             while (filp->f_pos < emd_dir->i_size){
  851. +                 struct umsdos_dirent entry;
  852. +                 off_t cur_f_pos = filp->f_pos;
  853. +                 if (umsdos_emd_dir_readentry (emd_dir,filp,&entry)!=0){
  854. +                     ret = -EIO;
  855. +                     break;
  856. +                 }else if (entry.name_len != 0){
  857. +                     /* #Specification: umsdos / readdir
  858. +                         umsdos_readdir() should fill a struct dirent with
  859. +                         an inode number. The cheap way to get it is to
  860. +                         do a lookup in the MSDOS directory for each
  861. +                         entry processed by the readdir() function.
  862. +                         This is not very efficient, but very simple. The
  863. +                         other way around is to maintain a copy of the inode
  864. +                         number in the EMD file. This is a problem because
  865. +                         this has to be maintained in sync using tricks.
  866. +                         Remember that MSDOS (the OS) does not update the
  867. +                         modification time (mtime) of a directory. There is
  868. +                         no easy way to tell that a directory was modified
  869. +                         during a DOS session and synchronise the EMD file.
  870. +                         Suggestion welcome.
  871. +                         So the easy way is used!
  872. +                     */
  873. +                     struct umsdos_info info;
  874. +                     struct inode *inode;
  875. +                     int lret;
  876. +                     umsdos_parse (entry.name,entry.name_len,&info);
  877. +                     info.f_pos = cur_f_pos;
  878. +                     *pt_f_pos = cur_f_pos;
  879. +                     umsdos_manglename (&info);
  880. +                     lret = umsdos_real_lookup (dir,info.fake.fname
  881. +                         ,info.fake.len,&inode);
  882. +                     PRINTK (("Cherche inode de %s lret %d flags %d\n"
  883. +                         ,info.fake.fname,lret,entry.flags));
  884. +                     if (lret == 0
  885. +                         && (entry.flags & UMSDOS_HLINK)
  886. +                         && follow_hlink){
  887. +                         struct inode *rinode;
  888. +                         lret = umsdos_hlink2inode (inode,&rinode);
  889. +                         inode = rinode;
  890. +                     }
  891. +                     if (lret == 0){
  892. +                         /* #Specification: pseudo root / reading real root
  893. +                             The pseudo root (/linux) is logically
  894. +                             erased from the real root. This mean that
  895. +                             ls /DOS, won't show "linux". This avoids
  896. +                             infinite recursion /DOS/linux/DOS/linux while
  897. +                             walking the file system.
  898. +                         */
  899. +                         if (inode != pseudo_root){
  900. +                             PRINTK (("Trouve ino %d ",inode->i_ino));
  901. +                             if (dirent_in_fs){
  902. +                                 put_fs_long(inode->i_ino,&dirent->d_ino);
  903. +                                 memcpy_tofs (dirent->d_name,entry.name
  904. +                                     ,entry.name_len);
  905. +                                 put_fs_byte(0,dirent->d_name+entry.name_len);
  906. +                                 put_fs_word (entry.name_len
  907. +                                     ,&dirent->d_reclen);
  908. +                                 /* In this case, the caller only needs */
  909. +                                 /* flags */
  910. +                                 if (u_entry != NULL){
  911. +                                     u_entry->flags = entry.flags;
  912. +                                 }
  913. +                             }else{
  914. +                                 dirent->d_ino = inode->i_ino;
  915. +                                 memcpy (dirent->d_name,entry.name
  916. +                                     ,entry.name_len);
  917. +                                 dirent->d_name[entry.name_len] = '\0';
  918. +                                 dirent->d_reclen = entry.name_len;
  919. +                                 if (u_entry != NULL) *u_entry = entry;
  920. +                             }
  921. +                             ret = entry.name_len;
  922. +                             iput (inode);
  923. +                             break;
  924. +                         }
  925. +                         iput (inode);
  926. +                     }else{
  927. +                         /* #Specification: umsdos / readdir / not in MSDOS
  928. +                             During a readdir operation, if the file is not
  929. +                             in the MSDOS directory anymore, the entry is
  930. +                             removed from the EMD file silently.
  931. +                         */
  932. +                         ret = umsdos_writeentry (dir,emd_dir,&info,1);
  933. +                         if (ret != 0){
  934. +                             break;
  935. +                         }
  936. +                     }
  937. +                 }
  938. +             }
  939. +             iput(emd_dir);
  940. +         }
  941. +     }
  942. +     umsdos_endlookup(dir);    
  943. +     PRINTK (("read dir %p pos %d ret %d\n",dir,filp->f_pos,ret));
  944. +     return ret;
  945. + }
  946. + /*
  947. +     Read count directory entries from directory filp
  948. +     Return a negative value from linux/errno.h.
  949. +     Return > 0 if success (the length of the file name).
  950. + */
  951. + static int UMSDOS_readdir(
  952. +     struct inode *dir,        /* Point to a description of the super block */
  953. +     struct file *filp,        /* Point to a directory which is read */
  954. +     struct dirent *dirent,    /* Will hold count directory entry */
  955. +     int count)
  956. + {
  957. +     int ret = -ENOENT;
  958. +     while (1){
  959. +         struct umsdos_dirent entry;
  960. +         off_t f_pos;
  961. +         ret = umsdos_readdir_x (dir,filp,dirent,1,count,&entry,1,&f_pos);
  962. +         if (ret <= 0 || !(entry.flags & UMSDOS_HIDDEN)) break;
  963. +     }
  964. +     return ret;
  965. + }
  966. + /*
  967. +     Complete the inode content with info from the EMD file
  968. + */
  969. + void umsdos_lookup_patch (
  970. +     struct inode *dir,
  971. +     struct inode *inode,
  972. +     struct umsdos_dirent *entry,
  973. +     off_t  emd_pos)
  974. + {
  975. +     /*
  976. +         This function modify the state of a dir inode. It decides
  977. +         if the dir is a umsdos dir or a dos dir. This is done
  978. +         deeper in umsdos_patch_inode() called at the end of this function.
  979. +         umsdos_patch_inode() may block because it is doing disk access.
  980. +         At the same time, another process may get here to initialise
  981. +         the same dir inode. There is 3 cases.
  982. +         1-The inode is already initialised. We do nothing.
  983. +         2-The inode is not initialised. We lock access and do it.
  984. +         3-Like 2 but another process has lock the inode, so we try
  985. +           to lock it and right after check if initialisation is still
  986. +           needed.
  987. +         Thanks to the mem option of the kernel command line, it was
  988. +         possible to consistently reproduce this problem by limiting
  989. +         my mem to 4 meg and running X.
  990. +     */
  991. +     /*
  992. +         Do this only if the inode is freshly read, because we will lose
  993. +         the current (updated) content.
  994. +     */
  995. +     /*
  996. +         A lookup of a mount point directory yield the inode into
  997. +         the other fs, so we don't care about initialising it. iget()
  998. +         does this automaticly.
  999. +     */
  1000. +     if (inode->i_sb == dir->i_sb && !umsdos_isinit(inode)){
  1001. +         if (S_ISDIR(inode->i_mode)) umsdos_lockcreate(inode);
  1002. +         if (!umsdos_isinit(inode)){
  1003. +             /* #Specification: umsdos / lookup / inode info
  1004. +                 After successfully reading an inode from the MSDOS
  1005. +                 filesystem, we use the EMD file to complete it.
  1006. +                 We update the following field.
  1007. +                 uid, gid, atime, ctime, mtime, mode.
  1008. +                 We rely on MSDOS for mtime. If the file
  1009. +                 was modified during an MSDOS session, at least
  1010. +                 mtime will be meaningful. We do this only for regular
  1011. +                 file.
  1012. +                 
  1013. +                 We don't rely on MSDOS for mtime for directory because
  1014. +                 the MSDOS directory date is creation time (strange
  1015. +                 MSDOS behavior) which fit nowhere in the three UNIX
  1016. +                 time stamp.
  1017. +             */
  1018. +             if (S_ISREG(entry->mode)) entry->mtime = inode->i_mtime;
  1019. +             inode->i_mode  = entry->mode;
  1020. +             inode->i_rdev  = entry->rdev;
  1021. +             inode->i_atime = entry->atime;
  1022. +             inode->i_ctime = entry->ctime;
  1023. +             inode->i_mtime = entry->mtime;
  1024. +             inode->i_uid   = entry->uid;
  1025. +             inode->i_gid   = entry->gid;
  1026. +             /* #Specification: umsdos / i_nlink
  1027. +                 The nlink field of an inode is maintain by the MSDOS file system
  1028. +                 for directory and by UMSDOS for other file. The logic is that
  1029. +                 MSDOS is already figuring out what to do for directories and
  1030. +                 does nothing for other files. For MSDOS, there are no hard link
  1031. +                 so all file carry nlink==1. UMSDOS use some info in the
  1032. +                 EMD file to plug the correct value.
  1033. +             */
  1034. +             if (!S_ISDIR(entry->mode)){
  1035. +                 if (entry->nlink > 0){
  1036. +                     inode->i_nlink = entry->nlink;
  1037. +                 }else{
  1038. +                     printk ("UMSDOS: lookup_patch entry->nlink < 1 ???\n");
  1039. +                 }
  1040. +             }
  1041. +             umsdos_patch_inode(inode,dir,emd_pos);
  1042. +         }
  1043. +         if (S_ISDIR(inode->i_mode)) umsdos_unlockcreate(inode);
  1044. + if (inode->u.umsdos_i.i_emd_owner==0) printk ("emd_owner still 0 ???\n");
  1045. +     }
  1046. + }
  1047. + /*
  1048. +     Locate entry of an inode in a directory.
  1049. +     Return 0 or a negative error code.
  1050. +     Normally, this function must succeed. It means a strange corruption
  1051. +     in the file system if not.
  1052. + */
  1053. + int umsdos_inode2entry (
  1054. +     struct inode *dir,
  1055. +     struct inode *inode,
  1056. +     struct umsdos_dirent *entry)    /* Will hold the entry */
  1057. + {
  1058. +     int ret = -ENOENT;
  1059. +     if (inode == pseudo_root){
  1060. +         /*
  1061. +             Quick way to find the name.
  1062. +             Also umsdos_readdir_x won't show /linux anyway
  1063. +         */
  1064. +         memcpy (entry->name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN+1);
  1065. +         entry->name_len = UMSDOS_PSDROOT_LEN;
  1066. +         ret = 0;
  1067. +     }else{
  1068. +         struct inode *emddir = umsdos_emd_dir_lookup(dir,0);
  1069. +         iput (emddir);
  1070. +         if (emddir == NULL){
  1071. +             /* This is a DOS directory */
  1072. +             struct file filp;
  1073. +             filp.f_pos = 0;
  1074. +             while (1){
  1075. +                 struct dirent dirent;
  1076. +                 if (msdos_readdir_kmem (dir,&filp,&dirent,1) <= 0){
  1077. +                     printk ("UMSDOS: can't locate inode %ld in DOS directory???\n"
  1078. +                         ,inode->i_ino);
  1079. +                 }else if (dirent.d_ino == inode->i_ino){
  1080. +                     ret = 0;
  1081. +                     memcpy (entry->name,dirent.d_name,dirent.d_reclen);
  1082. +                     entry->name[dirent.d_reclen] = '\0';
  1083. +                     entry->name_len = dirent.d_reclen;
  1084. +                     inode->u.umsdos_i.i_dir_owner = dir->i_ino;
  1085. +                     inode->u.umsdos_i.i_emd_owner = 0;
  1086. +                     umsdos_setup_dir_inode(inode);
  1087. +                     break;
  1088. +                 }
  1089. +             }
  1090. +         }else{
  1091. +             /* skip . and .. see umsdos_readdir_x() */
  1092. +             struct file filp;
  1093. +             filp.f_pos = UMSDOS_SPECIAL_DIRFPOS;
  1094. +             while (1){
  1095. +                 struct dirent dirent;
  1096. +                 off_t f_pos;
  1097. +                 if (umsdos_readdir_x(dir,&filp,&dirent
  1098. +                     ,0,1,entry,0,&f_pos) <= 0){
  1099. +                     printk ("UMSDOS: can't locate inode %ld in EMD file???\n"
  1100. +                         ,inode->i_ino);
  1101. +                     break;
  1102. +                 }else if (dirent.d_ino == inode->i_ino){
  1103. +                     ret = 0;
  1104. +                     umsdos_lookup_patch (dir,inode,entry,f_pos);
  1105. +                     break;
  1106. +                 }
  1107. +             }
  1108. +         }
  1109. +     }
  1110. +     return ret;
  1111. + }
  1112. + /*
  1113. +     Locate the parent of a directory and the info on that directory
  1114. +     Return 0 or a negative error code.
  1115. + */
  1116. + static int umsdos_locate_ancestor (
  1117. +     struct inode *dir,
  1118. +     struct inode **result,
  1119. +     struct umsdos_dirent *entry)
  1120. + {
  1121. +     int ret;
  1122. +     umsdos_patch_inode (dir,NULL,0);
  1123. +     ret = umsdos_real_lookup (dir,"..",2,result);
  1124. +     PRINTK (("result %d %x ",ret,*result));
  1125. +     if (ret == 0){
  1126. +         struct inode *adir = *result;
  1127. +         ret = umsdos_inode2entry (adir,dir,entry);
  1128. +     }
  1129. +     PRINTK (("\n"));
  1130. +     return ret;
  1131. + }
  1132. + /*
  1133. +     Build the path name of an inode (relative to the file system.
  1134. +     This function is need to set (pseudo) hard link.
  1135. +     It uses the same strategy as the standard getcwd().
  1136. + */
  1137. + int umsdos_locate_path (
  1138. +     struct inode *inode,
  1139. +     char *path)
  1140. + {
  1141. +     int ret = 0;
  1142. +     struct inode *dir = inode;
  1143. +     char *bpath = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
  1144. +     if (bpath == NULL){
  1145. +         ret = -ENOMEM;
  1146. +     }else{
  1147. +         struct umsdos_dirent entry;
  1148. +         char *ptbpath = bpath+PATH_MAX-1;
  1149. +         *ptbpath = '\0';
  1150. +         PRINTK (("locate_path mode %x ",inode->i_mode));
  1151. +         if (!S_ISDIR(inode->i_mode)){
  1152. +             ret = umsdos_get_dirowner (inode,&dir);
  1153. +             PRINTK (("locate_path ret %d ",ret));
  1154. +             if (ret == 0){
  1155. +                 ret = umsdos_inode2entry (dir,inode,&entry);
  1156. +                 if (ret == 0){
  1157. +                     ptbpath -= entry.name_len;
  1158. +                     memcpy (ptbpath,entry.name,entry.name_len);
  1159. +                     PRINTK (("ptbpath :%s: ",ptbpath));
  1160. +                 }
  1161. +             }
  1162. +         }else{
  1163. +             dir->i_count++;
  1164. +         }
  1165. +         if (ret == 0){
  1166. +             while (dir != dir->i_sb->s_mounted){
  1167. +                 struct inode *adir;
  1168. +                 ret = umsdos_locate_ancestor (dir,&adir,&entry);
  1169. +                 iput (dir);
  1170. +                 dir = NULL;
  1171. +                 PRINTK (("ancestor %d ",ret));
  1172. +                 if (ret == 0){
  1173. +                     *--ptbpath = '/';
  1174. +                     ptbpath -= entry.name_len;
  1175. +                     memcpy (ptbpath,entry.name,entry.name_len);
  1176. +                     dir = adir;
  1177. +                     PRINTK (("ptbpath :%s: ",ptbpath));
  1178. +                 }else{
  1179. +                     break;
  1180. +                 }
  1181. +             }
  1182. +         }
  1183. +         strcpy (path,ptbpath);
  1184. +         kfree (bpath);
  1185. +     }
  1186. +     PRINTK (("\n"));
  1187. +     iput (dir);
  1188. +     return ret;
  1189. + }
  1190. + /*
  1191. +     Return != 0 if an entry is the pseudo DOS entry in the pseudo root.
  1192. + */
  1193. + int umsdos_is_pseudodos (
  1194. +     struct inode *dir,
  1195. +     const char *name,
  1196. +     int len)
  1197. + {
  1198. +     /* #Specification: pseudo root / DOS hard coded
  1199. +         The pseudo sub-directory DOS in the pseudo root is hard coded.
  1200. +         The name is DOS. This is done this way to help standardised
  1201. +         the umsdos layout. The idea is that from now on /DOS is
  1202. +         a reserved path and nobody will think of using such a path
  1203. +         for a package.
  1204. +     */
  1205. +     return dir == pseudo_root
  1206. +         && len == 3
  1207. +         && name[0] == 'D' && name[1] == 'O' && name[2] == 'S';
  1208. + }
  1209. + /*
  1210. +     Check if a file exist in the current directory.
  1211. +     Return 0 if ok, negative error code if not (ex: -ENOENT).
  1212. + */
  1213. + static int umsdos_lookup_x (
  1214. +     struct inode *dir,
  1215. +     const char *name,
  1216. +     int len,
  1217. +     struct inode **result,    /* Will hold inode of the file, if successful */
  1218. +     int nopseudo)            /* Don't care about pseudo root mode */
  1219. + {
  1220. +     int ret = -ENOENT;
  1221. +     *result = NULL;
  1222. +     umsdos_startlookup(dir);    
  1223. +     if (len == 1 && name[0] == '.'){
  1224. +         *result = dir;
  1225. +         dir->i_count++;
  1226. +         ret = 0;
  1227. +     }else if (len == 2 && name[0] == '.' && name[1] == '.'){
  1228. +         if (pseudo_root != NULL && dir == pseudo_root->i_sb->s_mounted){
  1229. +             /* #Specification: pseudo root / .. in real root
  1230. +                 Whenever a lookup is those in the real root for
  1231. +                 the directory .., and pseudo root is active, the
  1232. +                 pseudo root is returned.
  1233. +             */
  1234. +             ret = 0;
  1235. +             *result = pseudo_root;
  1236. +             pseudo_root->i_count++;
  1237. +         }else{
  1238. +             /* #Specification: locating .. / strategy
  1239. +                 We use the msdos filesystem to locate the parent directory.
  1240. +                 But it is more complicated than that.
  1241. +                 
  1242. +                 We have to step back even further to
  1243. +                 get the parent of the parent, so we can get the EMD
  1244. +                 of the parent of the parent. Using the EMD file, we can
  1245. +                 locate all the info on the parent, such a permissions
  1246. +                 and owner.
  1247. +             */
  1248. +             ret = umsdos_real_lookup (dir,"..",2,result);
  1249. +             PRINTK (("ancestor ret %d dir %p *result %p ",ret,dir,*result));
  1250. +             if (ret == 0
  1251. +                 && *result != dir->i_sb->s_mounted
  1252. +                 && *result != pseudo_root){
  1253. +                 struct inode *aadir;
  1254. +                 struct umsdos_dirent entry;
  1255. +                 ret = umsdos_locate_ancestor (*result,&aadir,&entry);
  1256. +                 iput (aadir);
  1257. +             }
  1258. +         }
  1259. +     }else if (umsdos_is_pseudodos(dir,name,len)){
  1260. +         /* #Specification: pseudo root / lookup(DOS)
  1261. +             A lookup of DOS in the pseudo root will always succeed
  1262. +             and return the inode of the real root.
  1263. +         */
  1264. +         *result = dir->i_sb->s_mounted;
  1265. +         (*result)->i_count++;
  1266. +         ret = 0;
  1267. +     }else{
  1268. +         struct umsdos_info info;
  1269. +         ret = umsdos_parse (name,len,&info);
  1270. +         if (ret == 0) ret = umsdos_findentry (dir,&info,0);
  1271. +         PRINTK (("lookup %s pos %d ret %d len %d ",info.fake.fname,info.f_pos,ret
  1272. +             ,info.fake.len));
  1273. +         if (ret == 0){
  1274. +             /* #Specification: umsdos / lookup
  1275. +                 A lookup for a file is done in two step. First, we locate
  1276. +                 the file in the EMD file. If not present, we return
  1277. +                 an error code (-ENOENT). If it is there, we repeat the
  1278. +                 operation on the msdos file system. If this fails, it means
  1279. +                 that the file system is not in sync with the emd file.
  1280. +                 We silently remove this entry from the emd file,
  1281. +                 and return ENOENT.
  1282. +             */
  1283. +             struct inode *inode;
  1284. +             ret = umsdos_real_lookup (dir,info.fake.fname,info.fake.len,result);
  1285. +             inode = *result;
  1286. +             if (inode == NULL){
  1287. +                 printk ("UMSDOS: Erase entry %s, out of sync with MsDOS\n"
  1288. +                     ,info.fake.fname);
  1289. +                 umsdos_delentry (dir,&info,S_ISDIR(info.entry.mode));
  1290. +             }else{
  1291. +                 umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos);
  1292. +                 PRINTK (("lookup ino %d flags %d\n",inode->i_ino
  1293. +                     ,info.entry.flags));
  1294. +                 if (info.entry.flags & UMSDOS_HLINK){
  1295. +                     ret = umsdos_hlink2inode (inode,result);
  1296. +                 }
  1297. +                 if (*result == pseudo_root && !nopseudo){
  1298. +                     /* #Specification: pseudo root / dir lookup
  1299. +                         For the same reason as readdir, a lookup in /DOS for
  1300. +                         the pseudo root directory (linux) will fail.
  1301. +                     */
  1302. +                     /*
  1303. +                         This has to be allowed for resolving hard link
  1304. +                         which are recorded independantly of the pseudo-root
  1305. +                         mode.
  1306. +                     */
  1307. +                     iput (pseudo_root);
  1308. +                     *result = NULL;
  1309. +                     ret = -ENOENT;
  1310. +                 }
  1311. +             }
  1312. +         }
  1313. +     }
  1314. +     umsdos_endlookup(dir);    
  1315. +     iput (dir);
  1316. +     return ret;
  1317. + }
  1318. + /*
  1319. +     Check if a file exist in the current directory.
  1320. +     Return 0 if ok, negative error code if not (ex: -ENOENT).
  1321. + */
  1322. + int UMSDOS_lookup (
  1323. +     struct inode *dir,
  1324. +     const char *name,
  1325. +     int len,
  1326. +     struct inode **result)    /* Will hold inode of the file, if successful */
  1327. + {
  1328. +     return umsdos_lookup_x(dir,name,len,result,0);
  1329. + }
  1330. + /*
  1331. +     Locate the inode pointed by a (pseudo) hard link
  1332. +     Return 0 if ok, a negative error code if not.
  1333. + */
  1334. + int umsdos_hlink2inode (struct inode *hlink, struct inode **result)
  1335. + {
  1336. +     int ret = -EIO;
  1337. +     char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
  1338. +     *result = NULL;
  1339. +     if (path == NULL){
  1340. +         ret = -ENOMEM;
  1341. +         iput (hlink);
  1342. +     }else{
  1343. +         struct file filp;
  1344. +         filp.f_pos = 0;
  1345. +         PRINTK (("hlink2inode "));
  1346. +         if (msdos_file_read_kmem (hlink,&filp,path,hlink->i_size)
  1347. +             ==hlink->i_size){
  1348. +             struct inode *dir;
  1349. +             char *pt = path;
  1350. +             dir = hlink->i_sb->s_mounted;
  1351. +             path[hlink->i_size] = '\0';
  1352. +             iput (hlink);
  1353. +             dir->i_count++;
  1354. +             while (1){
  1355. +                 char *start = pt;
  1356. +                 int len;
  1357. +                 while (*pt != '\0' && *pt != '/') pt++;
  1358. +                 len = (int)(pt - start);
  1359. +                 if (*pt == '/') *pt++ = '\0';
  1360. +                 if (dir->u.umsdos_i.i_emd_dir == 0){
  1361. +                     /* This is a DOS directory */
  1362. +                     ret = msdos_lookup(dir,start,len,result);
  1363. +                 }else{
  1364. +                     ret = umsdos_lookup_x(dir,start,len,result,1);
  1365. +                 }
  1366. +                 PRINTK (("h2n lookup :%s: -> %d ",start,ret));
  1367. +                 if (ret == 0 && *pt != '\0'){
  1368. +                     dir = *result;
  1369. +                 }else{
  1370. +                     break;
  1371. +                 }
  1372. +             }
  1373. +         }else{
  1374. +             iput (hlink);
  1375. +         }
  1376. +         PRINTK (("hlink2inode ret = %d %p -> %p\n",ret,hlink,*result));
  1377. +         kfree (path);
  1378. +     }
  1379. +     return ret;
  1380. + }
  1381. + static struct file_operations umsdos_dir_operations = {
  1382. +     NULL,                /* lseek - default */
  1383. +     UMSDOS_dir_read,    /* read */
  1384. +     NULL,                /* write - bad */
  1385. +     UMSDOS_readdir,        /* readdir */
  1386. +     NULL,                /* select - default */
  1387. +     UMSDOS_ioctl_dir,    /* ioctl - default */
  1388. +     NULL,                /* mmap */
  1389. +     NULL,                /* no special open code */
  1390. +     NULL,                /* no special release code */
  1391. +     NULL                /* fsync */
  1392. + };
  1393. + struct inode_operations umsdos_dir_inode_operations = {
  1394. +     &umsdos_dir_operations,    /* default directory file-ops */
  1395. +     UMSDOS_create,        /* create */
  1396. +     UMSDOS_lookup,        /* lookup */
  1397. +     UMSDOS_link,        /* link */
  1398. +     UMSDOS_unlink,        /* unlink */
  1399. +     UMSDOS_symlink,        /* symlink */
  1400. +     UMSDOS_mkdir,        /* mkdir */
  1401. +     UMSDOS_rmdir,        /* rmdir */
  1402. +     UMSDOS_mknod,        /* mknod */
  1403. +     UMSDOS_rename,        /* rename */
  1404. +     NULL,            /* readlink */
  1405. +     NULL,            /* follow_link */
  1406. +     NULL,            /* bmap */
  1407. +     NULL,            /* truncate */
  1408. +     NULL            /* permission */
  1409. + };
  1410. diff -rc2P linux.1.1.12/fs/umsdos/emd.c linux/fs/umsdos/emd.c
  1411. *** linux.1.1.12/fs/umsdos/emd.c
  1412. --- linux/fs/umsdos/emd.c    Wed May 11 23:47:28 1994
  1413. ***************
  1414. *** 0 ****
  1415. --- 1,454 ----
  1416. + /*
  1417. +  *  linux/fs/umsdos/emd.c
  1418. +  *
  1419. +  *  Written 1993 by Jacques Gelinas
  1420. +  *
  1421. +  *  Extended MS-DOS directory handling functions
  1422. +  */
  1423. + #include <linux/types.h>
  1424. + #include <linux/fcntl.h>
  1425. + #include <linux/kernel.h>
  1426. + #include <linux/sched.h>
  1427. + #include <linux/errno.h>
  1428. + #include <linux/string.h>
  1429. + #include <linux/msdos_fs.h>
  1430. + #include <linux/umsdos_fs.h>
  1431. + #define PRINTK(x)
  1432. + #define Printk(x) printk x
  1433. + /*
  1434. +     Write a block of bytes into one EMD file.
  1435. +     The block of data is NOT in user space.
  1436. +     Return 0 if ok, a negative error code if not.
  1437. + */
  1438. + int umsdos_emd_dir_write (
  1439. +     struct inode *emd_dir,
  1440. +     struct file *filp,
  1441. +     char *buf,    /* buffer in kernel memory, not in user space */
  1442. +     int count)
  1443. + {
  1444. +     int written;
  1445. +     filp->f_flags = 0;
  1446. +     written = msdos_file_write_kmem (emd_dir,filp,buf,count);
  1447. +     return written != count ? -EIO : 0;
  1448. + }
  1449. + /*
  1450. +     Read a block of bytes from one EMD file.
  1451. +     The block of data is NOT in user space.
  1452. +     Retourne 0 if ok, -EIO if any error.
  1453. + */
  1454. + int umsdos_emd_dir_read (
  1455. +     struct inode *emd_dir,
  1456. +     struct file *filp,
  1457. +     char *buf,    /* buffer in kernel memory, not in user space */
  1458. +     int count)
  1459. + {
  1460. +     int ret = 0;
  1461. +     int sizeread;
  1462. +     filp->f_flags = 0;
  1463. +     sizeread = msdos_file_read_kmem (emd_dir,filp,buf,count);
  1464. +     if (sizeread != count){
  1465. +         printk ("UMSDOS: problem with EMD file. Can't read\n");
  1466. +         ret = -EIO;
  1467. +     }
  1468. +     return ret;
  1469. + }
  1470. + /*
  1471. +     Locate the EMD file in a directory and optionnally, creates it.
  1472. +     Return NULL if error. If ok, dir->u.umsdos_i.emd_inode 
  1473. + */
  1474. + struct inode *umsdos_emd_dir_lookup(struct inode *dir, int creat)
  1475. + {
  1476. +     struct inode *ret = NULL;
  1477. +     if (dir->u.umsdos_i.i_emd_dir != 0){
  1478. +         ret = iget (dir->i_sb,dir->u.umsdos_i.i_emd_dir);
  1479. +         PRINTK (("deja trouve %d %x [%d] "
  1480. +             ,dir->u.umsdos_i.i_emd_dir,ret,ret->i_count));
  1481. +     }else{
  1482. +         umsdos_real_lookup (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN,&ret);
  1483. +         PRINTK (("emd_dir_lookup "));
  1484. +         if (ret != NULL){
  1485. +             PRINTK (("Find --linux "));
  1486. +             dir->u.umsdos_i.i_emd_dir = ret->i_ino;
  1487. +         }else if (creat){
  1488. +             int code;
  1489. +             PRINTK (("avant create "));
  1490. +             dir->i_count++;
  1491. +             code = msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN
  1492. +                 ,S_IFREG|0777,&ret);
  1493. +             PRINTK (("Creat EMD code %d ret %x ",code,ret));
  1494. +             if (ret != NULL){
  1495. +                 dir->u.umsdos_i.i_emd_dir = ret->i_ino;
  1496. +             }else{
  1497. +                 printk ("UMSDOS: Can't create EMD file\n");
  1498. +             }
  1499. +         }
  1500. +     }
  1501. +     if (ret != NULL){
  1502. +         /* Disable UMSDOS_notify_change() for EMD file */
  1503. +         ret->u.umsdos_i.i_emd_owner = 0xffffffff;
  1504. +     }
  1505. +     return ret;
  1506. + }
  1507. + /*
  1508. +     Read an entry from the EMD file.
  1509. +     Support variable length record.
  1510. +     Return -EIO if error, 0 if ok.
  1511. + */
  1512. + int umsdos_emd_dir_readentry (
  1513. +     struct inode *emd_dir,
  1514. +     struct file *filp,
  1515. +     struct umsdos_dirent *entry)
  1516. + {
  1517. +     int ret = umsdos_emd_dir_read(emd_dir,filp,(char*)entry,UMSDOS_REC_SIZE);
  1518. +     if (ret == 0){
  1519. +         /* Variable size record. Maybe, we have to read some more */
  1520. +         int recsize = umsdos_evalrecsize (entry->name_len);
  1521. +         if (recsize > UMSDOS_REC_SIZE){
  1522. +             ret = umsdos_emd_dir_read(emd_dir,filp
  1523. +                 ,((char*)entry)+UMSDOS_REC_SIZE,recsize - UMSDOS_REC_SIZE);
  1524. +             
  1525. +         }
  1526. +     }
  1527. +     return ret;
  1528. + }
  1529. + /*
  1530. +     Write an entry in the EMD file.
  1531. +     Return 0 if ok, -EIO if some error.
  1532. + */
  1533. + int umsdos_writeentry (
  1534. +     struct inode *dir,
  1535. +     struct inode *emd_dir,
  1536. +     struct umsdos_info *info,
  1537. +     int free_entry)        /* This entry is deleted, so Write all 0's */
  1538. + {
  1539. +     int ret = 0;
  1540. +     struct file filp;
  1541. +     struct umsdos_dirent *entry = &info->entry;
  1542. +     struct umsdos_dirent entry0;
  1543. +     if (free_entry){
  1544. +         /* #Specification: EMD file / empty entries
  1545. +             Unused entry in the EMD file are identify
  1546. +             by the name_len field equal to 0. However to
  1547. +             help future extension (or bug corretion :-( ),
  1548. +             empty entries are filled with 0.
  1549. +         */
  1550. +         memset (&entry0,0,sizeof(entry0));
  1551. +         entry = &entry0;
  1552. +     }else if (entry->name_len > 0){
  1553. +         memset (entry->name+entry->name_len,'\0'
  1554. +             ,sizeof(entry->name)-entry->name_len);
  1555. +         /* #Specification: EMD file / spare bytes
  1556. +             10 bytes are unused in each record of the EMD. They
  1557. +             are set to 0 all the time. So it will be possible
  1558. +             to do new stuff and rely on the state of those
  1559. +             bytes in old EMD file around.
  1560. +         */
  1561. +         memset (entry->spare,0,sizeof(entry->spare));
  1562. +     }
  1563. +     filp.f_pos = info->f_pos;
  1564. +     ret = umsdos_emd_dir_write(emd_dir,&filp,(char*)entry,info->recsize);
  1565. +     if (ret != 0){
  1566. +         printk ("UMSDOS: problem with EMD file. Can't write\n");
  1567. +     }else{
  1568. +         dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  1569. +         dir->i_dirt = 1;
  1570. +     }
  1571. +     return ret;
  1572. + }
  1573. + #define CHUNK_SIZE (16*UMSDOS_REC_SIZE)
  1574. + struct find_buffer{
  1575. +     char buffer[CHUNK_SIZE];
  1576. +     int pos;    /* read offset in buffer */
  1577. +     int size;    /* Current size of buffer */
  1578. +     struct file filp;
  1579. + };
  1580. + /*
  1581. +     Fill the read buffer and take care of the byte remaining inside.
  1582. +     Unread bytes are simply move to the beginning.
  1583. +     Return -ENOENT if EOF, 0 if ok, a negativ error code if any problem.
  1584. + */
  1585. + static int umsdos_fillbuf (
  1586. +     struct inode *inode,
  1587. +     struct find_buffer *buf)
  1588. + {
  1589. +     int ret = -ENOENT;
  1590. +     int mustmove = buf->size - buf->pos;
  1591. +     int mustread;
  1592. +     int remain;
  1593. +     if (mustmove > 0){
  1594. +         memcpy (buf->buffer,buf->buffer+buf->pos,mustmove);
  1595. +     }
  1596. +     buf->pos = 0;
  1597. +     mustread = CHUNK_SIZE - mustmove;
  1598. +     remain = inode->i_size - buf->filp.f_pos;
  1599. +     if (remain < mustread) mustread = remain;
  1600. +     if (mustread > 0){
  1601. +         ret = umsdos_emd_dir_read (inode,&buf->filp,buf->buffer+mustmove
  1602. +             ,mustread);
  1603. +         if (ret == 0) buf->size = mustmove + mustread;        
  1604. +     }else if (mustmove){
  1605. +         buf->size = mustmove;
  1606. +         ret = 0;
  1607. +     }
  1608. +     return ret;
  1609. + }
  1610. + /*
  1611. +     General search, locate a name in the EMD file or an empty slot to
  1612. +     store it. if info->entry.name_len == 0, search the first empty
  1613. +     slot (of the proper size).
  1614. +     Caller must do iput on *pt_emd_dir.
  1615. +     Return 0 if found, -ENOENT if not found, another error code if
  1616. +     other problem.
  1617. +     So this routine is used to either find an existing entry or to
  1618. +     create a new one, while making sure it is a new one. After you
  1619. +     get -ENOENT, you make sure the entry is stuffed correctly and
  1620. +     call umsdos_writeentry().
  1621. +     To delete an entry, you find it, zero out the entry (memset)
  1622. +     and call umsdos_writeentry().
  1623. +     All this to say that umsdos_writeentry must be call after this
  1624. +     function since it rely on the f_pos field of info.
  1625. + */
  1626. + static int umsdos_find (
  1627. +     struct inode *dir,
  1628. +     struct umsdos_info *info,        /* Hold name and name_len */
  1629. +                                     /* Will hold the entry found */
  1630. +     struct inode **pt_emd_dir)        /* Will hold the emd_dir inode */
  1631. +                                     /* or NULL if not found */
  1632. + {
  1633. +     /* #Specification: EMD file structure
  1634. +         The EMD file uses a fairly simple layout. It is made of records
  1635. +         (UMSDOS_REC_SIZE == 64). When a name can't be written is a single
  1636. +         record, multiple contiguous record are allocated.
  1637. +     */
  1638. +     int ret = -ENOENT;
  1639. +     struct inode *emd_dir = umsdos_emd_dir_lookup(dir,1);
  1640. +     if (emd_dir != NULL){
  1641. +         struct umsdos_dirent *entry = &info->entry;
  1642. +         int recsize = info->recsize;
  1643. +         struct {
  1644. +             off_t posok;    /* Position available to store the entry */
  1645. +             int found;        /* A valid empty position has been found */
  1646. +             off_t one;        /* One empty position -> maybe <- large enough */
  1647. +             int onesize;    /* size of empty region starting at one */
  1648. +         }empty;
  1649. +         /* Read several entries at a time to speed up the search */
  1650. +         struct find_buffer buf;
  1651. +         buf.pos = 0;
  1652. +         buf.size = 0;
  1653. +         buf.filp.f_pos = 0;
  1654. +         empty.found = 0;
  1655. +         empty.posok = emd_dir->i_size;
  1656. +         empty.onesize = 0;
  1657. +         while (1){
  1658. +             struct umsdos_dirent *rentry = (struct umsdos_dirent*)
  1659. +                 (buf.buffer + buf.pos);
  1660. +             int file_pos = buf.filp.f_pos - buf.size + buf.pos;
  1661. +             if (buf.pos == buf.size){
  1662. +                 ret = umsdos_fillbuf (emd_dir,&buf);
  1663. +                 if (ret < 0){
  1664. +                     /* Not found, so note where it can be added */
  1665. +                     info->f_pos = empty.posok;
  1666. +                     break;
  1667. +                 }
  1668. +             }else if (rentry->name_len == 0){
  1669. +                 /* We are looking for an empty section at least */
  1670. +                 /* recsize large */
  1671. +                 if (entry->name_len == 0){
  1672. +                     info->f_pos = file_pos;
  1673. +                     ret = 0;
  1674. +                     break;
  1675. +                 }else if (!empty.found){
  1676. +                     if (empty.onesize == 0){
  1677. +                         /* This is the first empty record of a section */
  1678. +                         empty.one = file_pos;
  1679. +                     }
  1680. +                     /* grow the empty section */
  1681. +                     empty.onesize += UMSDOS_REC_SIZE;
  1682. +                     if (empty.onesize == recsize){
  1683. +                         /* here is a large enough section */
  1684. +                         empty.posok = empty.one;
  1685. +                         empty.found = 1;
  1686. +                     }
  1687. +                 }
  1688. +                 buf.pos += UMSDOS_REC_SIZE;
  1689. +             }else{
  1690. +                 int entry_size = umsdos_evalrecsize(rentry->name_len);
  1691. +                 if (buf.pos+entry_size > buf.size){
  1692. +                     ret = umsdos_fillbuf (emd_dir,&buf);
  1693. +                     if (ret < 0){
  1694. +                         /* Not found, so note where it can be added */
  1695. +                         info->f_pos = empty.posok;
  1696. +                         break;
  1697. +                     }
  1698. +                 }else{
  1699. +                     empty.onesize = 0;    /* Reset the free slot search */
  1700. +                     if (entry->name_len == rentry->name_len
  1701. +                         && memcmp(entry->name,rentry->name,rentry->name_len)
  1702. +                             ==0){
  1703. +                         info->f_pos = file_pos;
  1704. +                         *entry = *rentry;
  1705. +                         ret = 0;
  1706. +                         break;
  1707. +                     }else{
  1708. +                         buf.pos += entry_size;
  1709. +                     }
  1710. +                 }
  1711. +             }    
  1712. +         }
  1713. +         umsdos_manglename(info);
  1714. +     }
  1715. +     *pt_emd_dir = emd_dir;
  1716. +     return ret;
  1717. + }
  1718. + /*
  1719. +     Add a new entry in the emd file
  1720. +     Return 0 if ok or a negative error code.
  1721. +     Return -EEXIST if the entry already exist.
  1722. +     Complete the information missing in info.
  1723. + */
  1724. + int umsdos_newentry (
  1725. +     struct inode *dir,
  1726. +     struct umsdos_info *info)
  1727. + {
  1728. +     struct inode *emd_dir;
  1729. +     int ret = umsdos_find (dir,info,&emd_dir);
  1730. +     if (ret == 0){
  1731. +         ret = -EEXIST;
  1732. +     }else if (ret == -ENOENT){
  1733. +         ret = umsdos_writeentry(dir,emd_dir,info,0);
  1734. +         PRINTK (("umsdos_newentry EDM ret = %d\n",ret));
  1735. +     }
  1736. +     iput (emd_dir);
  1737. +     return ret;
  1738. + }
  1739. + /*
  1740. +     Create a new hidden link.
  1741. +     Return 0 if ok, an error code if not.
  1742. + */
  1743. + int umsdos_newhidden (
  1744. +     struct inode *dir,
  1745. +     struct umsdos_info *info)
  1746. + {
  1747. +     struct inode *emd_dir;
  1748. +     int ret;
  1749. +     umsdos_parse ("..LINK",6,info);
  1750. +     info->entry.name_len = 0;
  1751. +     ret = umsdos_find (dir,info,&emd_dir);
  1752. +     iput (emd_dir);
  1753. +     if (ret == -ENOENT || ret == 0){
  1754. +         /* #Specification: hard link / hidden name
  1755. +             When a hard link is created, the original file is renamed
  1756. +             to a hidden name. The name is "..LINKNNN" where NNN is a
  1757. +             number define from the entry offset in the EMD file.
  1758. +         */
  1759. +         info->entry.name_len = sprintf (info->entry.name,"..LINK%ld"
  1760. +             ,info->f_pos);
  1761. +         ret = 0;
  1762. +     }
  1763. +     return ret;
  1764. + }
  1765. + /*
  1766. +     Remove an entry from the emd file
  1767. +     Return 0 if ok, a negative error code otherwise.
  1768. +     Complete the information missing in info.
  1769. + */
  1770. + int umsdos_delentry (
  1771. +     struct inode *dir,
  1772. +     struct umsdos_info *info,
  1773. +     int isdir)
  1774. + {
  1775. +     struct inode *emd_dir;
  1776. +     int ret = umsdos_find (dir,info,&emd_dir);
  1777. +     if (ret == 0){
  1778. +         if (info->entry.name_len != 0){
  1779. +             if ((isdir != 0) != (S_ISDIR(info->entry.mode) != 0)){
  1780. +                 if (S_ISDIR(info->entry.mode)){
  1781. +                     ret = -EISDIR;
  1782. +                 }else{
  1783. +                     ret = -ENOTDIR;
  1784. +                 }
  1785. +             }else{
  1786. +                 ret = umsdos_writeentry(dir,emd_dir,info,1);
  1787. +             }
  1788. +         }
  1789. +     }
  1790. +     iput(emd_dir);
  1791. +     return ret;
  1792. + }
  1793. + /*
  1794. +     Verify is a EMD directory is empty.
  1795. +     Return 0 if not empty
  1796. +            1 if empty
  1797. +            2 if empty, no EMD file.
  1798. + */
  1799. + int umsdos_isempty (struct inode *dir)
  1800. + {
  1801. +     int ret = 2;
  1802. +     struct inode *emd_dir = umsdos_emd_dir_lookup(dir,0);
  1803. +     /* If the EMD file does not exist, it is certainly empty :-) */
  1804. +     if (emd_dir != NULL){
  1805. +         struct file filp;
  1806. +         /* Find an empty slot */
  1807. +         filp.f_pos = 0;
  1808. +         filp.f_flags = O_RDONLY;
  1809. +         ret = 1;
  1810. +         while (filp.f_pos < emd_dir->i_size){
  1811. +             struct umsdos_dirent entry;
  1812. +             if (umsdos_emd_dir_readentry(emd_dir,&filp,&entry)!=0){
  1813. +                 ret = 0;
  1814. +                 break;
  1815. +             }else if (entry.name_len != 0){
  1816. +                 ret = 0;
  1817. +                 break;
  1818. +             }    
  1819. +         }
  1820. +         iput (emd_dir);
  1821. +     }
  1822. +     return ret;
  1823. + }
  1824. + /*
  1825. +     Locate an entry in a EMD directory.
  1826. +     Return 0 if ok, errcod if not, generally -ENOENT.
  1827. + */
  1828. + int umsdos_findentry (
  1829. +     struct inode *dir,
  1830. +     struct umsdos_info *info,
  1831. +     int expect)        /* 0: anything */
  1832. +                     /* 1: file */
  1833. +                     /* 2: directory */
  1834. + {
  1835. +     struct inode *emd_dir;
  1836. +     int ret = umsdos_find (dir,info,&emd_dir);
  1837. +     if (ret == 0){
  1838. +         if (expect != 0){
  1839. +             if (S_ISDIR(info->entry.mode)){
  1840. +                 if (expect != 2) ret = -EISDIR;
  1841. +             }else if (expect == 2){
  1842. +                 ret = -ENOTDIR;
  1843. +             }
  1844. +         }
  1845. +     }
  1846. +     iput (emd_dir);
  1847. +     return ret;
  1848. + }
  1849. diff -rc2P linux.1.1.12/fs/umsdos/file.c linux/fs/umsdos/file.c
  1850. *** linux.1.1.12/fs/umsdos/file.c
  1851. --- linux/fs/umsdos/file.c    Wed May 11 23:47:28 1994
  1852. ***************
  1853. *** 0 ****
  1854. --- 1,103 ----
  1855. + /*
  1856. +  *  linux/fs/umsdos/file.c
  1857. +  *
  1858. +  *  Written 1993 by Jacques Gelinas
  1859. +  *    inpired from linux/fs/msdos/file.c Werner Almesberger
  1860. +  *
  1861. +  *  Extended MS-DOS regular file handling primitives
  1862. +  */
  1863. + #include <asm/segment.h>
  1864. + #include <asm/system.h>
  1865. + #include <linux/sched.h>
  1866. + #include <linux/fs.h>
  1867. + #include <linux/msdos_fs.h>
  1868. + #include <linux/errno.h>
  1869. + #include <linux/fcntl.h>
  1870. + #include <linux/stat.h>
  1871. + #include <linux/msdos_fs.h>
  1872. + #include <linux/umsdos_fs.h>
  1873. + #define PRINTK(x)
  1874. + #define Printk(x)    printk x
  1875. + /*
  1876. +     Read a file into user space memory
  1877. + */
  1878. + static int UMSDOS_file_read(
  1879. +     struct inode *inode,
  1880. +     struct file *filp,
  1881. +     char *buf,
  1882. +     int count)
  1883. + {
  1884. +     /* We have to set the access time because msdos don't care */
  1885. +     int ret = msdos_file_read(inode,filp,buf,count);
  1886. +     inode->i_atime = CURRENT_TIME;
  1887. +     inode->i_dirt = 1;
  1888. +     return ret;
  1889. + }
  1890. + /*
  1891. +     Write a file from user space memory
  1892. + */
  1893. + static int UMSDOS_file_write(
  1894. +     struct inode *inode,
  1895. +     struct file *filp,
  1896. +     char *buf,
  1897. +     int count)
  1898. + {
  1899. +     return msdos_file_write(inode,filp,buf,count);
  1900. + }
  1901. + /*
  1902. +     Truncate a file to 0 length.
  1903. + */
  1904. + static void UMSDOS_truncate(struct inode *inode)
  1905. + {
  1906. +     PRINTK (("UMSDOS_truncate\n"));
  1907. +     msdos_truncate (inode);
  1908. +     inode->i_ctime = inode->i_mtime = CURRENT_TIME;
  1909. +     inode->i_dirt = 1;
  1910. + }
  1911. + /*
  1912. +     See inode.c
  1913. +     
  1914. +     Some entry point are filled dynamicly with function pointers
  1915. +     from the msdos file_operations and file_inode_operations.
  1916. +     
  1917. +     The idea is to have the code as independant as possible from
  1918. +     the msdos file system.
  1919. + */
  1920. + struct file_operations umsdos_file_operations = {
  1921. +     NULL,                /* lseek - default */
  1922. +     UMSDOS_file_read,    /* read */
  1923. +     UMSDOS_file_write,    /* write */
  1924. +     NULL,                /* readdir - bad */
  1925. +     NULL,                /* select - default */
  1926. +     NULL,                /* ioctl - default */
  1927. +     msdos_mmap,            /* mmap */
  1928. +     NULL,                /* no special open is needed */
  1929. +     NULL,                /* release */
  1930. +     NULL                /* fsync */
  1931. + };
  1932. + struct inode_operations umsdos_file_inode_operations = {
  1933. +     &umsdos_file_operations,    /* default file operations */
  1934. +     NULL,            /* create */
  1935. +     NULL,            /* lookup */
  1936. +     NULL,            /* link */
  1937. +     NULL,            /* unlink */
  1938. +     NULL,            /* symlink */
  1939. +     NULL,            /* mkdir */
  1940. +     NULL,            /* rmdir */
  1941. +     NULL,            /* mknod */
  1942. +     NULL,            /* rename */
  1943. +     NULL,            /* readlink */
  1944. +     NULL,            /* follow_link */
  1945. +     NULL,            /* bmap */
  1946. +     UMSDOS_truncate,/* truncate */
  1947. +     NULL,            /* permission */
  1948. +     msdos_smap        /* smap */
  1949. + };
  1950. diff -rc2P linux.1.1.12/fs/umsdos/inode.c linux/fs/umsdos/inode.c
  1951. *** linux.1.1.12/fs/umsdos/inode.c
  1952. --- linux/fs/umsdos/inode.c    Thu May 12 09:44:21 1994
  1953. ***************
  1954. *** 0 ****
  1955. --- 1,465 ----
  1956. + /*
  1957. +  *  linux/fs/umsdos/inode.c
  1958. +  *
  1959. +  *    Written 1993 by Jacques Gelinas 
  1960. +  *    Inspired from linux/fs/msdos/... by Werner Almesberger
  1961. +  *
  1962. +  */
  1963. + #include <stdlib.h>
  1964. + #include <linux/fs.h>
  1965. + #include <linux/msdos_fs.h>
  1966. + #include <linux/kernel.h>
  1967. + #include <linux/sched.h>
  1968. + #include <linux/errno.h>
  1969. + #include <asm/segment.h>
  1970. + #include <linux/string.h>
  1971. + #include <linux/ctype.h>
  1972. + #include <linux/stat.h>
  1973. + #include <linux/umsdos_fs.h>
  1974. + struct inode *pseudo_root=NULL;        /* Useful to simulate the pseudo DOS */
  1975. +                                     /* directory. See UMSDOS_readdir_x() */
  1976. + /* #Specification: convention / PRINTK Printk and printk
  1977. +     Here is the convention for the use of printk inside fs/umsdos
  1978. +     printk carry important message (error or status).
  1979. +     Printk is for debugging (it is a macro defined at the beginning of
  1980. +            most source.
  1981. +     PRINTK is a nulled Printk macro.
  1982. +     This convention makes the source easier to read, and Printk easier
  1983. +     to shut off.
  1984. + */
  1985. + #define PRINTK(x)
  1986. + #define Printk(x) printk x
  1987. + void UMSDOS_put_inode(struct inode *inode)
  1988. + {
  1989. +     PRINTK (("put inode %x owner %x pos %d dir %x\n",inode
  1990. +         ,inode->u.umsdos_i.i_emd_owner,inode->u.umsdos_i.pos
  1991. +         ,inode->u.umsdos_i.i_emd_dir));
  1992. +     msdos_put_inode(inode);
  1993. + }
  1994. + void UMSDOS_put_super(struct super_block *sb)
  1995. + {
  1996. +     msdos_put_super(sb);
  1997. + }
  1998. + void UMSDOS_statfs(struct super_block *sb,struct statfs *buf)
  1999. + {
  2000. +     msdos_statfs(sb,buf);
  2001. + }
  2002. + /*
  2003. +     Call msdos_lookup, but set back the original msdos function table.
  2004. +     Retourne 0 if ok, or a negative error code if not.
  2005. + */
  2006. + int umsdos_real_lookup (
  2007. +     struct inode *dir,
  2008. +     const char *name,
  2009. +     int len,
  2010. +     struct inode **result)    /* Will hold inode of the file, if successful */
  2011. + {
  2012. +     int ret;
  2013. +     dir->i_count++;
  2014. +     ret = msdos_lookup (dir,name,len,result);
  2015. +     return ret;
  2016. + }
  2017. + /*
  2018. +     Complete the setup of an directory inode.
  2019. +     First, it completes the function pointers, then
  2020. +     it locates the EMD file. If the EMD is there, then plug the
  2021. +     umsdos function table. If not, use the msdos one.
  2022. + */
  2023. + void umsdos_setup_dir_inode (struct inode *inode)
  2024. + {
  2025. +     inode->u.umsdos_i.i_emd_dir = 0;
  2026. +     {
  2027. +         struct inode *emd_dir = umsdos_emd_dir_lookup (inode,0);
  2028. +         extern struct inode_operations umsdos_rdir_inode_operations;
  2029. +         inode->i_op = emd_dir != NULL
  2030. +             ? &umsdos_dir_inode_operations
  2031. +             : &umsdos_rdir_inode_operations;
  2032. +         iput (emd_dir);
  2033. +     }
  2034. + }
  2035. + /*
  2036. +     Add some info into an inode so it can find its owner quickly
  2037. + */
  2038. + void umsdos_set_dirinfo(
  2039. +     struct inode *inode,
  2040. +     struct inode *dir,
  2041. +     off_t f_pos)
  2042. + {
  2043. +     struct inode *emd_owner = umsdos_emd_dir_lookup(dir,1);
  2044. +     inode->u.umsdos_i.i_dir_owner = dir->i_ino;
  2045. +     inode->u.umsdos_i.i_emd_owner = emd_owner->i_ino;
  2046. +     iput (emd_owner);
  2047. +     inode->u.umsdos_i.pos = f_pos;
  2048. + }
  2049. + /*
  2050. +     Tells if an Umsdos inode has been "patched" once.
  2051. +     Returne != 0 if so.
  2052. + */
  2053. + int umsdos_isinit (struct inode *inode)
  2054. + {
  2055. + #if    1
  2056. +     return inode->u.umsdos_i.i_emd_owner != 0;
  2057. + #elif 0
  2058. +     return inode->i_atime != 0;
  2059. + #else
  2060. +     return inode->i_count > 1;
  2061. + #endif
  2062. + }
  2063. + /*
  2064. +     Connect the proper tables in the inode and add some info.
  2065. + */
  2066. + void umsdos_patch_inode (
  2067. +     struct inode *inode,
  2068. +     struct inode *dir,        /* May be NULL */
  2069. +     off_t f_pos)
  2070. + {
  2071. +     /*
  2072. +         This function is called very early to setup the inode, somewhat
  2073. +         too early (called by UMSDOS_read_inode). At this point, we can't
  2074. +         do to much, such as lookup up EMD files and so on. This causes
  2075. +         confusion in the kernel. This is why some initialisation
  2076. +         will be done when dir != NULL only.
  2077. +         UMSDOS do run piggy back on top of msdos fs. It looks like something
  2078. +         is missing in the VFS to accomodate stacked fs. Still unclear what
  2079. +         (quite honestly).
  2080. +         Well, maybe one! A new entry "may_unmount" which would allow
  2081. +         the stacked fs to allocate some inode permanently and release
  2082. +         them at the end. Doing that now introduce a problem. unmount
  2083. +         always fail because some inodes are in use.
  2084. +     */
  2085. +     if (!umsdos_isinit(inode)){
  2086. +         inode->u.umsdos_i.i_emd_dir = 0;
  2087. +         if (S_ISREG(inode->i_mode)){
  2088. +             static char is_init = 0;
  2089. +             if (!is_init){
  2090. +                 /*
  2091. +                     I don't want to change the msdos file system code
  2092. +                     so I get the adress of some subroutine dynamicly
  2093. +                     once.
  2094. +                 */
  2095. +                 umsdos_file_inode_operations.bmap = inode->i_op->bmap;
  2096. +                 inode->i_op = &umsdos_file_inode_operations;
  2097. +                 is_init = 1;
  2098. +             }
  2099. +             inode->i_op = &umsdos_file_inode_operations;
  2100. +         }else if (S_ISDIR(inode->i_mode)){
  2101. +             if (dir != NULL){
  2102. +                 umsdos_setup_dir_inode(inode);
  2103. +             }
  2104. +         }else if (S_ISLNK(inode->i_mode)){
  2105. +             inode->i_op = &umsdos_symlink_inode_operations;
  2106. +         }else if (S_ISCHR(inode->i_mode)){
  2107. +             inode->i_op = &chrdev_inode_operations;
  2108. +         }else if (S_ISBLK(inode->i_mode)){
  2109. +             inode->i_op = &blkdev_inode_operations;
  2110. +         }else if (S_ISFIFO(inode->i_mode)){
  2111. +             init_fifo(inode);
  2112. +         }
  2113. +         if (dir != NULL){
  2114. +             /* #Specification: inode / umsdos info
  2115. +                 The first time an inode is seen (inode->i_count == 1),
  2116. +                 the inode number of the EMD file which control this inode
  2117. +                 is tagged to this inode. It allows operation such
  2118. +                 as notify_change to be handled.
  2119. +             */
  2120. +             /*
  2121. +                 This is done last because it also control the
  2122. +                 status of umsdos_isinit()
  2123. +             */
  2124. +             umsdos_set_dirinfo (inode,dir,f_pos);
  2125. +         }
  2126. +     }else if (dir != NULL){
  2127. +         /*
  2128. +             Test to see if the info is maintained.
  2129. +             This should be removed when the file system will be proven.
  2130. +         */
  2131. +         struct inode *emd_owner = umsdos_emd_dir_lookup(dir,1);
  2132. +         iput (emd_owner);
  2133. +         if (emd_owner->i_ino != inode->u.umsdos_i.i_emd_owner){
  2134. +             printk ("UMSDOS: *** EMD_OWNER ??? *** ino = %ld %ld <> %ld "
  2135. +                 ,inode->i_ino,emd_owner->i_ino,inode->u.umsdos_i.i_emd_owner);
  2136. +         }
  2137. +     }
  2138. + }
  2139. + /*
  2140. +     Get the inode of the directory which owns this inode.
  2141. +     Return 0 if ok, -EIO if error.
  2142. + */
  2143. + int umsdos_get_dirowner(
  2144. +     struct inode *inode,
  2145. +     struct inode **result)    /* Hold NULL if any error */
  2146. +                             /* else, the inode of the directory */
  2147. + {
  2148. +     int ret = -EIO;
  2149. +     unsigned long ino = inode->u.umsdos_i.i_dir_owner;
  2150. +     *result = NULL;
  2151. +     if (ino == 0){
  2152. +         printk ("UMSDOS: umsdos_get_dirowner ino == 0\n");
  2153. +     }else{
  2154. +         struct inode *dir = *result = iget(inode->i_sb,ino);
  2155. +         if (dir != NULL){
  2156. +             umsdos_patch_inode (dir,NULL,0);
  2157. +             ret = 0;
  2158. +         }
  2159. +     }
  2160. +     return ret;
  2161. + }
  2162. + /*
  2163. +     Load an inode from disk.
  2164. + */
  2165. + void UMSDOS_read_inode(struct inode *inode)
  2166. + {
  2167. +     PRINTK (("read inode %x ino = %d ",inode,inode->i_ino));
  2168. +     msdos_read_inode(inode);
  2169. +     PRINTK (("ino = %d %d\n",inode->i_ino,inode->i_count));
  2170. +     if (S_ISDIR(inode->i_mode)
  2171. +         && (inode->u.umsdos_i.u.dir_info.creating != 0
  2172. +             || inode->u.umsdos_i.u.dir_info.looking != 0
  2173. +             || inode->u.umsdos_i.u.dir_info.p != NULL)){
  2174. +         Printk (("read inode %d %d %p\n"
  2175. +             ,inode->u.umsdos_i.u.dir_info.creating
  2176. +             ,inode->u.umsdos_i.u.dir_info.looking
  2177. +             ,inode->u.umsdos_i.u.dir_info.p));
  2178. +     }
  2179. +     /* #Specification: Inode / post initialisation
  2180. +         To completly initialise an inode, we need access to the owner
  2181. +         directory, so we can locate more info in the EMD file. This is
  2182. +         not available the first time the inode is access, we use
  2183. +         a value in the inode to tell if it has been finally initialised.
  2184. +         At first, we have tried testing i_count but it was causing
  2185. +         problem. It is possible that two or more process use the
  2186. +         newly accessed inode. While the first one block during
  2187. +         the initialisation (probably while reading the EMD file), the
  2188. +         others believe all is well because i_count > 1. They go banana
  2189. +         with a broken inode. See umsdos_lookup_patch and umsdos_patch_inode.
  2190. +     */
  2191. +     umsdos_patch_inode(inode,NULL,0);
  2192. + }
  2193. + /*
  2194. +     Update the disk with the inode content
  2195. + */
  2196. + void UMSDOS_write_inode(struct inode *inode)
  2197. + {
  2198. +     PRINTK (("UMSDOS_write_inode emd %d\n",inode->u.umsdos_i.i_emd_owner));
  2199. +     msdos_write_inode(inode);
  2200. +     UMSDOS_notify_change (NOTIFY_TIME,inode);
  2201. + }
  2202. + int UMSDOS_notify_change (int flags, struct inode *inode)
  2203. + {
  2204. +     int ret = 0;
  2205. +     if (inode->i_nlink > 0){
  2206. +         /* #Specification: notify_change / i_nlink > 0
  2207. +             notify change is only done for inode with nlink > 0. An inode
  2208. +             with nlink == 0 is no longer associated with any entry in
  2209. +             the EMD file, so there is nothing to update.
  2210. +         */
  2211. +         unsigned long i_emd_owner = inode->u.umsdos_i.i_emd_owner;
  2212. +         if (inode == inode->i_sb->s_mounted){
  2213. +             /* #Specification: root inode / attributes
  2214. +                 I don't know yet how this should work. Normally
  2215. +                 the attributes (permissions bits, owner, times) of
  2216. +                 a directory are stored in the EMD file of its parent.
  2217. +                 One thing we could do is store the attributes of the root
  2218. +                 inode in its own EMD file. A simple entry named "." could
  2219. +                 be used for this special case. It would be read once
  2220. +                 when the file system is mounted and update in
  2221. +                 UMSDOS_notify_change() (right here).
  2222. +                 I am not sure of the behavior of the root inode for
  2223. +                 a real UNIX file system. For now, this is a nop.
  2224. +             */
  2225. +         }else if (i_emd_owner != 0xffffffff && i_emd_owner != 0){
  2226. +             /* This inode is not a EMD file nor an inode used internally
  2227. +                 by MSDOS, so we can update its status.
  2228. +                 See emd.c
  2229. +             */
  2230. +             struct inode *emd_owner = iget (inode->i_sb,i_emd_owner);
  2231. +             PRINTK (("notify change %p ",inode));
  2232. +             if (emd_owner == NULL){
  2233. +                 printk ("UMSDOS: emd_owner = NULL ???");
  2234. +                 ret = -EPERM;
  2235. +             }else{
  2236. +                 struct file filp;
  2237. +                 struct umsdos_dirent entry;
  2238. +                 filp.f_pos = inode->u.umsdos_i.pos;
  2239. +                 PRINTK (("pos = %d ",filp.f_pos));
  2240. +                 /* Read only the start of the entry since we don't touch */
  2241. +                 /* the name */
  2242. +                 ret = umsdos_emd_dir_read (emd_owner,&filp,(char*)&entry
  2243. +                     ,UMSDOS_REC_SIZE);
  2244. +                 if (ret == 0){
  2245. +                     if (flags & NOTIFY_UIDGID){
  2246. +                         entry.uid = inode->i_uid;
  2247. +                         entry.gid = inode->i_gid;
  2248. +                         /* Remove those flags msdos don't like */
  2249. +                         flags &= ~NOTIFY_UIDGID;
  2250. +                     }
  2251. +                     if (flags & NOTIFY_MODE){
  2252. +                         entry.mode = inode->i_mode;
  2253. +                         flags &= ~NOTIFY_MODE;
  2254. +                     }
  2255. +                     if (flags & NOTIFY_TIME){
  2256. +                         entry.atime = inode->i_atime;
  2257. +                         entry.mtime = inode->i_mtime;
  2258. +                         entry.ctime = inode->i_ctime;
  2259. +                     }
  2260. +                     entry.nlink = inode->i_nlink;
  2261. +                     filp.f_pos = inode->u.umsdos_i.pos;
  2262. +                     ret = umsdos_emd_dir_write (emd_owner,&filp,(char*)&entry
  2263. +                         ,UMSDOS_REC_SIZE);
  2264. +                     PRINTK (("notify pos %d ret %d nlink %d "
  2265. +                         ,inode->u.umsdos_i.pos
  2266. +                         ,ret,entry.nlink));
  2267. +                     /* #Specification: notify_change / msdos fs
  2268. +                         notify_change operation are done only on the
  2269. +                         EMD file. The msdos fs is not even called.
  2270. +                     */
  2271. +                     #if 0
  2272. +                     if (ret == 0
  2273. +                         && (S_ISDIR(inode->i_mode)
  2274. +                             || S_ISREG(inode->i_mode))){
  2275. +                         ret = msdos_notify_change(flags, inode);
  2276. +                         printk ("msdos_notify %x %d",inode,ret);
  2277. +                     }
  2278. +                     #endif
  2279. +                 }
  2280. +                 iput (emd_owner);
  2281. +             }
  2282. +             PRINTK (("\n"));
  2283. +         }
  2284. +     }
  2285. +     return ret;
  2286. + }
  2287. + /* #Specification: function name / convention
  2288. +     A simple convention for function name has been used in
  2289. +     the UMSDOS file system. First all function use the prefix
  2290. +     umsdos_ to avoid name clash with other part of the kernel.
  2291. +     And standard VFS entry point use the prefix UMSDOS (upper case)
  2292. +     so it's easier to tell them apart.
  2293. + */
  2294. + static struct super_operations umsdos_sops = { 
  2295. +     UMSDOS_read_inode,
  2296. +     UMSDOS_notify_change,
  2297. +     UMSDOS_write_inode,
  2298. +     UMSDOS_put_inode,
  2299. +     UMSDOS_put_super,
  2300. +     NULL, /* added in 0.96c */
  2301. +     UMSDOS_statfs,
  2302. +     NULL
  2303. + };
  2304. + /*
  2305. +     Read the super block of an Extended MS-DOS FS.
  2306. + */
  2307. + struct super_block *UMSDOS_read_super(
  2308. +     struct super_block *s,
  2309. +     void *data,
  2310. +     int silent)
  2311. + {
  2312. +     /* #Specification: mount / options
  2313. +         Umsdos run on top of msdos. Currently, it supports no
  2314. +         mount option, but happily pass all option received to
  2315. +         the msdos driver. I am not sure if all msdos mount option
  2316. +         make sens with Umsdos. Here are at least those who
  2317. +         are useful.
  2318. +             uid=
  2319. +             gid=
  2320. +         These options affect the operation of umsdos in directories
  2321. +         which do not have an EMD file. They behave like normal
  2322. +         msdos directory, with all limitation of msdos.
  2323. +     */
  2324. +     struct super_block *sb = msdos_read_super(s,data,silent);
  2325. +     printk ("UMSDOS Alpha %d.%d\n",UMSDOS_VERSION,UMSDOS_RELEASE);
  2326. +     if (sb != NULL){
  2327. +         sb->s_op = &umsdos_sops;
  2328. +         PRINTK (("umsdos_read_super %p\n",sb->s_mounted));
  2329. +         umsdos_setup_dir_inode (sb->s_mounted);
  2330. +         PRINTK (("End umsdos_read_super\n"));
  2331. +         if (s == super_blocks){
  2332. +             /* #Specification: pseudo root / mount
  2333. +                 When a umsdos fs is mounted, a special handling is done
  2334. +                 if it is the root partition. We check for the presence
  2335. +                 of the file /linux/etc/init or /linux/etc/rc.
  2336. +                 If one is there, we do a chroot("/linux").
  2337. +                 We check both because (see init/main.c) the kernel
  2338. +                 try to exec init at different place and if it fails
  2339. +                 it tries /bin/sh /etc/rc. To be consistent with
  2340. +                 init/main.c, many more test would have to be done
  2341. +                 to locate init. Any complain ?
  2342. +                 The chroot is done manually in init/main.c but the
  2343. +                 info (the inode) is located at mount time and store
  2344. +                 in a global variable (pseudo_root) which is used at
  2345. +                 different place in the umsdos driver. There is no
  2346. +                 need to store this variable elsewhere because it
  2347. +                 will always be one, not one per mount.
  2348. +                 This feature allows the installation
  2349. +                 of a linux system within a DOS system in a subdirectory.
  2350. +     
  2351. +                 A user may install its linux stuff in c:\linux
  2352. +                 avoiding any clash with existing DOS file and subdirectory.
  2353. +                 When linux boots, it hides this fact, showing a normal
  2354. +                 root directory with /etc /bin /tmp ...
  2355. +                 The word "linux" is hardcoded in /usr/include/linux/umsdos_fs.h
  2356. +                 in the macro UMSDOS_PSDROOT_NAME.
  2357. +             */
  2358. +             struct inode *pseudo;
  2359. +             Printk (("Mounting root\n"));
  2360. +             if (umsdos_real_lookup (sb->s_mounted,UMSDOS_PSDROOT_NAME
  2361. +                     ,UMSDOS_PSDROOT_LEN,&pseudo)==0
  2362. +                 && S_ISDIR(pseudo->i_mode)){
  2363. +                 struct inode *etc = NULL;
  2364. +                 struct inode *rc = NULL;
  2365. +                 Printk (("/%s is there\n",UMSDOS_PSDROOT_NAME));
  2366. +                 if (umsdos_real_lookup (pseudo,"etc",3,&etc)==0
  2367. +                     && S_ISDIR(etc->i_mode)){
  2368. +                     struct inode *init;
  2369. +                     Printk (("/%s/etc is there\n",UMSDOS_PSDROOT_NAME));
  2370. +                     if ((umsdos_real_lookup (etc,"init",4,&init)==0
  2371. +                             && S_ISREG(init->i_mode))
  2372. +                         || (umsdos_real_lookup (etc,"rc",2,&rc)==0
  2373. +                             && S_ISREG(rc->i_mode))){
  2374. +                         umsdos_setup_dir_inode (pseudo);
  2375. +                         Printk (("Activating pseudo root /%s\n",UMSDOS_PSDROOT_NAME));
  2376. +                         pseudo_root = pseudo;
  2377. +                         pseudo->i_count++;
  2378. +                         pseudo = NULL;
  2379. +                     }
  2380. +                     iput (init);
  2381. +                     iput (rc);
  2382. +                 }
  2383. +                 iput (etc);
  2384. +             }
  2385. +             iput (pseudo);
  2386. +         }
  2387. +     }
  2388. +     return sb;
  2389. + }
  2390. diff -rc2P linux.1.1.12/fs/umsdos/ioctl.c linux/fs/umsdos/ioctl.c
  2391. *** linux.1.1.12/fs/umsdos/ioctl.c
  2392. --- linux/fs/umsdos/ioctl.c    Wed May 11 23:47:30 1994
  2393. ***************
  2394. *** 0 ****
  2395. --- 1,259 ----
  2396. + /*
  2397. +  *  linux/fs/umsdos/ioctl.c
  2398. +  *
  2399. +  *  Written 1993 by Jacques Gelinas
  2400. +  *
  2401. +  *  Extended MS-DOS ioctl directory handling functions
  2402. +  */
  2403. + #include <asm/segment.h>
  2404. + #include <linux/errno.h>
  2405. + #include <linux/kernel.h>
  2406. + #include <linux/sched.h>
  2407. + #include <linux/fs.h>
  2408. + #include <linux/msdos_fs.h>
  2409. + #include <linux/umsdos_fs.h>
  2410. + #define PRINTK(x)
  2411. + #define Printk(x) printk x
  2412. + /*
  2413. +     Perform special function on a directory
  2414. + */
  2415. + int UMSDOS_ioctl_dir (
  2416. +     struct inode *dir,
  2417. +     struct file *filp,
  2418. +     unsigned int cmd,
  2419. +     unsigned long data)
  2420. + {
  2421. +     int ret = -EPERM;
  2422. +     /* #Specification: ioctl / acces
  2423. +         Only root (effective id) is allowed to do IOCTL on directory
  2424. +         in UMSDOS. EPERM is returned for other user.
  2425. +     */
  2426. +     if (current->euid == 0
  2427. +         || cmd == UMSDOS_GETVERSION){
  2428. +         struct umsdos_ioctl *idata = (struct umsdos_ioctl *)data;
  2429. +         ret = -EINVAL;
  2430. +         /* #Specification: ioctl / prototypes
  2431. +             The official prototype for the umsdos ioctl on directory
  2432. +             is:
  2433. +             int ioctl (
  2434. +                 int fd,        // File handle of the directory
  2435. +                 int cmd,    // command
  2436. +                 struct umsdos_ioctl *data)
  2437. +             The struct and the commands are defined in linux/umsdos_fs.h.
  2438. +             umsdos_progs/umsdosio.c provide an interface in C++ to all
  2439. +             these ioctl. umsdos_progs/udosctl is a small utility showing
  2440. +             all this.
  2441. +             These ioctl generally allow one to work on the EMD or the
  2442. +             DOS directory independantly. These are essential to implement
  2443. +             the synchroniser.
  2444. +         */
  2445. +         PRINTK (("ioctl %d ",cmd));
  2446. +         if (cmd == UMSDOS_GETVERSION){
  2447. +             /* #Specification: ioctl / UMSDOS_GETVERSION
  2448. +                 The field version and release of the structure
  2449. +                 umsdos_ioctl are filled with the version and release
  2450. +                 number of the fs code in the kernel. This will allow
  2451. +                 some form of checking. Users won't be able to run
  2452. +                 incompatible utility such as the synchroniser (umssync).
  2453. +                 umsdos_progs/umsdosio.c enforce this checking.
  2454. +                 Return always 0.
  2455. +             */
  2456. +             put_fs_byte (UMSDOS_VERSION,&idata->version);
  2457. +             put_fs_byte (UMSDOS_RELEASE,&idata->release);
  2458. +             ret = 0;
  2459. +         }else if (cmd == UMSDOS_READDIR_DOS){
  2460. +             /* #Specification: ioctl / UMSDOS_READDIR_DOS
  2461. +                 One entry is read from the DOS directory at the current
  2462. +                 file position. The entry is put as is in the dos_dirent
  2463. +                 field of struct umsdos_ioctl.
  2464. +                 Return > 0 if success.
  2465. +             */
  2466. +             ret = msdos_readdir(dir,filp,&idata->dos_dirent,1);
  2467. +         }else if (cmd == UMSDOS_READDIR_EMD){
  2468. +             /* #Specification: ioctl / UMSDOS_READDIR_EMD
  2469. +                 One entry is read from the EMD at the current
  2470. +                 file position. The entry is put as is in the umsdos_dirent
  2471. +                 field of struct umsdos_ioctl. The corresponding mangled
  2472. +                 DOS entry name is put in the dos_dirent field.
  2473. +                 All entries are read including hidden links. Blank
  2474. +                 entries are skipped.
  2475. +                 Return > 0 if success.
  2476. +             */
  2477. +             struct inode *emd_dir = umsdos_emd_dir_lookup (dir,0);
  2478. +             if (emd_dir != NULL){
  2479. +                 while (1){
  2480. +                     if (filp->f_pos >= emd_dir->i_size){
  2481. +                         ret = 0;
  2482. +                         break;
  2483. +                     }else{
  2484. +                         struct umsdos_dirent entry;
  2485. +                         off_t f_pos = filp->f_pos;
  2486. +                         ret = umsdos_emd_dir_readentry (emd_dir,filp,&entry);
  2487. +                         if (ret < 0){
  2488. +                             break;
  2489. +                         }else if (entry.name_len > 0){
  2490. +                             struct umsdos_info info;
  2491. +                             ret = entry.name_len;
  2492. +                             umsdos_parse (entry.name,entry.name_len,&info);
  2493. +                             info.f_pos = f_pos;
  2494. +                             umsdos_manglename(&info);
  2495. +                             memcpy_tofs(&idata->umsdos_dirent,&entry
  2496. +                                 ,sizeof(entry));
  2497. +                             memcpy_tofs(&idata->dos_dirent.d_name
  2498. +                                 ,info.fake.fname,info.fake.len+1);
  2499. +                             break;
  2500. +                         }
  2501. +                     }
  2502. +                 }
  2503. +                 iput (emd_dir);
  2504. +             }else{
  2505. +                 /* The absence of the EMD is simply seen as an EOF */
  2506. +                 ret = 0;
  2507. +             }
  2508. +         }else if (cmd == UMSDOS_INIT_EMD){
  2509. +             /* #Specification: ioctl / UMSDOS_INIT_EMD
  2510. +                 The UMSDOS_INIT_EMD command make sure the EMD
  2511. +                 exist for a directory. If it does not, it is
  2512. +                 created. Also, it makes sure the directory functions
  2513. +                 table (struct inode_operations) is set to the UMSDOS
  2514. +                 semantic. This mean that umssync may be applied to
  2515. +                 an "opened" msdos directory, and it will change behavior
  2516. +                 on the fly.
  2517. +                 Return 0 if success.
  2518. +             */
  2519. +             extern struct inode_operations umsdos_rdir_inode_operations;
  2520. +             struct inode *emd_dir = umsdos_emd_dir_lookup (dir,1);
  2521. +             ret = emd_dir != NULL;
  2522. +             iput (emd_dir);
  2523. +                     
  2524. +             dir->i_op = ret
  2525. +                 ? &umsdos_dir_inode_operations
  2526. +                 : &umsdos_rdir_inode_operations;
  2527. +         }else{
  2528. +             struct umsdos_ioctl data;
  2529. +             memcpy_fromfs (&data,idata,sizeof(data));
  2530. +             if (cmd == UMSDOS_CREAT_EMD){
  2531. +                 /* #Specification: ioctl / UMSDOS_CREAT_EMD
  2532. +                     The umsdos_dirent field of the struct umsdos_ioctl is used
  2533. +                     as is to create a new entry in the EMD of the directory.
  2534. +                     The DOS directory is not modified.
  2535. +                     No validation is done (yet).
  2536. +                     Return 0 if success.
  2537. +                 */
  2538. +                 struct umsdos_info info;
  2539. +                 /* This makes sure info.entry and info in general is correctly */
  2540. +                 /* initialised */
  2541. +                 memcpy (&info.entry,&data.umsdos_dirent
  2542. +                     ,sizeof(data.umsdos_dirent));
  2543. +                 umsdos_parse (data.umsdos_dirent.name
  2544. +                     ,data.umsdos_dirent.name_len,&info);
  2545. +                 ret = umsdos_newentry (dir,&info);
  2546. +             }else if (cmd == UMSDOS_UNLINK_EMD){
  2547. +                 /* #Specification: ioctl / UMSDOS_UNLINK_EMD
  2548. +                     The umsdos_dirent field of the struct umsdos_ioctl is used
  2549. +                     as is to remove an entry from the EMD of the directory.
  2550. +                     No validation is done (yet). The mode field is used
  2551. +                     to validate S_ISDIR or S_ISREG.
  2552. +                     Return 0 if success.
  2553. +                 */
  2554. +                 struct umsdos_info info;
  2555. +                 /* This makes sure info.entry and info in general is correctly */
  2556. +                 /* initialised */
  2557. +                 memcpy (&info.entry,&data.umsdos_dirent
  2558. +                     ,sizeof(data.umsdos_dirent));
  2559. +                 umsdos_parse (data.umsdos_dirent.name
  2560. +                     ,data.umsdos_dirent.name_len,&info);
  2561. +                 ret = umsdos_delentry (dir,&info
  2562. +                     ,S_ISDIR(data.umsdos_dirent.mode));
  2563. +             }else if (cmd == UMSDOS_UNLINK_DOS){
  2564. +                 /* #Specification: ioctl / UMSDOS_UNLINK_DOS
  2565. +                     The dos_dirent field of the struct umsdos_ioctl is used to
  2566. +                     execute a msdos_unlink operation. The d_name and d_reclen
  2567. +                     fields are used.
  2568. +                     Return 0 if success.
  2569. +                 */
  2570. +                 dir->i_count++;
  2571. +                 ret = msdos_unlink (dir,data.dos_dirent.d_name
  2572. +                     ,data.dos_dirent.d_reclen);
  2573. +             }else if (cmd == UMSDOS_RMDIR_DOS){
  2574. +                 /* #Specification: ioctl / UMSDOS_RMDIR_DOS
  2575. +                     The dos_dirent field of the struct umsdos_ioctl is used to
  2576. +                     execute a msdos_unlink operation. The d_name and d_reclen
  2577. +                     fields are used.
  2578. +                     Return 0 if success.
  2579. +                 */
  2580. +                 dir->i_count++;
  2581. +                 ret = msdos_rmdir (dir,data.dos_dirent.d_name
  2582. +                     ,data.dos_dirent.d_reclen);
  2583. +             }else if (cmd == UMSDOS_STAT_DOS){
  2584. +                 /* #Specification: ioctl / UMSDOS_STAT_DOS
  2585. +                     The dos_dirent field of the struct umsdos_ioctl is
  2586. +                     used to execute a stat operation in the DOS directory.
  2587. +                     The d_name and d_reclen fields are used.
  2588. +                     The following field of umsdos_ioctl.stat are filled.
  2589. +                     st_ino,st_mode,st_size,st_atime,st_mtime,st_ctime,
  2590. +                     Return 0 if success.
  2591. +                 */
  2592. +                 struct inode *inode;
  2593. +                 ret = umsdos_real_lookup (dir,data.dos_dirent.d_name
  2594. +                     ,data.dos_dirent.d_reclen,&inode);
  2595. +                 if (ret == 0){
  2596. +                     data.stat.st_ino = inode->i_ino;
  2597. +                     data.stat.st_mode = inode->i_mode;
  2598. +                     data.stat.st_size = inode->i_size;
  2599. +                     data.stat.st_atime = inode->i_atime;
  2600. +                     data.stat.st_ctime = inode->i_ctime;
  2601. +                     data.stat.st_mtime = inode->i_mtime;
  2602. +                     memcpy_tofs (&idata->stat,&data.stat,sizeof(data.stat));
  2603. +                     iput (inode);
  2604. +                 }
  2605. +             }else if (cmd == UMSDOS_DOS_SETUP){
  2606. +                 /* #Specification: ioctl / UMSDOS_DOS_SETUP
  2607. +                     The UMSDOS_DOS_SETUP ioctl allow changing the
  2608. +                     default permission of the MsDOS file system driver
  2609. +                     on the fly. The MsDOS driver apply global permission
  2610. +                     to every file and directory. Normally these permissions
  2611. +                     are controlled by a mount option. This is not
  2612. +                     available for root partition, so a special utility
  2613. +                     (umssetup) is provided to do this, normally in
  2614. +                     /etc/rc.local.
  2615. +                     Be aware that this apply ONLY to MsDOS directory
  2616. +                     (those without EMD --linux-.---). Umsdos directory
  2617. +                     have independant (standard) permission for each
  2618. +                     and every file.
  2619. +                     The field umsdos_dirent provide the information needed.
  2620. +                     umsdos_dirent.uid and gid sets the owner and group.
  2621. +                     umsdos_dirent.mode set the permissions flags.
  2622. +                 */
  2623. +                 dir->i_sb->u.msdos_sb.fs_uid = data.umsdos_dirent.uid;
  2624. +                 dir->i_sb->u.msdos_sb.fs_gid = data.umsdos_dirent.gid;
  2625. +                 dir->i_sb->u.msdos_sb.fs_umask = data.umsdos_dirent.mode;
  2626. +                 ret = 0;
  2627. +             }
  2628. +         }
  2629. +     }
  2630. +     PRINTK (("ioctl return %d\n",ret));
  2631. +     return ret;
  2632. + }
  2633. diff -rc2P linux.1.1.12/fs/umsdos/mangle.c linux/fs/umsdos/mangle.c
  2634. *** linux.1.1.12/fs/umsdos/mangle.c
  2635. --- linux/fs/umsdos/mangle.c    Thu May 12 07:10:16 1994
  2636. ***************
  2637. *** 0 ****
  2638. --- 1,478 ----
  2639. + /*
  2640. +  *  linux/fs/umsdos/mangle.c
  2641. +  *
  2642. +  *    Written 1993 by Jacques Gelinas 
  2643. +  *
  2644. +  * Control the mangling of file name to fit msdos name space.
  2645. +  * Many optimisation by GLU == dglaude@is1.vub.ac.be (GLAUDE DAVID)
  2646. + */
  2647. + #include <linux/errno.h>
  2648. + #include <linux/ctype.h>
  2649. + #include <linux/string.h>
  2650. + #include <linux/kernel.h>
  2651. + #include <linux/umsdos_fs.h>
  2652. + /*
  2653. +     Complete the mangling of the MSDOS fake name
  2654. +     based on the position of the entry in the EMD file.
  2655. +     Simply complete the job of umsdos_parse; fill the extension.
  2656. +     Beware that info->f_pos must be set.
  2657. + */
  2658. + void umsdos_manglename (struct umsdos_info *info)
  2659. + {
  2660. +     if (info->msdos_reject){
  2661. +         /* #Specification: file name / non MSDOS conforming / mangling
  2662. +             Each non MSDOS conforming file has a special extension
  2663. +             build from the entry position in the EMD file.
  2664. +             This number is then transform in a base 32 number, where
  2665. +             each digit is expressed like hexadecimal number, using
  2666. +             digit and letter, except it uses 22 letters from 'a' to 'v'.
  2667. +             The number 32 comes from 2**5. It is faster to split a binary
  2668. +             number using a base which is a power of two. And I was 32
  2669. +             when I started this project. Pick your answer :-) .
  2670. +             If the result is '0', it is replace with '_', simply
  2671. +             to make it odd.
  2672. +             This is true for the first two character of the extension.
  2673. +             The last one is taken from a list of odd character, which
  2674. +             are:
  2675. +                 { } ( ) ! ` ^ & @
  2676. +             With this scheme, we can produce 9216 ( 9* 32 * 32)
  2677. +             different extensions which should not clash with any useful
  2678. +             extension already popular or meaningful. Since most directory
  2679. +             have much less than 32 * 32 files in it, the first character
  2680. +             of the extension of any mangle name will be {.
  2681. +             Here are the reason to do this (this kind of mangling).
  2682. +             -The mangling is deterministic. Just by the extension, we
  2683. +              are able to locate the entry in the EMD file.
  2684. +             -By keeping to beginning of the file name almost unchange,
  2685. +              we are helping the MSDOS user.
  2686. +             -The mangling produces names not too ugly, so an msdos user
  2687. +              may live with it (remember it, type it, etc...).
  2688. +             -The mangling produces names ugly enough so no one will
  2689. +              ever think of using such a name in real life. This is not
  2690. +              fool proof. I don't think there is a total solution to this.
  2691. +         */
  2692. +         union {
  2693. +             int entry_num;
  2694. +             struct {
  2695. +                 unsigned num1:5,num2:5,num3:5;
  2696. +             }num;
  2697. +         } u;
  2698. +         char *pt = info->fake.fname + info->fake.len;
  2699. +         /* lookup for encoding the last character of the extension */
  2700. +         /* It contain valid character after the ugly one to make sure */
  2701. +         /* even if someone overflow the 32 * 32 * 9 limit, it still do */
  2702. +         /* something */
  2703. +         #define SPECIAL_MANGLING '{','}','(',')','!','`','^','&','@'
  2704. +         static char lookup3[]={
  2705. +             SPECIAL_MANGLING,
  2706. +             /* This is the start of lookup12 */
  2707. +             '_','1','2','3','4','5','6','7','8','9',
  2708. +             'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
  2709. +             'p','q','r','s','t','u','v' 
  2710. +         };
  2711. +         #define lookup12 (lookup3+9)
  2712. +         u.entry_num = info->f_pos / UMSDOS_REC_SIZE;
  2713. +         if (u.entry_num > (9* 32 * 32)){
  2714. +             printk ("UMSDOS: More than 9216 file in a directory.\n"
  2715. +                 "This may break the mangling strategy.\n"
  2716. +                 "Not a killer problem. See doc.\n");
  2717. +         }
  2718. +         *pt++ = '.';
  2719. +         *pt++ = lookup3 [u.num.num3];
  2720. +         *pt++ = lookup12[u.num.num2];
  2721. +         *pt++ = lookup12[u.num.num1];
  2722. +         *pt = '\0';        /* help doing printk */    
  2723. +         info->fake.len += 4;
  2724. +         info->msdos_reject = 0;        /* Avoid mangling twice */
  2725. +     }
  2726. + }
  2727. + /*
  2728. +     Evaluate the record size needed to store of name of len character.
  2729. +     The value returned is a multiple of UMSDOS_REC_SIZE.
  2730. + */
  2731. + int umsdos_evalrecsize (int len)
  2732. + {
  2733. +     struct umsdos_dirent dirent;
  2734. +     int nbrec = 1+((len-1+(dirent.name-(char*)&dirent))
  2735. +                    / UMSDOS_REC_SIZE);
  2736. +     return nbrec * UMSDOS_REC_SIZE;
  2737. +     /*
  2738. +     GLU    This should be inlined or something to speed it up to the max.
  2739. +     GLU    nbrec is absolutely not needed to return the value.
  2740. +     */
  2741. + }
  2742. + #ifdef TEST
  2743. + int umsdos_evalrecsize_old (int len)
  2744. + {
  2745. +     struct umsdos_dirent dirent;
  2746. +     int size = len + (dirent.name-(char*)&dirent);
  2747. +     int nbrec = size / UMSDOS_REC_SIZE;
  2748. +     int extra = size % UMSDOS_REC_SIZE;
  2749. +     if (extra > 0) nbrec++;
  2750. +     return nbrec * UMSDOS_REC_SIZE;
  2751. + }
  2752. + #endif
  2753. + /*
  2754. +     Fill the struct info with the full and msdos name of a file
  2755. +     Return 0 if all is ok, a negative error code otherwise.
  2756. + */
  2757. + int umsdos_parse (
  2758. +     const char *fname,
  2759. +     int len,
  2760. +     struct umsdos_info *info)
  2761. + {
  2762. +     int ret = -ENAMETOOLONG;
  2763. +     /* #Specification: file name / too long
  2764. +         If a file name exceed UMSDOS maxima, the file name is silently
  2765. +         truncated. This makes it conformant with the other file system
  2766. +         of Linux (minix and ext2 at least).
  2767. +     */
  2768. +     if (len > UMSDOS_MAXNAME) len = UMSDOS_MAXNAME;
  2769. +     {
  2770. +         const char *firstpt=NULL;    /* First place we saw a . in fname */
  2771. +         /* #Specification: file name / non MSDOS conforming / base length 0
  2772. +             file name beginning with a period '.' are invalid for MsDOS.
  2773. +             It needs absolutly a base name. So the file name is mangled
  2774. +         */
  2775. +         int ivldchar = fname[0] == '.';/* At least one invalid character */
  2776. +         int msdos_len = len;
  2777. +         int base_len;
  2778. +         /*
  2779. +             cardinal_per_size tells if there exist at least one
  2780. +             DOS pseudo devices on length n. See the test below.
  2781. +         */
  2782. +         static const char cardinal_per_size[9]={
  2783. +             0, 0, 0, 1, 1, 0, 1, 0, 1
  2784. +         };
  2785. +         /*
  2786. +             lkp translate all character to acceptable character (for DOS).
  2787. +             When lkp[n] == n, it means also it is an acceptable one.
  2788. +             So it serve both as a flag and as a translator.
  2789. +         */
  2790. +         static char lkp[256];
  2791. +         static char is_init=0;
  2792. +         if (!is_init){
  2793. +             /*
  2794. +                 Initialisation of the array is easier and less error prone
  2795. +                 like this.
  2796. +             */
  2797. +             int i;
  2798. +             static char *spc = "\"*+,/:;<=>?[\\]|~";
  2799. +             is_init = 1;
  2800. +             for (i=0; i<=32; i++) lkp[i] = '#';
  2801. +             for (i=33; i<'A'; i++) lkp[i] = (char)i;
  2802. +             for (i='A'; i<='Z'; i++) lkp[i] = (char)(i+('a'-'A'));
  2803. +             for (i='Z'+1; i<127; i++) lkp[i] = (char)i;
  2804. +             for (i=128; i<256; i++) lkp[i] = '#';
  2805. +             lkp['.'] = '_';
  2806. +             while (*spc != '\0') lkp[(unsigned char)(*spc++)] = '#';
  2807. +         }
  2808. +         /*    GLU
  2809. +             file name wich are longer than 8+'.'+3 are invalid for MsDOS.
  2810. +             So the file name is to be mangled no more test needed.
  2811. +             This Speed Up for long and very long name.
  2812. +             The position of the last point is no more necessary anyway.
  2813. +         */
  2814. +         if (len<=(8+1+3)){
  2815. +             const char *pt = fname;
  2816. +             const char *endpt = fname + len;
  2817. +             while (pt < endpt){
  2818. +                 if (*pt == '.'){
  2819. +                     if (firstpt != NULL){
  2820. +                         /* 2 . in a file name. Reject */
  2821. +                         ivldchar = 1;
  2822. +                         break;
  2823. +                     }else{
  2824. +                         int extlen = (int)(endpt - pt);
  2825. +                         firstpt = pt;
  2826. +                         if (firstpt - fname > 8){
  2827. +                             /* base name longer than 8: reject */
  2828. +                             ivldchar = 1;
  2829. +                             break;
  2830. +                         }else if (extlen > 4){
  2831. +                             /* Extension longer than 4 (including .): reject */
  2832. +                             ivldchar = 1;
  2833. +                             break;
  2834. +                         }else if (extlen == 1){
  2835. +                             /* #Specification: file name / non MSDOS conforming / last char == .
  2836. +                                 If the last character of a file name is
  2837. +                                 a period, mangling is applied. MsDOS do
  2838. +                                 not support those file name.
  2839. +                             */
  2840. +                             ivldchar = 1;
  2841. +                             break;
  2842. +                         }else if (extlen == 4){
  2843. +                             /* #Specification: file name / non MSDOS conforming / mangling clash
  2844. +                                 To avoid clash with    the umsdos mangling, any file
  2845. +                                 with a special character as the first character
  2846. +                                 of the extension will be mangled. This solve the
  2847. +                                 following problem:
  2848. +                 
  2849. +                                 touch FILE
  2850. +                                 # FILE is invalid for DOS, so mangling is applied
  2851. +                                 # file.{_1 is created in the DOS directory
  2852. +                                 touch file.{_1
  2853. +                                 # To UMSDOS file point to a single DOS entry.
  2854. +                                 # So file.{_1 has to be mangled.
  2855. +                             */    
  2856. +                             static char special[]={
  2857. +                                 SPECIAL_MANGLING,'\0'
  2858. +                             };
  2859. +                             if (strchr(special,firstpt[1])!= NULL){
  2860. +                                 ivldchar = 1;
  2861. +                                 break;
  2862. +                             }
  2863. +                         }
  2864. +                     }
  2865. +                 }else if (lkp[(unsigned char)(*pt)] != *pt){
  2866. +                     ivldchar = 1;
  2867. +                     break;
  2868. +                 }
  2869. +                 pt++;
  2870. +             }
  2871. +         }else{
  2872. +             ivldchar = 1;
  2873. +         }
  2874. +         if (ivldchar
  2875. +             || (firstpt == NULL && len > 8)
  2876. +             || (len == UMSDOS_EMD_NAMELEN
  2877. +                 && memcmp(fname,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN)==0)){
  2878. +             /* #Specification: file name / --linux-.---
  2879. +                 The name of the EMD file --linux-.--- is map to a mangled
  2880. +                 name. So UMSDOS does not restrict its use.
  2881. +             */
  2882. +             /* #Specification: file name / non MSDOS conforming / mangling
  2883. +                 Non MSDOS conforming file name must use some alias to fit
  2884. +                 in the MSDOS name space.
  2885. +                 The strategy is simple. The name is simply truncated to
  2886. +                 8 char. points are replace with underscore and a
  2887. +                 number is given as an extension. This number correspond
  2888. +                 to the entry number in the EMD file. The EMD file
  2889. +                 only need to carry the real name.
  2890. +                 Upper case is also convert to lower case.
  2891. +                 Control character are converted to #.
  2892. +                 Space are converted to #.
  2893. +                 The following character are also converted to #.
  2894. +                     " * + , / : ; < = > ? [ \ ] | ~
  2895. +                 Sometime, the problem is not in MsDOS itself but in
  2896. +                 command.com.
  2897. +             */
  2898. +             int i;
  2899. +             char *pt = info->fake.fname;
  2900. +             base_len = msdos_len = (msdos_len>8) ? 8 : msdos_len;
  2901. +             /*
  2902. +                 There is no '.' any more so we know for a fact that
  2903. +                 the base lenght is the lenght.
  2904. +             */
  2905. +             memcpy (info->fake.fname,fname,msdos_len);
  2906. +             for (i=0; i<msdos_len; i++, pt++) *pt = lkp[(unsigned char)(*pt)];
  2907. +             *pt = '\0';    /* GLU    C'est sur on a un 0 a la fin */
  2908. +             info->msdos_reject = 1;
  2909. +             /*
  2910. +                 The numeric extension is added only when we know
  2911. +                 the position in the EMD file, in umsdos_newentry(),
  2912. +                 umsdos_delentry(), and umsdos_findentry().
  2913. +                 See umsdos_manglename().
  2914. +             */
  2915. +         }else{
  2916. +             /* Conforming MSDOS file name */
  2917. +             strcpy (info->fake.fname,fname);    /* GLU    C'est sur on a un 0 a la fin */
  2918. +             info->msdos_reject = 0;
  2919. +             base_len = firstpt != NULL ? (int)(firstpt - fname) : len;
  2920. +         }
  2921. +         if (cardinal_per_size[base_len]){
  2922. +             /* #Specification: file name / MSDOS devices / mangling
  2923. +                 To avoid unreachable file from MsDOS, any MsDOS conforming
  2924. +                 file with a basename equal to one of the MsDOS pseudo
  2925. +                 devices will be mangled.
  2926. +                 If a file such as "prn" was created, it would be unreachable
  2927. +                 under MsDOS because prn is assumed to be the printer, even
  2928. +                 if the file does have an extension.
  2929. +                 Since the extension is unimportant to MsDOS, we must patch
  2930. +                 the basename also. We simply insert a minus '-'. To avoid
  2931. +                 conflict with valid file with a minus in front (such as
  2932. +                 "-prn"), we add an mangled extension like any other
  2933. +                 mangled file name.
  2934. +                 Here is the list of DOS pseudo devices:
  2935. +                     "prn","con","aux","nul",
  2936. +                     "lpt1","lpt2","lpt3","lpt4",
  2937. +                     "com1","com2","com3","com4",
  2938. +                     "clock$"
  2939. +                 and some standard ones for common DOS programs
  2940. +                     "emmxxxx0","xmsxxxx0","setverxx"
  2941. +                 (Thanks to Chris Hall <CAH17@PHOENIX.CAMBRIDGE.AC.UK>
  2942. +                  for pointing these to me).
  2943. +                 Is there one missing ?
  2944. +             */
  2945. +             /* This table must be ordered by length */
  2946. +             static const char *tbdev[]={
  2947. +                 "prn","con","aux","nul",
  2948. +                 "lpt1","lpt2","lpt3","lpt4",
  2949. +                 "com1","com2","com3","com4",
  2950. +                 "clock$",
  2951. +                 "emmxxxx0","xmsxxxx0","setverxx"
  2952. +             };
  2953. +             /* Tell where to find in tbdev[], the first name of */
  2954. +             /* a certain length */
  2955. +             static const char start_ind_dev[9]={
  2956. +                 0, 0, 0, 4, 12, 12, 13, 13, 16 
  2957. +             };
  2958. +             char basen[9];
  2959. +             int i;
  2960. +             for (i=start_ind_dev[base_len-1]; i<start_ind_dev[base_len]; i++){
  2961. +                 if (memcmp(info->fake.fname,tbdev[i],base_len)==0){
  2962. +                     memcpy (basen,info->fake.fname,base_len);
  2963. +                     basen[base_len] = '\0';        /* GLU    C'est sur on a un 0 a la fin */
  2964. +                     /*
  2965. +                     GLU    On ne fait cela que si necessaire, on essaye d'etre le
  2966. +                     GLU    simple dans le cas general (le plus frequent).
  2967. +                     */
  2968. +                     info->fake.fname[0] = '-';
  2969. +                     strcpy (info->fake.fname+1,basen);    /* GLU    C'est sur on a un 0 a la fin */
  2970. +                     msdos_len = (base_len==8) ? 8 : base_len + 1;
  2971. +                     info->msdos_reject = 1;
  2972. +                     break;
  2973. +                 }
  2974. +             }
  2975. +         }
  2976. +         info->fake.fname[msdos_len] = '\0';    /* Help doing printk */
  2977. +         /* GLU    Ce zero devrais deja y etre ! (invariant ?) */
  2978. +         info->fake.len = msdos_len;
  2979. +         /* Pourquoi ne pas utiliser info->fake.len partout ??? plus long ?*/
  2980. +         memcpy (info->entry.name,fname,len);
  2981. +         info->entry.name_len = len;
  2982. +         ret = 0;
  2983. +     }
  2984. +     /*
  2985. +         Evaluate how many record are needed to store this entry.
  2986. +     */
  2987. +     info->recsize = umsdos_evalrecsize (len);
  2988. +     return ret;
  2989. + }
  2990. + #ifdef TEST
  2991. + struct MANG_TEST{
  2992. +     char *fname;        /* Name to validate */
  2993. +     int msdos_reject;    /* Expected msdos_reject flag */
  2994. +     char *msname;        /* Expected msdos name */
  2995. + };
  2996. + struct MANG_TEST tb[]={
  2997. +     "hello",        0,    "hello",
  2998. +     "hello.1",        0,    "hello.1",
  2999. +     "hello.1_",        0,    "hello.1_",
  3000. +     "prm",            0,    "prm",
  3001. + #ifdef PROPOSITION
  3002. +     "HELLO",        1,    "hello",
  3003. +     "Hello.1",        1,    "hello.1",
  3004. +     "Hello.c",        1,    "hello.c",
  3005. + #elseif
  3006. + /*
  3007. +     Je trouve les trois exemples ci-dessous tres "malheureux".
  3008. +     Je propose de mettre en minuscule dans un passe preliminaire,
  3009. +     et de tester apres si il y a d'autres caracters "mechants".
  3010. +     Bon, je ne l'ai pas fait, parceque ce n'est pas si facilement
  3011. +     modifiable que ca. Mais c'est pour le principe.
  3012. +     Evidemment cela augmente les chances de "Colision",
  3013. +     par exemple: entre "HELLO" et "Hello", mais ces problemes
  3014. +     peuvent etre traiter ailleur avec les autres colisions.
  3015. + */
  3016. +     "HELLO",        1,    "hello",
  3017. +     "Hello.1",        1,    "hello_1",
  3018. +     "Hello.c",        1,    "hello_c",
  3019. + #endif
  3020. +     "hello.{_1",        1,    "hello_{_",
  3021. +     "hello\t",        1,    "hello#",
  3022. +     "hello.1.1",        1,    "hello_1_",
  3023. +     "hel,lo",        1,    "hel#lo",
  3024. +     "Salut.Tu.vas.bien?",    1,    "salut_tu",
  3025. +     ".profile",        1,    "_profile",
  3026. +     ".xv",            1,    "_xv",
  3027. +     "toto.",        1,    "toto_",
  3028. +     "clock$.x",        1,    "-clock$",
  3029. +     "emmxxxx0",        1,    "-emmxxxx",
  3030. +     "emmxxxx0.abcd",    1,    "-emmxxxx",
  3031. +     "aux",            1,    "-aux",
  3032. +     "prn",            1,    "-prn",
  3033. +     "prn.abc",        1,    "-prn",
  3034. +     "PRN",            1,    "-prn",
  3035. + /* 
  3036. + GLU    ATTENTION : Le resultat de ceux-ci sont differents avec ma version
  3037. + GLU    du mangle par rapport au mangle originale.
  3038. + GLU    CAUSE: La maniere de calculer la variable baselen. 
  3039. + GLU        Pour toi c'est toujours 3
  3040. + GLU        Pour moi c'est respectivement 7, 8 et 8
  3041. + */
  3042. +     "PRN.abc",        1,    "prn_abc",
  3043. +     "Prn.abcd",        1,    "prn_abcd",
  3044. +     "prn.abcd",        1,    "prn_abcd",
  3045. +     "Prn.abcdefghij",    1,    "prn_abcd"
  3046. + };
  3047. + int main (int argc, char *argv[])
  3048. + {
  3049. +     int i,rold,rnew;
  3050. +     printf ("Testing the umsdos_parse.\n");
  3051. +     for (i=0; i<sizeof(tb)/sizeof(tb[0]); i++){
  3052. +         struct MANG_TEST *pttb = tb+i;
  3053. +         struct umsdos_info info;
  3054. +         int ok = umsdos_parse (pttb->fname,strlen(pttb->fname),&info);
  3055. +         if (strcmp(info.fake.fname,pttb->msname)!=0){
  3056. +             printf ("**** %s -> ",pttb->fname);
  3057. +             printf ("%s <> %s\n",info.fake.fname,pttb->msname);
  3058. +         }else if (info.msdos_reject != pttb->msdos_reject){
  3059. +             printf ("**** %s -> %s ",pttb->fname,pttb->msname);
  3060. +             printf ("%d <> %d\n",info.msdos_reject,pttb->msdos_reject);
  3061. +         }else{
  3062. +             printf ("     %s -> %s %d\n",pttb->fname,pttb->msname
  3063. +                 ,pttb->msdos_reject);
  3064. +         }
  3065. +     }
  3066. +     printf ("Testing the new umsdos_evalrecsize.");
  3067. +     for (i=0; i<UMSDOS_MAXNAME ; i++){
  3068. +         rnew=umsdos_evalrecsize (i);
  3069. +         rold=umsdos_evalrecsize_old (i);
  3070. +         if (!(i%UMSDOS_REC_SIZE)){
  3071. +             printf ("\n%d:\t",i);
  3072. +         }
  3073. +         if (rnew!=rold){
  3074. +             printf ("**** %d newres: %d != %d \n", i, rnew, rold);
  3075. +         }else{
  3076. +             printf(".");
  3077. +         }
  3078. +     }
  3079. +     printf ("\nEnd of Testing.\n");
  3080. +     return 0;
  3081. + }
  3082. + #endif
  3083. diff -rc2P linux.1.1.12/fs/umsdos/namei.c linux/fs/umsdos/namei.c
  3084. *** linux.1.1.12/fs/umsdos/namei.c
  3085. --- linux/fs/umsdos/namei.c    Fri May 20 23:30:18 1994
  3086. ***************
  3087. *** 0 ****
  3088. --- 1,992 ----
  3089. + /*
  3090. +  *  linux/fs/umsdos/namei.c
  3091. +  *
  3092. +  *    Written 1993 by Jacques Gelinas 
  3093. +  *    Inspired from linux/fs/msdos/... by Werner Almesberger
  3094. +  *
  3095. +  * Maintain and access the --linux alternate directory file.
  3096. + */
  3097. + #include <linux/errno.h>
  3098. + #include <linux/kernel.h>
  3099. + #include <linux/sched.h>
  3100. + #include <linux/types.h>
  3101. + #include <linux/fcntl.h>
  3102. + #include <linux/stat.h>
  3103. + #include <linux/string.h>
  3104. + #include <linux/msdos_fs.h>
  3105. + #include <linux/umsdos_fs.h>
  3106. + #include <linux/malloc.h>
  3107. + #define PRINTK(x)
  3108. + #define Printk(x)    printk x
  3109. + #if 1
  3110. + /*
  3111. +     Wait for creation exclusivity.
  3112. +     Return 0 if the dir was already available.
  3113. +     Return 1 if a wait was necessary.
  3114. +         When 1 is return, it means a wait was done. It does not
  3115. +         mean the directory is available.
  3116. + */
  3117. + static int umsdos_waitcreate(struct inode *dir)
  3118. + {
  3119. +     int ret = 0;
  3120. +     if (dir->u.umsdos_i.u.dir_info.creating
  3121. +         && dir->u.umsdos_i.u.dir_info.pid != current->pid){
  3122. +         sleep_on(&dir->u.umsdos_i.u.dir_info.p);
  3123. +         ret = 1;
  3124. +     }
  3125. +     return ret;
  3126. + }
  3127. + /*
  3128. +     Wait for any lookup process to finish
  3129. + */
  3130. + static void umsdos_waitlookup (struct inode *dir)
  3131. + {
  3132. +     while (dir->u.umsdos_i.u.dir_info.looking){
  3133. +         sleep_on(&dir->u.umsdos_i.u.dir_info.p);
  3134. +     }
  3135. + }
  3136. + /*
  3137. +     Lock all other process out of this directory.
  3138. + */
  3139. + void umsdos_lockcreate (struct inode *dir)
  3140. + {
  3141. +     /* #Specification: file creation / not atomic
  3142. +         File creation is a two step process. First we create (allocate)
  3143. +         an entry in the EMD file and then (using the entry offset) we
  3144. +         build a unique name for MSDOS. We create this name in the msdos
  3145. +         space.
  3146. +         We have to use semaphore (sleep_on/wake_up) to prevent lookup
  3147. +         into a directory when we create a file or directory and to
  3148. +         prevent creation while a lookup is going on. Since many lookup
  3149. +         may happen at the same time, the semaphore is a counter.
  3150. +         Only one creation is allowed at the same time. This protection
  3151. +         may not be necessary. The problem arise mainly when a lookup
  3152. +         or a readdir is done while a file is partially created. The
  3153. +         lookup process see that as a "normal" problem and silently
  3154. +         erase the file from the EMD file. Normal because a file
  3155. +         may be erased during a MSDOS session, but not removed from
  3156. +         the EMD file.
  3157. +         The locking is done on a directory per directory basis. Each
  3158. +         directory inode has its wait_queue.
  3159. +         For some operation like hard link, things even get worse. Many
  3160. +         creation must occur at once (atomic). To simplify the design
  3161. +         a process is allowed to recursivly lock the directory for
  3162. +         creation. The pid of the locking process is kept along with
  3163. +         a counter so a second level of locking is granted or not.
  3164. +     */
  3165. +     /*
  3166. +         Wait for any creation process to finish except
  3167. +         if we (the process) own the lock
  3168. +     */
  3169. +     while (umsdos_waitcreate(dir)!=0);
  3170. +     dir->u.umsdos_i.u.dir_info.creating++;
  3171. +     dir->u.umsdos_i.u.dir_info.pid = current->pid;
  3172. +     umsdos_waitlookup (dir);
  3173. + }
  3174. + /*
  3175. +     Lock all other process out of those two directories.
  3176. + */
  3177. + static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2)
  3178. + {
  3179. +     /*
  3180. +         We must check that both directory are available before
  3181. +         locking anyone of them. This is to avoid some deadlock.
  3182. +         Thanks to dglaude@is1.vub.ac.be (GLAUDE DAVID) for pointing
  3183. +         this to me.
  3184. +     */
  3185. +     while (1){
  3186. +         if (umsdos_waitcreate(dir1)==0
  3187. +             && umsdos_waitcreate(dir2)==0){
  3188. +             /* We own both now */
  3189. +             dir1->u.umsdos_i.u.dir_info.creating++;
  3190. +             dir1->u.umsdos_i.u.dir_info.pid = current->pid;
  3191. +             dir2->u.umsdos_i.u.dir_info.creating++;
  3192. +             dir2->u.umsdos_i.u.dir_info.pid = current->pid;
  3193. +             break;
  3194. +         }
  3195. +     }
  3196. +     umsdos_waitlookup(dir1);
  3197. +     umsdos_waitlookup(dir2);
  3198. + }
  3199. + /*
  3200. +     Wait until creation is finish in this directory.
  3201. + */
  3202. + void umsdos_startlookup (struct inode *dir)
  3203. + {
  3204. +     while (umsdos_waitcreate (dir) != 0);
  3205. +     dir->u.umsdos_i.u.dir_info.looking++;
  3206. + }
  3207. + void check_page_tables(void);
  3208. + /*
  3209. +     Unlock the directory.
  3210. + */
  3211. + void umsdos_unlockcreate (struct inode *dir)
  3212. + {
  3213. +     dir->u.umsdos_i.u.dir_info.creating--;
  3214. +     if (dir->u.umsdos_i.u.dir_info.creating < 0){
  3215. +         printk ("UMSDOS: dir->u.umsdos_i.u.dir_info.creating < 0: %d"
  3216. +             ,dir->u.umsdos_i.u.dir_info.creating);
  3217. +     }
  3218. +     wake_up (&dir->u.umsdos_i.u.dir_info.p);
  3219. + }
  3220. + /*
  3221. +     Tell directory lookup is over.
  3222. + */
  3223. + void umsdos_endlookup (struct inode *dir)
  3224. + {
  3225. +     dir->u.umsdos_i.u.dir_info.looking--;
  3226. +     if (dir->u.umsdos_i.u.dir_info.looking < 0){
  3227. +         printk ("UMSDOS: dir->u.umsdos_i.u.dir_info.looking < 0: %d"
  3228. +             ,dir->u.umsdos_i.u.dir_info.looking);
  3229. +     }
  3230. +     wake_up (&dir->u.umsdos_i.u.dir_info.p);
  3231. + }
  3232. + #else
  3233. + static void umsdos_lockcreate (struct inode *dir){}
  3234. + static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2){}
  3235. + void umsdos_startlookup (struct inode *dir){}
  3236. + static void umsdos_unlockcreate (struct inode *dir){}
  3237. + void umsdos_endlookup (struct inode *dir){}
  3238. + #endif
  3239. + static int umsdos_nevercreat(
  3240. +     struct inode *dir,
  3241. +     const char *name,        /* Name of the file to add */
  3242. +     int len,
  3243. +     int errcod)                /* Length of the name */
  3244. + {
  3245. +     int ret = 0;
  3246. +     if (umsdos_is_pseudodos(dir,name,len)){
  3247. +         /* #Specification: pseudo root / any file creation /DOS
  3248. +             The pseudo sub-directory /DOS can't be created!
  3249. +             EEXIST is returned.
  3250. +             The pseudo sub-directory /DOS can't be removed!
  3251. +             EPERM is returned.
  3252. +         */
  3253. +         ret = -EPERM;
  3254. +         ret = errcod;
  3255. +     }else if (name[0] == '.'
  3256. +         && (len == 1 || (len == 2 && name[1] == '.'))){
  3257. +         /* #Specification: create / . and ..
  3258. +             If one try to creates . or .., it always fail and return
  3259. +             EEXIST.
  3260. +             If one try to delete . or .., it always fail and return
  3261. +             EPERM.
  3262. +             This should be test at the VFS layer level to avoid
  3263. +             duplicating this in all file systems. Any comments ?
  3264. +         */
  3265. +         ret = errcod;
  3266. +     }
  3267. +     return ret;
  3268. + }
  3269. +     
  3270. + /*
  3271. +     Add a new file (ordinary or special) into the alternate directory.
  3272. +     The file is added to the real MSDOS directory. If successfull, it
  3273. +     is then added to the EDM file.
  3274. +     Return the status of the operation. 0 mean success.
  3275. + */
  3276. + static int umsdos_create_any (
  3277. +     struct inode *dir,
  3278. +     const char *name,        /* Name of the file to add */
  3279. +     int len,                /* Length of the name */
  3280. +     int mode,                /* Permission bit + file type ??? */
  3281. +     int rdev,                /* major, minor or 0 for ordinary file */
  3282. +                             /* and symlinks */
  3283. +     char flags,
  3284. +     struct inode **result)    /* Will hold the inode of the newly created */
  3285. +                             /* file */
  3286. + {
  3287. +     int ret = umsdos_nevercreat(dir,name,len,-EEXIST);
  3288. +     if (ret == 0){
  3289. +         struct umsdos_info info;
  3290. +         ret = umsdos_parse (name,len,&info);
  3291. +         *result = NULL;
  3292. +         if (ret == 0){
  3293. +             info.entry.mode = mode;
  3294. +             info.entry.rdev = rdev;
  3295. +             info.entry.flags = flags;
  3296. +             info.entry.uid = current->euid;
  3297. +             info.entry.gid = (dir->i_mode & S_ISGID)
  3298. +                 ? dir->i_gid : current->egid;
  3299. +             info.entry.ctime = info.entry.atime = info.entry.mtime
  3300. +                 = CURRENT_TIME;
  3301. +             info.entry.nlink = 1;
  3302. +             umsdos_lockcreate(dir);
  3303. +             ret = umsdos_newentry (dir,&info);
  3304. +             if (ret == 0){
  3305. +                 dir->i_count++;
  3306. +                 ret = msdos_create (dir,info.fake.fname,info.fake.len
  3307. +                     ,S_IFREG|0777,result);
  3308. +                 if (ret == 0){
  3309. +                     struct inode *inode = *result;
  3310. +                     umsdos_lookup_patch (dir,inode,&info.entry,info.f_pos);
  3311. +                     PRINTK (("inode %p[%d] ",inode,inode->i_count));
  3312. +                     PRINTK (("Creation OK: [%d] %s %d pos %d\n",dir->i_ino
  3313. +                         ,info.fake.fname,current->pid,info.f_pos));
  3314. +                 }else{
  3315. +                     /* #Specification: create / file exist in DOS
  3316. +                         Here is a situation. Trying to create a file with
  3317. +                         UMSDOS. The file is unknown to UMSDOS but already
  3318. +                         exist in the DOS directory.
  3319. +                         Here is what we are NOT doing:
  3320. +                         We could silently assume that everything is fine
  3321. +                         and allows the creation to succeed.
  3322. +                         It is possible not all files in the partition
  3323. +                         are mean to be visible from linux. By trying to create
  3324. +                         those file in some directory, one user may get access
  3325. +                         to those file without proper permissions. Looks like
  3326. +                         a security hole to me. Off course sharing a file system
  3327. +                         with DOS is some kind of security hole :-)
  3328. +                         So ?
  3329. +                         We return EEXIST in this case.
  3330. +                         The same is true for directory creation.
  3331. +                     */
  3332. +                     if (ret == -EEXIST){
  3333. +                         printk ("UMSDOS: out of sync, Creation error [%ld], "
  3334. +                             "deleting %s %d %d pos %ld\n",dir->i_ino
  3335. +                             ,info.fake.fname,-ret,current->pid,info.f_pos);
  3336. +                     }
  3337. +                     umsdos_delentry (dir,&info,0);
  3338. +                 }
  3339. +                 PRINTK (("umsdos_create %s ret = %d pos %d\n"
  3340. +                     ,info.fake.fname,ret,info.f_pos));
  3341. +             }
  3342. +             umsdos_unlockcreate(dir);
  3343. +         }
  3344. +     }
  3345. +     iput (dir);
  3346. +     return ret;
  3347. + }
  3348. + /*
  3349. +     Initialise the new_entry from the old for a rename operation.
  3350. +     (Only useful for umsdos_rename_f() below).
  3351. + */
  3352. + static void umsdos_ren_init(
  3353. +     struct umsdos_info *new_info,
  3354. +     struct umsdos_info *old_info,
  3355. +     int flags)        /* 0 == copy flags from old_name */
  3356. +                     /* != 0, this is the value of flags */
  3357. + {
  3358. +     new_info->entry.mode = old_info->entry.mode;
  3359. +     new_info->entry.rdev = old_info->entry.rdev;
  3360. +     new_info->entry.uid = old_info->entry.uid;
  3361. +     new_info->entry.gid = old_info->entry.gid;
  3362. +     new_info->entry.ctime = old_info->entry.ctime;
  3363. +     new_info->entry.atime = old_info->entry.atime;
  3364. +     new_info->entry.mtime = old_info->entry.mtime;
  3365. +     new_info->entry.flags = flags ? flags : old_info->entry.flags;
  3366. +     new_info->entry.nlink = old_info->entry.nlink;
  3367. + }
  3368. + /*
  3369. +     Rename a file (move) in the file system.
  3370. + */
  3371. + static int umsdos_rename_f(
  3372. +     struct inode * old_dir,
  3373. +     const char * old_name,
  3374. +     int old_len,
  3375. +     struct inode * new_dir,
  3376. +     const char * new_name,
  3377. +     int new_len,
  3378. +     int flags)        /* 0 == copy flags from old_name */
  3379. +                     /* != 0, this is the value of flags */
  3380. + {
  3381. +     int ret = EPERM;
  3382. +     struct umsdos_info old_info;
  3383. +     int old_ret = umsdos_parse (old_name,old_len,&old_info);
  3384. +     struct umsdos_info new_info;
  3385. +     int new_ret = umsdos_parse (new_name,new_len,&new_info);
  3386. +     PRINTK (("umsdos_rename %d %d ",old_ret,new_ret));
  3387. +     if (old_ret == 0 && new_ret == 0){
  3388. +         umsdos_lockcreate2(old_dir,new_dir);
  3389. +         PRINTK (("old findentry "));
  3390. +         ret = umsdos_findentry(old_dir,&old_info,0);
  3391. +         PRINTK (("ret %d ",ret));
  3392. +         if (ret == 0){
  3393. +             PRINTK (("new newentry "));
  3394. +             umsdos_ren_init(&new_info,&old_info,flags);
  3395. +             ret = umsdos_newentry (new_dir,&new_info);
  3396. +             PRINTK (("ret %d %d ",ret,new_info.fake.len));
  3397. +             if (ret == -EEXIST){
  3398. +                 /* #Specification: rename / new name exist
  3399. +                     If the destination name already exist, it will
  3400. +                     silently be removed. EXT2 does it this way
  3401. +                     and this is the spec of SUNOS. So does UMSDOS.
  3402. +                     If the destination is an empty directory it will
  3403. +                     also be removed.
  3404. +                 */
  3405. +                 /* This is not super efficient but should work */
  3406. +                 new_dir->i_count++;
  3407. +                 ret = UMSDOS_unlink (new_dir,new_name,new_len);
  3408. +                 PRINTK (("rename unlink ret %d %d -- ",ret,new_len));
  3409. +                 if (ret == -EISDIR){
  3410. +                     new_dir->i_count++;
  3411. +                     ret = UMSDOS_rmdir (new_dir,new_name,new_len);
  3412. +                     PRINTK (("rename rmdir ret %d -- ",ret));
  3413. +                 }
  3414. +                 if (ret == 0){
  3415. +                     /*
  3416. +                         The last umsdos_newentry had a side effect.
  3417. +                         new_info was filled with information from the
  3418. +                         existing entry (the one we just deleted).
  3419. +                     */
  3420. +                     umsdos_parse (new_name,new_len,&new_info);
  3421. +                     umsdos_ren_init(&new_info,&old_info,flags);
  3422. +                     ret = umsdos_newentry (new_dir,&new_info);
  3423. +                 }
  3424. +             }
  3425. +             if (ret == 0){
  3426. +                 PRINTK (("msdos_rename "));
  3427. +                 old_dir->i_count++;
  3428. +                 new_dir->i_count++;    /* Both inode are needed later */
  3429. +                 ret = msdos_rename (old_dir
  3430. +                     ,old_info.fake.fname,old_info.fake.len
  3431. +                     ,new_dir
  3432. +                     ,new_info.fake.fname,new_info.fake.len);
  3433. +                 PRINTK (("after m_rename ret %d ",ret));
  3434. +                 if (ret != 0){
  3435. +                     umsdos_delentry (new_dir,&new_info
  3436. +                         ,S_ISDIR(new_info.entry.mode));
  3437. +                 }else{
  3438. +                     ret = umsdos_delentry (old_dir,&old_info
  3439. +                         ,S_ISDIR(old_info.entry.mode));
  3440. +                     if (ret == 0){
  3441. +                         /*
  3442. +                             This UMSDOS_lookup does not look very useful.
  3443. +                             It makes sure that the inode of the file will
  3444. +                             be correctly setup (umsdos_patch_inode()) in
  3445. +                             case it is already in use.
  3446. +                             Not very efficient ...
  3447. +                         */
  3448. +                         struct inode *inode;
  3449. +                         new_dir->i_count++;
  3450. +                         PRINTK (("rename lookup len %d %d -- ",new_len,new_info.entry.flags));
  3451. +                         ret = UMSDOS_lookup (new_dir,new_name,new_len
  3452. +                             ,&inode);
  3453. +                         if (ret != 0){
  3454. +                             printk ("UMSDOS: partial rename for file %s\n"
  3455. +                                 ,new_info.entry.name);
  3456. +                         }else{
  3457. +                             /*
  3458. +                                 Update f_pos so notify_change will succeed
  3459. +                                 if the file was already in use.
  3460. +                             */
  3461. +                             umsdos_set_dirinfo (inode,new_dir,new_info.f_pos);
  3462. +                             iput (inode);
  3463. +                         }
  3464. +                     }
  3465. +                 }
  3466. +             }
  3467. +         }
  3468. +         umsdos_unlockcreate(old_dir);
  3469. +         umsdos_unlockcreate(new_dir);
  3470. +     }
  3471. +     iput (old_dir);
  3472. +     iput (new_dir);
  3473. +     PRINTK (("\n"));
  3474. +     return ret;
  3475. + }
  3476. + /*
  3477. +     Setup un Symbolic link or a (pseudo) hard link
  3478. +     Return a negative error code or 0 if ok.
  3479. + */
  3480. + static int umsdos_symlink_x(
  3481. +     struct inode * dir,
  3482. +     const char * name,
  3483. +     int len,
  3484. +     const char * symname,    /* name will point to this path */
  3485. +     int mode,
  3486. +     char flags)
  3487. + {
  3488. +     /* #Specification: symbolic links / strategy
  3489. +         A symbolic link is simply a file which hold a path. It is
  3490. +         implemented as a normal MSDOS file (not very space efficient :-()
  3491. +         I see 2 different way to do it. One is to place the link data
  3492. +         in unused entry of the EMD file. The other is to have a separate
  3493. +         file dedicated to hold all symbolic links data.
  3494. +         Lets go for simplicity...
  3495. +     */
  3496. +     struct inode *inode;
  3497. +     int ret;
  3498. +     dir->i_count++;        /* We keep the inode in case we need it */
  3499. +                         /* later */
  3500. +     ret = umsdos_create_any (dir,name,len,mode,0,flags,&inode);
  3501. +     PRINTK (("umsdos_symlink ret %d ",ret));
  3502. +     if (ret == 0){
  3503. +         int len = strlen(symname);
  3504. +         struct file filp;
  3505. +         filp.f_pos = 0;
  3506. +         /* Make the inode acceptable to MSDOS */
  3507. +         ret = msdos_file_write_kmem (inode,&filp,(char*)symname,len);
  3508. +         iput (inode);
  3509. +         if (ret >= 0){
  3510. +             if (ret != len){
  3511. +                 ret = -EIO;
  3512. +                 printk ("UMSDOS: "
  3513. +                     "Can't write symbolic link data\n");
  3514. +             }else{
  3515. +                 ret = 0;
  3516. +             }
  3517. +         }
  3518. +         if (ret != 0){
  3519. +             UMSDOS_unlink (dir,name,len);
  3520. +             dir = NULL;
  3521. +         }
  3522. +     }
  3523. +     iput (dir);
  3524. +     PRINTK (("\n"));
  3525. +     return ret;
  3526. + }
  3527. + /*
  3528. +     Setup un Symbolic link.
  3529. +     Return a negative error code or 0 if ok.
  3530. + */
  3531. + int UMSDOS_symlink(
  3532. +     struct inode * dir,
  3533. +     const char * name,
  3534. +     int len,
  3535. +     const char * symname)    /* name will point to this path */
  3536. + {
  3537. +     return umsdos_symlink_x (dir,name,len,symname,S_IFLNK|0777,0);
  3538. + }
  3539. + /*
  3540. +     Add a link to an inode in a directory
  3541. + */
  3542. + int UMSDOS_link (
  3543. +     struct inode * oldinode,
  3544. +     struct inode * dir,
  3545. +     const char * name,
  3546. +     int len)
  3547. + {
  3548. +     /* #Specification: hard link / strategy
  3549. +         Well ... hard link are difficult to implement on top of an
  3550. +         MsDOS fat file system. Unlike UNIX file systems, there are no
  3551. +         inode. A directory entry hold the functionnality of the inode
  3552. +         and the entry.
  3553. +         We will used the same strategy as a normal Unix file system
  3554. +         (with inode) except we will do it symbolicly (using paths).
  3555. +         Because anything can happen during a DOS session (defragment,
  3556. +         directory sorting, etc...), we can't rely on MsDOS pseudo
  3557. +         inode number to record the link. For this reason, the link
  3558. +         will be done using hidden symbolic links. The following
  3559. +         scenario illustrate how it work.
  3560. +         
  3561. +         Given a file /foo/file
  3562. +             ln /foo/file /tmp/file2
  3563. +             become internally
  3564. +             mv /foo/file /foo/-LINK1
  3565. +             ln -s /foo/-LINK1 /foo/file
  3566. +             ln -s /foo/-LINK1 /tmp/file2
  3567. +         Using this strategy, we can operate on /foo/file or /foo/file2.
  3568. +         We can remove one and keep the other, like a normal Unix hard link.
  3569. +         We can rename /foo/file ou /tmp/file2 independantly.
  3570. +             
  3571. +         The entry -LINK1 will be hidden. It will hold a link count.
  3572. +         When all link are erased, the hidden file is erased too.
  3573. +     */
  3574. +     /* #Specification: weakness / hard link
  3575. +         The strategy for hard link introduces a side effect that
  3576. +         may or may not be acceptable. Here is the sequence
  3577. +         mkdir subdir1
  3578. +         touch subdir1/file
  3579. +         mkdir subdir2
  3580. +         ln    subdir1/file subdir2/file
  3581. +         rm    subdir1/file
  3582. +         rmdir subdir1
  3583. +         rmdir: subdir1: Directory not empty
  3584. +         This happen because there is an invisible file (--link) in
  3585. +         subdir1 which is referenced by subdir2/file.
  3586. +         Any idea ?
  3587. +     */
  3588. +     /* #Specification: weakness / hard link / rename directory
  3589. +         Another weakness of hard link come from the fact that
  3590. +         it is based on hidden symbolic links. Here is an example.
  3591. +         mkdir /subdir1
  3592. +         touch /subdir1/file
  3593. +         mkdir /subdir2
  3594. +         ln    /subdir1/file subdir2/file
  3595. +         mv    /subdir1 subdir3
  3596. +         ls -l /subdir2/file
  3597. +         Since /subdir2/file is a hidden symbolic link
  3598. +         to /subdir1/..hlinkNNN, accessing it will fail since
  3599. +         /subdir1 does not exist anymore (has been renamed).
  3600. +     */
  3601. +     int ret = 0;
  3602. +     if (S_ISDIR(oldinode->i_mode)){
  3603. +         /* #Specification: hard link / directory
  3604. +             A hard link can't be made on a directory. EPERM is returned
  3605. +             in this case.
  3606. +         */
  3607. +         ret = -EPERM;
  3608. +     }else if ((ret = umsdos_nevercreat(dir,name,len,-EPERM))==0){
  3609. +         struct inode *olddir;
  3610. +         ret = umsdos_get_dirowner(oldinode,&olddir);
  3611. +         PRINTK (("umsdos_link dir_owner = %d -> %p [%d] "
  3612. +             ,oldinode->u.umsdos_i.i_dir_owner,olddir,olddir->i_count));
  3613. +         if (ret == 0){
  3614. +             struct umsdos_dirent entry;
  3615. +             umsdos_lockcreate2(dir,olddir);
  3616. +             ret = umsdos_inode2entry (olddir,oldinode,&entry);
  3617. +             if (ret == 0){
  3618. +                 PRINTK (("umsdos_link :%s: ino %d flags %d "
  3619. +                     ,entry.name
  3620. +                     ,oldinode->i_ino,entry.flags));
  3621. +                 if (!(entry.flags & UMSDOS_HIDDEN)){
  3622. +                     /* #Specification: hard link / first hard link
  3623. +                         The first time a hard link is done on a file, this
  3624. +                         file must be renamed and hidden. Then an internal
  3625. +                         simbolic link must be done on the hidden file.
  3626. +                         The second link is done after on this hidden file.
  3627. +                         It is expected that the Linux MSDOS file system
  3628. +                         keeps the same pseudo inode when a rename operation
  3629. +                         is done on a file in the same directory.
  3630. +                     */
  3631. +                     struct umsdos_info info;
  3632. +                     ret = umsdos_newhidden (olddir,&info);
  3633. +                     if (ret == 0){
  3634. +                         olddir->i_count+=2;
  3635. +                         PRINTK (("olddir[%d] ",olddir->i_count));
  3636. +                         ret = umsdos_rename_f (olddir,entry.name
  3637. +                             ,entry.name_len
  3638. +                             ,olddir,info.entry.name,info.entry.name_len
  3639. +                             ,UMSDOS_HIDDEN);
  3640. +                         if (ret == 0){
  3641. +                             char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
  3642. +                             if (path == NULL){
  3643. +                                 ret = -ENOMEM;
  3644. +                             }else{
  3645. +                                 PRINTK (("olddir[%d] ",olddir->i_count));
  3646. +                                 ret = umsdos_locate_path (oldinode,path);
  3647. +                                 PRINTK (("olddir[%d] ",olddir->i_count));
  3648. +                                 if (ret == 0){
  3649. +                                     olddir->i_count++;
  3650. +                                     ret = umsdos_symlink_x (olddir
  3651. +                                         ,entry.name
  3652. +                                         ,entry.name_len,path
  3653. +                                         ,S_IFREG|0777,UMSDOS_HLINK);
  3654. +                                     if (ret == 0){
  3655. +                                         dir->i_count++;
  3656. +                                         ret = umsdos_symlink_x (dir,name,len
  3657. +                                             ,path
  3658. +                                             ,S_IFREG|0777,UMSDOS_HLINK);
  3659. +                                     }
  3660. +                                 }
  3661. +                                 kfree (path);
  3662. +                             }
  3663. +                         }
  3664. +                     }
  3665. +                 }else{
  3666. +                     char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
  3667. +                     if (path == NULL){
  3668. +                         ret = -ENOMEM;
  3669. +                     }else{
  3670. +                         ret = umsdos_locate_path (oldinode,path);
  3671. +                         if (ret == 0){
  3672. +                             dir->i_count++;
  3673. +                             ret = umsdos_symlink_x (dir,name,len,path
  3674. +                                             ,S_IFREG|0777,UMSDOS_HLINK);
  3675. +                         }
  3676. +                         kfree (path);
  3677. +                     }
  3678. +                 }
  3679. +             }
  3680. +             umsdos_unlockcreate(olddir);
  3681. +             umsdos_unlockcreate(dir);
  3682. +         }
  3683. +         iput (olddir);
  3684. +     }
  3685. +     if (ret == 0){
  3686. +         oldinode->i_nlink++;
  3687. +         ret = UMSDOS_notify_change (0,oldinode);
  3688. +     }
  3689. +     iput (oldinode);
  3690. +     iput (dir);
  3691. +     PRINTK (("umsdos_link %d\n",ret));
  3692. +     return ret;
  3693. + }
  3694. + /*
  3695. +     Add a new file into the alternate directory.
  3696. +     The file is added to the real MSDOS directory. If successfull, it
  3697. +     is then added to the EDM file.
  3698. +     Return the status of the operation. 0 mean success.
  3699. + */
  3700. + int UMSDOS_create (
  3701. +     struct inode *dir,
  3702. +     const char *name,        /* Name of the file to add */
  3703. +     int len,                /* Length of the name */
  3704. +     int mode,                /* Permission bit + file type ??? */
  3705. +     struct inode **result)    /* Will hold the inode of the newly created */
  3706. +                             /* file */
  3707. + {
  3708. +     return umsdos_create_any (dir,name,len,mode,0,0,result);
  3709. + }
  3710. + /*
  3711. +     Add a sub-directory in a directory
  3712. + */
  3713. + int UMSDOS_mkdir(
  3714. +     struct inode * dir,
  3715. +     const char * name,
  3716. +     int len,
  3717. +     int mode)
  3718. + {
  3719. +     int ret = umsdos_nevercreat(dir,name,len,-EEXIST);
  3720. +     if (ret == 0){
  3721. +         struct umsdos_info info;
  3722. +         ret = umsdos_parse (name,len,&info);
  3723. +         PRINTK (("umsdos_mkdir %d\n",ret));
  3724. +         if (ret == 0){
  3725. +             info.entry.mode = mode | S_IFDIR;
  3726. +             info.entry.rdev = 0;
  3727. +             info.entry.uid = current->euid;
  3728. +             info.entry.gid = (dir->i_mode & S_ISGID)
  3729. +                 ? dir->i_gid : current->egid;
  3730. +             info.entry.ctime = info.entry.atime = info.entry.mtime
  3731. +                 = CURRENT_TIME;
  3732. +             info.entry.flags = 0;
  3733. +             umsdos_lockcreate(dir);
  3734. +             info.entry.nlink = 1;
  3735. +             ret = umsdos_newentry (dir,&info);
  3736. +             PRINTK (("newentry %d ",ret));
  3737. +             if (ret == 0){
  3738. +                 dir->i_count++;
  3739. +                 ret = msdos_mkdir (dir,info.fake.fname,info.fake.len,mode);
  3740. +                 if (ret != 0){
  3741. +                     umsdos_delentry (dir,&info,1);
  3742. +                     /* #Specification: mkdir / Directory already exist in DOS
  3743. +                         We do the same thing as for file creation.
  3744. +                         For all user it is an error.
  3745. +                     */
  3746. +                 }else{
  3747. +                     /* #Specification: mkdir / umsdos directory / create EMD
  3748. +                         When we created a new sub-directory in a UMSDOS
  3749. +                         directory (one with full UMSDOS semantic), we
  3750. +                         create immediatly an EMD file in the new
  3751. +                         sub-directory so it inherit UMSDOS semantic.
  3752. +                     */
  3753. +                     struct inode *subdir;
  3754. +                     ret = umsdos_real_lookup (dir,info.fake.fname
  3755. +                         ,info.fake.len,&subdir);
  3756. +                     if (ret == 0){
  3757. +                         struct inode *result;
  3758. +                         ret = msdos_create (subdir,UMSDOS_EMD_FILE
  3759. +                             ,UMSDOS_EMD_NAMELEN,S_IFREG|0777,&result);
  3760. +                         subdir = NULL;
  3761. +                         iput (result);
  3762. +                     }
  3763. +                     if (ret < 0){
  3764. +                         printk ("UMSDOS: Can't create empty --linux-.---\n");
  3765. +                     }
  3766. +                     iput (subdir);
  3767. +                 }
  3768. +             }
  3769. +             umsdos_unlockcreate(dir);
  3770. +         }
  3771. +     }
  3772. +     PRINTK (("umsdos_mkdir %d\n",ret));
  3773. +     iput (dir);
  3774. +     return ret;
  3775. + }
  3776. + /*
  3777. +     Add a new device special file into a directory.
  3778. + */
  3779. + int UMSDOS_mknod(
  3780. +     struct inode * dir,
  3781. +     const char * name,
  3782. +     int len,
  3783. +     int mode,
  3784. +     int rdev)
  3785. + {
  3786. +     /* #Specification: Special files / strategy
  3787. +         Device special file, pipes, etc ... are created like normal
  3788. +         file in the msdos file system. Of course they remain empty.
  3789. +         One strategy was to create thoses files only in the EMD file
  3790. +         since they were not important for MSDOS. The problem with
  3791. +         that, is that there were not getting inode number allocated.
  3792. +         The MSDOS filesystems is playing a nice game to fake inode
  3793. +         number, so why not use it.
  3794. +         The absence of inode number compatible with those allocated
  3795. +         for ordinary files was causing major trouble with hard link
  3796. +         in particular and other parts of the kernel I guess.
  3797. +     */
  3798. +     struct inode *inode;
  3799. +     int ret = umsdos_create_any (dir,name,len,mode,rdev,0,&inode);
  3800. +     iput (inode);
  3801. +     return ret;
  3802. + }
  3803. + /*
  3804. +     Remove a sub-directory.
  3805. + */
  3806. + int UMSDOS_rmdir(
  3807. +     struct inode * dir,
  3808. +     const char * name,
  3809. +     int len)
  3810. + {
  3811. +     /* #Specification: style / iput strategy
  3812. +         In the UMSDOS project, I am trying to apply a single
  3813. +         programming style regarding inode management. Many
  3814. +         entry point are receiving an inode to act on, and must
  3815. +         do an iput() as soon as they are finished with
  3816. +         the inode.
  3817. +         For simple case, there is no problem. When you introduce
  3818. +         error checking, you end up with many iput placed around the
  3819. +         code.
  3820. +         The coding style I use all around is one where I am trying
  3821. +         to provide independant flow logic (I don't know how to
  3822. +         name this). With this style, code is easier to understand
  3823. +         but you rapidly get iput() all around. Here is an exemple
  3824. +         of what I am trying to avoid.
  3825. +         if (a){
  3826. +             ...
  3827. +             if(b){
  3828. +                 ...
  3829. +             }
  3830. +             ...
  3831. +             if (c){
  3832. +                 // Complexe state. Was b true ? 
  3833. +                 ...
  3834. +             }
  3835. +             ...
  3836. +         }
  3837. +         // Weird state
  3838. +         if (d){
  3839. +             // ...
  3840. +         }
  3841. +         // Was iput finally done ?
  3842. +         return status;
  3843. +         Here is the style I am using. Still sometime I do the
  3844. +         first when things are very simple (or very complicated :-( )
  3845. +         if (a){
  3846. +             if (b){
  3847. +                 ...
  3848. +             }else if (c){
  3849. +                 // A single state gets here
  3850. +             }
  3851. +         }else if (d){
  3852. +             ...
  3853. +         }
  3854. +         return status;
  3855. +         Again, while this help clarifying the code, I often get a lot
  3856. +         of iput(), unlike the first style, where I can place few 
  3857. +         "strategic" iput(). "strategic" also mean, more difficult
  3858. +         to place.
  3859. +         So here is the style I will be using from now on in this project.
  3860. +         There is always an iput() at the end of a function (which has
  3861. +         to do an iput()). One iput by inode. There is also one iput()
  3862. +         at the places where a successful operation is achieved. This
  3863. +         iput() is often done by a sub-function (often from the msdos
  3864. +         file system). So I get one too many iput() ? At the place
  3865. +         where an iput() is done, the inode is simply nulled, disabling
  3866. +         the last one.
  3867. +         if (a){
  3868. +             if (b){
  3869. +                 ...
  3870. +             }else if (c){
  3871. +                 msdos_rmdir(dir,...);
  3872. +                 dir = NULL;
  3873. +             }
  3874. +         }else if (d){
  3875. +             ...
  3876. +         }
  3877. +         iput (dir);
  3878. +         return status;
  3879. +         Note that the umsdos_lockcreate() and umsdos_unlockcreate() function
  3880. +         paire goes against this practice of "forgetting" the inode as soon
  3881. +         as possible.
  3882. +     */        
  3883. +     int ret = umsdos_nevercreat(dir,name,len,-EPERM);
  3884. +     if (ret == 0){
  3885. +         struct inode *sdir;
  3886. +         dir->i_count++;
  3887. +         ret = UMSDOS_lookup (dir,name,len,&sdir);
  3888. +         PRINTK (("rmdir lookup %d ",ret));
  3889. +         if (ret == 0){
  3890. +             int empty;
  3891. +             umsdos_lockcreate(dir);
  3892. +             if ((empty = umsdos_isempty (sdir)) != 0){
  3893. +                 PRINTK (("isempty %d i_count %d ",empty,sdir->i_count));
  3894. +                 if (empty == 1){
  3895. +                     /* We have to removed the EMD file */
  3896. +                     ret = msdos_unlink(sdir,UMSDOS_EMD_FILE
  3897. +                         ,UMSDOS_EMD_NAMELEN);
  3898. +                     sdir = NULL;
  3899. +                 }
  3900. +                 /* sdir must be free before msdos_rmdir() */
  3901. +                 iput (sdir);
  3902. +                 sdir = NULL;
  3903. +                 PRINTK (("isempty ret %d nlink %d ",ret,dir->i_nlink));
  3904. +                 if (ret == 0){
  3905. +                     struct umsdos_info info;
  3906. +                     dir->i_count++;
  3907. +                     umsdos_parse (name,len,&info);
  3908. +                     /* The findentry is there only to complete */
  3909. +                     /* the mangling */
  3910. +                     umsdos_findentry (dir,&info,2);
  3911. +                     ret = msdos_rmdir (dir,info.fake.fname
  3912. +                         ,info.fake.len);
  3913. +                     if (ret == 0){
  3914. +                         ret = umsdos_delentry (dir,&info,1);
  3915. +                     }
  3916. +                 }
  3917. +             }else{    
  3918. +                 /*
  3919. +                     The subdirectory is not empty, so leave it there
  3920. +                 */
  3921. +                 ret = -ENOTEMPTY;
  3922. +             }
  3923. +             iput(sdir);
  3924. +             umsdos_unlockcreate(dir);
  3925. +         }    
  3926. +     }
  3927. +     iput (dir);
  3928. +     PRINTK (("umsdos_rmdir %d\n",ret));
  3929. +     return ret;
  3930. + }
  3931. + /*
  3932. +     Remove a file from the directory.
  3933. + */
  3934. + int UMSDOS_unlink (
  3935. +     struct inode * dir,
  3936. +     const char * name,
  3937. +     int len)
  3938. + {
  3939. +     struct umsdos_info info;
  3940. +     int ret = umsdos_nevercreat(dir,name,len,-EPERM);
  3941. +     if (ret == 0){
  3942. +         ret = umsdos_parse (name,len,&info);
  3943. +         if (ret == 0){
  3944. +             umsdos_lockcreate(dir);
  3945. +             ret = umsdos_findentry(dir,&info,1);
  3946. +             if (ret == 0){
  3947. +                 PRINTK (("UMSDOS_unlink %s ",info.fake.fname));
  3948. +                 if (info.entry.flags & UMSDOS_HLINK){
  3949. +                     /* #Specification: hard link / deleting a link
  3950. +                         When we deletes a file, and this file is a link
  3951. +                         we must substract 1 to the nlink field of the
  3952. +                         hidden link.
  3953. +                         If the count goes to 0, we delete this hidden
  3954. +                         link too.
  3955. +                     */
  3956. +                     /*
  3957. +                         First, get the inode of the hidden link
  3958. +                         using the standard lookup function.
  3959. +                     */
  3960. +                     struct inode *inode;
  3961. +                     dir->i_count++;
  3962. +                     ret = UMSDOS_lookup (dir,name,len,&inode);
  3963. +                     if (ret == 0){
  3964. +                         PRINTK (("unlink nlink = %d ",inode->i_nlink));
  3965. +                         inode->i_nlink--;
  3966. +                         if (inode->i_nlink == 0){
  3967. +                             struct inode *hdir = iget(inode->i_sb
  3968. +                                 ,inode->u.umsdos_i.i_dir_owner);
  3969. +                             struct umsdos_dirent entry;
  3970. +                             ret = umsdos_inode2entry (hdir,inode,&entry);
  3971. +                             if (ret == 0){
  3972. +                                 ret = UMSDOS_unlink (hdir,entry.name
  3973. +                                     ,entry.name_len);
  3974. +                             }else{
  3975. +                                 iput (hdir);
  3976. +                             }
  3977. +                         }else{
  3978. +                             ret = UMSDOS_notify_change (0,inode);
  3979. +                         }
  3980. +                         iput (inode);
  3981. +                     }
  3982. +                 }
  3983. +                 if (ret == 0){
  3984. +                     ret = umsdos_delentry (dir,&info,0);
  3985. +                     if (ret == 0){
  3986. +                         PRINTK (("Avant msdos_unlink %s ",info.fake.fname));
  3987. +                         dir->i_count++;
  3988. +                         ret = msdos_unlink_umsdos (dir,info.fake.fname
  3989. +                             ,info.fake.len);
  3990. +                         PRINTK (("msdos_unlink %s %o ret %d ",info.fake.fname
  3991. +                             ,info.entry.mode,ret));
  3992. +                     }
  3993. +                 }
  3994. +             }
  3995. +             umsdos_unlockcreate(dir);
  3996. +         }
  3997. +     }    
  3998. +     iput (dir);
  3999. +     PRINTK (("umsdos_unlink %d\n",ret));
  4000. +     return ret;
  4001. + }
  4002. + /*
  4003. +     Rename a file (move) in the file system.
  4004. + */
  4005. + int UMSDOS_rename(
  4006. +     struct inode * old_dir,
  4007. +     const char * old_name,
  4008. +     int old_len,
  4009. +     struct inode * new_dir,
  4010. +     const char * new_name,
  4011. +     int new_len)
  4012. + {
  4013. +     /* #Specification: weakness / rename
  4014. +         There is a case where UMSDOS rename has a different behavior
  4015. +         than normal UNIX file system. Renaming an open file across
  4016. +         directory boundary does not work. Renaming an open file within
  4017. +         a directory does work however.
  4018. +         The problem (not sure) is in the linux VFS msdos driver.
  4019. +         I believe this is not a bug but a design feature, because
  4020. +         an inode number represent some sort of directory address
  4021. +         in the MSDOS directory structure. So moving the file into
  4022. +         another directory does not preserve the inode number.
  4023. +     */
  4024. +     int ret = umsdos_nevercreat(new_dir,new_name,new_len,-EEXIST);
  4025. +     if (ret == 0){
  4026. +         ret = umsdos_rename_f (old_dir,old_name,old_len,new_dir,new_name
  4027. +             ,new_len,0);
  4028. +     }
  4029. +     return ret;
  4030. + }
  4031. diff -rc2P linux.1.1.12/fs/umsdos/notes linux/fs/umsdos/notes
  4032. *** linux.1.1.12/fs/umsdos/notes
  4033. --- linux/fs/umsdos/notes    Wed May 11 23:47:33 1994
  4034. ***************
  4035. *** 0 ****
  4036. --- 1,17 ----
  4037. + This file contain idea and things I don't want to forget
  4038. + Possible bug in fs/read_write.c
  4039. + Function sys_readdir()
  4040. +     There is a call the verify_area that does not take in account
  4041. +     the count parameter. I guess it should read
  4042. +     error = verify_area(VERIFY_WRITE, dirent, count*sizeof (*dirent));
  4043. +     instead of
  4044. +     error = verify_area(VERIFY_WRITE, dirent, sizeof (*dirent));
  4045. +     Of course, now , count is always 1
  4046. diff -rc2P linux.1.1.12/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c
  4047. *** linux.1.1.12/fs/umsdos/rdir.c
  4048. --- linux/fs/umsdos/rdir.c    Wed May 11 23:47:33 1994
  4049. ***************
  4050. *** 0 ****
  4051. --- 1,239 ----
  4052. + /*
  4053. +  *  linux/fs/umsdos/rdir.c
  4054. +  *
  4055. +  *  Written 1994 by Jacques Gelinas
  4056. +  *
  4057. +  *  Extended MS-DOS directory pure MS-DOS handling functions
  4058. +  *  (For directory without EMD file).
  4059. +  */
  4060. + #include <asm/segment.h>
  4061. + #include <linux/sched.h>
  4062. + #include <linux/fs.h>
  4063. + #include <linux/msdos_fs.h>
  4064. + #include <linux/errno.h>
  4065. + #include <linux/stat.h>
  4066. + #include <linux/limits.h>
  4067. + #include <linux/umsdos_fs.h>
  4068. + #include <linux/malloc.h>
  4069. + #define PRINTK(x)
  4070. + #define Printk(x) printk x
  4071. + extern struct inode *pseudo_root;
  4072. + static int UMSDOS_rreaddir (
  4073. +     struct inode *dir,
  4074. +     struct file *filp,
  4075. +     struct dirent *dirent,
  4076. +     int count)
  4077. + {
  4078. +     int ret = 0;
  4079. +     while (1){
  4080. +         ret = msdos_readdir(dir,filp,dirent,count);
  4081. +         if (ret == 5
  4082. +             && pseudo_root != NULL
  4083. +             && dir->i_sb->s_mounted == pseudo_root->i_sb->s_mounted){
  4084. +             /*
  4085. +                 In pseudo root mode, we must eliminate logically
  4086. +                 the directory linux from the real root.
  4087. +             */
  4088. +             char name[5];
  4089. +             memcpy_fromfs (name,dirent->d_name,5);
  4090. +             if (memcmp(name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN)!=0) break;
  4091. +         }else{
  4092. +             if (pseudo_root != NULL
  4093. +                 && ret == 2
  4094. +                 && dir == dir->i_sb->s_mounted
  4095. +                 && dir == pseudo_root->i_sb->s_mounted){
  4096. +                 char name[2];
  4097. +                 memcpy_fromfs (name,dirent->d_name,2);
  4098. +                 if (name[0] == '.' && name[1] == '.'){
  4099. +                     put_fs_long (pseudo_root->i_ino,&dirent->d_ino);
  4100. +                 }
  4101. +             }
  4102. +             break;
  4103. +         }
  4104. +     }
  4105. +     return ret;
  4106. + }
  4107. + int UMSDOS_rlookup(
  4108. +     struct inode *dir,
  4109. +     const char *name,
  4110. +     int len,
  4111. +     struct inode **result)    /* Will hold inode of the file, if successful */
  4112. + {
  4113. +     int ret;
  4114. +     if (pseudo_root != NULL
  4115. +         && len == 2
  4116. +         && name[0] == '.'
  4117. +         && name[1] == '.'
  4118. +         && dir == dir->i_sb->s_mounted
  4119. +         && dir == pseudo_root->i_sb->s_mounted){
  4120. +         *result = pseudo_root;
  4121. +         pseudo_root->i_count++;
  4122. +         ret = 0;
  4123. +         /* #Specification: pseudo root / DOS/..
  4124. +             In the real root directory (c:\), the directory ..
  4125. +             is the pseudo root (c:\linux).
  4126. +         */
  4127. +     }else{
  4128. +         ret = umsdos_real_lookup (dir,name,len,result);
  4129. +         if (ret == 0){
  4130. +             struct inode *inode = *result;
  4131. +             if (inode == pseudo_root){
  4132. +                 /* #Specification: pseudo root / DOS/linux
  4133. +                     Even in the real root directory (c:\), the directory
  4134. +                     /linux won't show
  4135. +                 */
  4136. +                 ret = -ENOENT;
  4137. +                 iput (pseudo_root);
  4138. +                 *result = NULL;
  4139. +             }else if (S_ISDIR(inode->i_mode)){
  4140. +                 /* We must place the proper function table */
  4141. +                 /* depending if this is a MsDOS directory or an UMSDOS directory */
  4142. +                 umsdos_setup_dir_inode(inode);
  4143. +             }
  4144. +         }
  4145. +     }
  4146. +     iput (dir);
  4147. +     return ret;
  4148. + }
  4149. + static int UMSDOS_rrmdir (
  4150. +     struct inode *dir,
  4151. +     const char *name,
  4152. +     int len)
  4153. + {
  4154. +     /* #Specification: dual mode / rmdir in a DOS directory
  4155. +         In a DOS (not EMD in it) directory, we use a reverse strategy
  4156. +         compared with an Umsdos directory. We assume that a subdirectory
  4157. +         of a DOS directory is also a DOS directory. This is not always
  4158. +         true (umssync may be used anywhere), but make sense.
  4159. +         So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
  4160. +         then we check if it is a Umsdos directory. We check if it is
  4161. +         really empty (only . .. and --linux-.--- in it). If it is true
  4162. +         we remove the EMD and do a msdos_rmdir() again.
  4163. +         In a Umsdos directory, we assume all subdirectory are also
  4164. +         Umsdos directory, so we check the EMD file first.
  4165. +     */
  4166. +     int ret;
  4167. +     if (umsdos_is_pseudodos(dir,name,len)){
  4168. +         /* #Specification: pseudo root / rmdir /DOS
  4169. +             The pseudo sub-directory /DOS can't be removed!
  4170. +             This is done even if the pseudo root is not a Umsdos
  4171. +             directory anymore (very unlikely), but an accident (under
  4172. +             MsDOS) is always possible.
  4173. +             EPERM is returned.
  4174. +         */
  4175. +         ret = -EPERM;
  4176. +     }else{
  4177. +         umsdos_lockcreate (dir);
  4178. +         dir->i_count++;
  4179. +         ret = msdos_rmdir (dir,name,len);
  4180. +         if (ret == -ENOTEMPTY){
  4181. +             struct inode *sdir;
  4182. +             dir->i_count++;
  4183. +             ret = UMSDOS_rlookup (dir,name,len,&sdir);
  4184. +             PRINTK (("rrmdir lookup %d ",ret));
  4185. +             if (ret == 0){
  4186. +                 int empty;
  4187. +                 if ((empty = umsdos_isempty (sdir)) != 0){
  4188. +                     PRINTK (("isempty %d i_count %d ",empty,sdir->i_count));
  4189. +                     if (empty == 2){
  4190. +                         /*
  4191. +                             Not a Umsdos directory, so the previous msdos_rmdir
  4192. +                             was not lying :-)
  4193. +                         */
  4194. +                         ret = -ENOTEMPTY;
  4195. +                     }else if (empty == 1){
  4196. +                         /* We have to removed the EMD file */
  4197. +                         ret = msdos_unlink(sdir,UMSDOS_EMD_FILE
  4198. +                             ,UMSDOS_EMD_NAMELEN);
  4199. +                         sdir = NULL;
  4200. +                         if (ret == 0){
  4201. +                             dir->i_count++;
  4202. +                             ret = msdos_rmdir (dir,name,len);
  4203. +                         }
  4204. +                     }
  4205. +                 }else{
  4206. +                     ret = -ENOTEMPTY;
  4207. +                 }
  4208. +                 iput (sdir);
  4209. +             }
  4210. +         }
  4211. +         umsdos_unlockcreate (dir);
  4212. +     }
  4213. +     iput (dir);
  4214. +     return ret;
  4215. + }
  4216. + /* #Specification: dual mode / introduction
  4217. +     One goal of UMSDOS is to allow a practical and simple coexistence
  4218. +     between MsDOS and Linux in a single partition. Using the EMD file
  4219. +     in each directory, UMSDOS add Unix semantics and capabilities to
  4220. +     normal DOS file system. To help and simplify coexistence, here is
  4221. +     the logic related to the EMD file.
  4222. +     If it is missing, then the directory is managed by the MsDOS driver.
  4223. +     The names are limited to DOS limits (8.3). No links, no device special
  4224. +     and pipe and so on.
  4225. +     If it is there, it is the directory. If it is there but empty, then
  4226. +     the directory looks empty. The utility umssync allows synchronisation
  4227. +     of the real DOS directory and the EMD.
  4228. +     Whenever umssync is applied to a directory without EMD, one is
  4229. +     created on the fly. The directory is promoted to full unix semantic.
  4230. +     Of course, the ls command will show exactly the same content as before
  4231. +     the umssync session.
  4232. +     It is believed that the user/admin will promote directories to unix
  4233. +     semantic as needed.
  4234. +     The strategy to implement this is to use two function table (struct
  4235. +     inode_operations). One for true UMSDOS directory and one for directory
  4236. +     with missing EMD.
  4237. +     Functions related to the DOS semantic (but aware of UMSDOS) generally
  4238. +     have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
  4239. +     from the one with full UMSDOS semantic.
  4240. + */
  4241. + static struct file_operations umsdos_rdir_operations = {
  4242. +     NULL,                /* lseek - default */
  4243. +     UMSDOS_dir_read,    /* read */
  4244. +     NULL,                /* write - bad */
  4245. +     UMSDOS_rreaddir,    /* readdir */
  4246. +     NULL,                /* select - default */
  4247. +     UMSDOS_ioctl_dir,    /* ioctl - default */
  4248. +     NULL,                /* mmap */
  4249. +     NULL,                /* no special open code */
  4250. +     NULL,                /* no special release code */
  4251. +     NULL                /* fsync */
  4252. + };
  4253. + struct inode_operations umsdos_rdir_inode_operations = {
  4254. +     &umsdos_rdir_operations,    /* default directory file-ops */
  4255. +     msdos_create,        /* create */
  4256. +     UMSDOS_rlookup,        /* lookup */
  4257. +     NULL,                /* link */
  4258. +     msdos_unlink,        /* unlink */
  4259. +     NULL,                /* symlink */
  4260. +     msdos_mkdir,        /* mkdir */
  4261. +     UMSDOS_rrmdir,        /* rmdir */
  4262. +     NULL,                /* mknod */
  4263. +     msdos_rename,        /* rename */
  4264. +     NULL,                /* readlink */
  4265. +     NULL,                /* follow_link */
  4266. +     NULL,                /* bmap */
  4267. +     NULL,                /* truncate */
  4268. +     NULL                /* permission */
  4269. + };
  4270. diff -rc2P linux.1.1.12/fs/umsdos/symlink.c linux/fs/umsdos/symlink.c
  4271. *** linux.1.1.12/fs/umsdos/symlink.c
  4272. --- linux/fs/umsdos/symlink.c    Thu May 12 00:21:54 1994
  4273. ***************
  4274. *** 0 ****
  4275. --- 1,143 ----
  4276. + /*
  4277. +  *  linux/fs/umsdos/file.c
  4278. +  *
  4279. +  *  Written 1992 by Jacques Gelinas
  4280. +  *    inpired from linux/fs/msdos/file.c Werner Almesberger
  4281. +  *
  4282. +  *  Extended MS-DOS regular file handling primitives
  4283. +  */
  4284. + #include <asm/segment.h>
  4285. + #include <asm/system.h>
  4286. + #include <linux/sched.h>
  4287. + #include <linux/fs.h>
  4288. + #include <linux/msdos_fs.h>
  4289. + #include <linux/errno.h>
  4290. + #include <linux/fcntl.h>
  4291. + #include <linux/stat.h>
  4292. + #include <linux/umsdos_fs.h>
  4293. + #include <linux/malloc.h>
  4294. + #define PRINTK(x)
  4295. + #define Printk(x)    printk x
  4296. + /*
  4297. +     Read the data associate with the symlink.
  4298. +     Return lenght read in buffer or  a negative error code.
  4299. + */
  4300. + static int umsdos_readlink_x (
  4301. +     struct inode *inode,
  4302. +     char *buffer,
  4303. +     int (*msdos_read)(struct inode *, struct file *, char *, int),
  4304. +     int bufsiz)
  4305. + {
  4306. +     int ret = inode->i_size;
  4307. +     struct file filp;
  4308. +     filp.f_pos = 0;
  4309. +     if (ret > bufsiz) ret = bufsiz;
  4310. +     if ((*msdos_read) (inode, &filp, buffer,ret) != ret){
  4311. +         ret = -EIO;
  4312. +     }
  4313. +     return ret;
  4314. + }
  4315. + /*
  4316. +     Follow a symbolic link chain by calling open_namei recursivly
  4317. +     until an inode is found.
  4318. +     Return 0 if ok, or a negative error code if not.
  4319. + */
  4320. + static int UMSDOS_follow_link(
  4321. +     struct inode * dir,
  4322. +     struct inode * inode,
  4323. +     int flag,
  4324. +     int mode,
  4325. +     struct inode ** res_inode)
  4326. + {
  4327. +     int ret = -ELOOP;
  4328. +     *res_inode = NULL;
  4329. +     if (current->link_count < 5) {
  4330. +         char *path = (char*)kmalloc(PATH_MAX,GFP_KERNEL);
  4331. +         if (path == NULL){
  4332. +             ret = -ENOMEM;
  4333. +         }else{
  4334. +             if (!dir) {
  4335. +                 dir = current->fs[1].root;
  4336. +                 dir->i_count++;
  4337. +             }
  4338. +             if (!inode){
  4339. +                 PRINTK (("symlink: inode = NULL\n"));
  4340. +                 ret = -ENOENT;
  4341. +             }else if (!S_ISLNK(inode->i_mode)){
  4342. +                 PRINTK (("symlink: Not ISLNK\n"));
  4343. +                 *res_inode = inode;
  4344. +                 inode = NULL;
  4345. +                 ret = 0;
  4346. +             }else{
  4347. +                 ret = umsdos_readlink_x (inode,path,msdos_file_read_kmem,PATH_MAX-1);
  4348. +                 if (ret > 0){
  4349. +                     path[ret] = '\0';
  4350. +                     PRINTK (("follow :%s: %d ",path,ret));
  4351. +                     iput(inode);
  4352. +                     inode = NULL;
  4353. +                     current->link_count++;
  4354. +                     ret = open_namei(path,flag,mode,res_inode,dir);
  4355. +                     current->link_count--;
  4356. +                     dir = NULL;
  4357. +                 }else{
  4358. +                     ret = -EIO;
  4359. +                 }
  4360. +             }
  4361. +             kfree (path);
  4362. +         }
  4363. +     }    
  4364. +     iput(inode);
  4365. +     iput(dir);
  4366. +     PRINTK (("follow_link ret %d\n",ret));
  4367. +     return ret;
  4368. + }
  4369. + static int UMSDOS_readlink(struct inode * inode, char * buffer, int buflen)
  4370. + {
  4371. +     int ret = -EINVAL;
  4372. +     if (S_ISLNK(inode->i_mode)) {
  4373. +         ret = umsdos_readlink_x (inode,buffer,msdos_file_read,buflen);
  4374. +     }
  4375. +     PRINTK (("readlink %d %x bufsiz %d\n",ret,inode->i_mode,buflen));
  4376. +     iput(inode);
  4377. +     return ret;
  4378. +     
  4379. + }
  4380. + static struct file_operations umsdos_symlink_operations = {
  4381. +     NULL,                /* lseek - default */
  4382. +     NULL,                /* read */
  4383. +     NULL,                /* write */
  4384. +     NULL,                /* readdir - bad */
  4385. +     NULL,                /* select - default */
  4386. +     NULL,                /* ioctl - default */
  4387. +     NULL,                /* mmap */
  4388. +     NULL,                /* no special open is needed */
  4389. +     NULL,                /* release */
  4390. +     NULL                /* fsync */
  4391. + };
  4392. + struct inode_operations umsdos_symlink_inode_operations = {
  4393. +     &umsdos_symlink_operations,    /* default file operations */
  4394. +     NULL,            /* create */
  4395. +     NULL,            /* lookup */
  4396. +     NULL,            /* link */
  4397. +     NULL,            /* unlink */
  4398. +     NULL,            /* symlink */
  4399. +     NULL,            /* mkdir */
  4400. +     NULL,            /* rmdir */
  4401. +     NULL,            /* mknod */
  4402. +     NULL,            /* rename */
  4403. +     UMSDOS_readlink,    /* readlink */
  4404. +     UMSDOS_follow_link,    /* follow_link */
  4405. +     NULL,            /* bmap */
  4406. +     NULL,            /* truncate */
  4407. +     NULL            /* permission */
  4408. + };
  4409. diff -rc2P linux.1.1.12/include/linux/fs.h linux/include/linux/fs.h
  4410. *** linux.1.1.12/include/linux/fs.h    Fri May 20 23:49:07 1994
  4411. --- linux/include/linux/fs.h    Wed May 11 23:48:43 1994
  4412. ***************
  4413. *** 158,161 ****
  4414. --- 158,162 ----
  4415.   #include <linux/hpfs_fs_i.h>
  4416.   #include <linux/msdos_fs_i.h>
  4417. + #include <linux/umsdos_fs_i.h>
  4418.   #include <linux/iso_fs_i.h>
  4419.   #include <linux/nfs_fs_i.h>
  4420. ***************
  4421. *** 202,205 ****
  4422. --- 203,207 ----
  4423.           struct hpfs_inode_info hpfs_i;
  4424.           struct msdos_inode_info msdos_i;
  4425. +         struct umsdos_inode_info umsdos_i;
  4426.           struct iso_inode_info isofs_i;
  4427.           struct nfs_inode_info nfs_i;
  4428. ***************
  4429. *** 300,303 ****
  4430. --- 302,306 ----
  4431.       void (*truncate) (struct inode *);
  4432.       int (*permission) (struct inode *, int);
  4433. +     int (*smap) (struct inode *,int);
  4434.   };
  4435.   
  4436. diff -rc2P linux.1.1.12/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h
  4437. *** linux.1.1.12/include/linux/msdos_fs.h    Wed Dec  1 07:44:15 1993
  4438. --- linux/include/linux/msdos_fs.h    Wed May 11 23:48:51 1994
  4439. ***************
  4440. *** 162,165 ****
  4441. --- 162,166 ----
  4442.   extern int msdos_rmdir(struct inode *dir,const char *name,int len);
  4443.   extern int msdos_unlink(struct inode *dir,const char *name,int len);
  4444. + extern int msdos_unlink_umsdos(struct inode *dir,const char *name,int len);
  4445.   extern int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
  4446.       struct inode *new_dir,const char *new_name,int new_len);
  4447. ***************
  4448. *** 180,190 ****
  4449.   
  4450.   extern struct inode_operations msdos_dir_inode_operations;
  4451.   /* file.c */
  4452.   
  4453.   extern struct inode_operations msdos_file_inode_operations;
  4454.   extern struct inode_operations msdos_file_inode_operations_no_bmap;
  4455.   
  4456.   extern void msdos_truncate(struct inode *inode);
  4457.   
  4458.   #endif
  4459. --- 181,202 ----
  4460.   
  4461.   extern struct inode_operations msdos_dir_inode_operations;
  4462. ! extern int msdos_readdir (struct inode *inode, struct file *filp,
  4463. !     struct dirent *dirent, int count);
  4464. ! extern int msdos_readdir_kmem (struct inode *inode, struct file *filp,
  4465. !     struct dirent *dirent, int count);
  4466.   /* file.c */
  4467.   
  4468.   extern struct inode_operations msdos_file_inode_operations;
  4469. + extern int msdos_file_read_kmem(struct inode *, struct file *, char *, int);
  4470. + extern int msdos_file_read(struct inode *, struct file *, char *, int);
  4471. + extern int msdos_file_write_kmem(struct inode *, struct file *, char *, int);
  4472. + extern int msdos_file_write(struct inode *, struct file *, char *, int);
  4473.   extern struct inode_operations msdos_file_inode_operations_no_bmap;
  4474.   
  4475.   extern void msdos_truncate(struct inode *inode);
  4476. + /* mmap.c */
  4477. + extern int msdos_mmap (struct inode *, struct file *, unsigned long, size_t
  4478. +     ,int , unsigned long);
  4479.   
  4480.   #endif
  4481. diff -rc2P linux.1.1.12/include/linux/msdos_fs_i.h linux/include/linux/msdos_fs_i.h
  4482. *** linux.1.1.12/include/linux/msdos_fs_i.h    Wed Dec  1 07:44:15 1993
  4483. --- linux/include/linux/msdos_fs_i.h    Wed May 11 23:48:51 1994
  4484. ***************
  4485. *** 2,5 ****
  4486. --- 2,12 ----
  4487.   #define _MSDOS_FS_I
  4488.   
  4489. + #ifndef _LINUX_CONFIG_H
  4490. + #include <linux/config.h>
  4491. + #endif
  4492. + #ifndef _LINUX_PIPE_FS_I_H
  4493. + #include <linux/pipe_fs_i.h>
  4494. + #endif
  4495.   /*
  4496.    * MS-DOS file system inode data in memory
  4497. ***************
  4498. *** 7,10 ****
  4499. --- 14,32 ----
  4500.   
  4501.   struct msdos_inode_info {
  4502. +     /*
  4503. +         UMSDOS manage special file and fifo as normal empty
  4504. +         msdos file. fifo inode processing conflict with msdos
  4505. +         processing. So I insert the pipe_inode_info so the
  4506. +         information does not overlap. This increases the size of
  4507. +         the msdos_inode_info, but the clear winner here is
  4508. +         the ext2_inode_info. So it does not change anything to
  4509. +         the total size of a struct inode.
  4510. +         I have not put it conditionnal. With the advent of loadable
  4511. +         file system drivers, it would be very easy to compile
  4512. +         a MsDOS FS driver unaware of UMSDOS and then later to
  4513. +         load a (then incompatible) UMSDOS FS driver.
  4514. +     */
  4515. +     struct pipe_inode_info reserved;
  4516.       int i_start;    /* first cluster or 0 */
  4517.       int i_attrs;    /* unused attribute bits */
  4518. diff -rc2P linux.1.1.12/include/linux/umsdos_fs.h linux/include/linux/umsdos_fs.h
  4519. *** linux.1.1.12/include/linux/umsdos_fs.h
  4520. --- linux/include/linux/umsdos_fs.h    Wed May 11 23:54:05 1994
  4521. ***************
  4522. *** 0 ****
  4523. --- 1,105 ----
  4524. + #ifndef LINUX_UMSDOS_FS_H
  4525. + #define LINUX_UMSDOS_FS_H
  4526. + #define UMSDOS_VERSION    0
  4527. + #define UMSDOS_RELEASE    3
  4528. + #ifndef LINUX_FS_H
  4529. + #include <linux/fs.h>
  4530. + #endif
  4531. + /* This is the file acting as a directory extension */
  4532. + #define UMSDOS_EMD_FILE        "--linux-.---"
  4533. + #define UMSDOS_EMD_NAMELEN    12
  4534. + #define UMSDOS_PSDROOT_NAME    "linux"
  4535. + #define UMSDOS_PSDROOT_LEN    5
  4536. + struct umsdos_fake_info {
  4537. +     char fname[13];
  4538. +     int  len;
  4539. + };
  4540. + #define UMSDOS_MAXNAME    220
  4541. + /* This structure is 256 bytes large, depending on the name, only part */
  4542. + /* of it is written to disk */
  4543. + struct umsdos_dirent {
  4544. +     unsigned char name_len;    /* if == 0, then this entry is not used */
  4545. +     unsigned char  flags;    /* UMSDOS_xxxx */
  4546. +     unsigned short nlink;    /* How many hard links point to this entry */
  4547. +     uid_t         uid;        /* Owner user id */
  4548. +     gid_t         gid;        /* Group id */
  4549. +     time_t        atime;        /* Access time */
  4550. +     time_t        mtime;        /* Last modification time */
  4551. +     time_t        ctime;        /* Creation time */
  4552. +     dev_t        rdev;        /* major and minor number of a device */
  4553. +                             /* special file */
  4554. +     umode_t        mode;        /* Standard UNIX permissions bits + type of */
  4555. +     char    spare[12];        /* unused bytes for future extensions */
  4556. +                             /* file, see linux/stat.h */
  4557. +     char name[UMSDOS_MAXNAME];    /* Not '\0' terminated */
  4558. +                             /* but '\0' padded, so it will allow */
  4559. +                             /* for adding news fields in this record */
  4560. +                             /* by reducing the size of name[] */
  4561. + };
  4562. + #define UMSDOS_HIDDEN    1    /* Never show this entry in directory search */
  4563. + #define UMSDOS_HLINK    2    /* It is a (pseudo) hard link */
  4564. + /* #Specification: EMD file / record size
  4565. +     Entry are 64 bytes wide in the EMD file. It allows for a 30 characters
  4566. +     name. If a name is longer, contiguous entries are allocated. So a
  4567. +     umsdos_dirent may span multiple records.
  4568. + */
  4569. + #define UMSDOS_REC_SIZE        64
  4570. + /* Translation between MSDOS name and UMSDOS name */
  4571. + struct umsdos_info{
  4572. +     int msdos_reject;    /* Tell if the file name is invalid for MSDOS */
  4573. +                         /* See umsdos_parse */
  4574. +     struct umsdos_fake_info fake;
  4575. +     struct umsdos_dirent entry;
  4576. +     off_t f_pos;        /* offset of the entry in the EMD file */
  4577. +                         /* or offset where the entry may be store */
  4578. +                         /* if it is a new entry */
  4579. +     int recsize;        /* Record size needed to store entry */
  4580. + };
  4581. + /* Definitions for ioctl (number randomly chosen) */
  4582. + /* The next ioctl commands operate only on the DOS directory */
  4583. + /* The file umsdos_progs/umsdosio.c contain a string table */
  4584. + /* based on the order of those definition. Keep it in sync */
  4585. + #define UMSDOS_READDIR_DOS    1234    /* Do a readdir of the DOS directory */
  4586. + #define UMSDOS_UNLINK_DOS    1235    /* Erase in the DOS directory only */
  4587. + #define UMSDOS_RMDIR_DOS    1236    /* rmdir in the DOS directory only */
  4588. + #define UMSDOS_STAT_DOS        1237    /* Get info about a file */
  4589. + /* The next ioctl commands operate only on the EMD file */
  4590. + #define UMSDOS_CREAT_EMD    1238    /* Create a file */
  4591. + #define UMSDOS_UNLINK_EMD    1239    /* unlink (rmdir) a file */
  4592. + #define UMSDOS_READDIR_EMD    1240    /* read the EMD file only. */
  4593. + #define UMSDOS_GETVERSION    1241    /* Get the release number of UMSDOS */
  4594. + #define UMSDOS_INIT_EMD        1242    /* Create the EMD file if not there */
  4595. + #define UMSDOS_DOS_SETUP    1243    /* Set the defaults of the MsDOS driver */
  4596. + #ifndef _SYS_STAT_H
  4597. + #include <sys/stat.h>
  4598. + #endif
  4599. + struct umsdos_ioctl{
  4600. +     struct dirent dos_dirent;
  4601. +     struct umsdos_dirent umsdos_dirent;
  4602. +     struct stat stat;
  4603. +     char version,release;
  4604. + };
  4605. + /* Different macros to access struct umsdos_dirent */
  4606. + #define EDM_ENTRY_ISUSED(e) ((e)->name_len!=0)
  4607. + extern struct inode_operations umsdos_dir_inode_operations;
  4608. + extern struct file_operations  umsdos_file_operations;
  4609. + extern struct inode_operations umsdos_file_inode_operations;
  4610. + extern struct inode_operations umsdos_file_inode_operations_no_bmap;
  4611. + extern struct inode_operations umsdos_symlink_inode_operations;
  4612. + #include <linux/umsdos_fs.p>
  4613. + #endif
  4614. diff -rc2P linux.1.1.12/include/linux/umsdos_fs.p linux/include/linux/umsdos_fs.p
  4615. *** linux.1.1.12/include/linux/umsdos_fs.p
  4616. --- linux/include/linux/umsdos_fs.p    Wed May 11 23:49:37 1994
  4617. ***************
  4618. *** 0 ****
  4619. --- 1,122 ----
  4620. + /* check.c 05/02/94 15.36.10 */
  4621. + void check_page_tables (void);
  4622. + /* dir.c 24/04/94 00.00.40 */
  4623. + int UMSDOS_dir_read (struct inode *inode,
  4624. +      struct file *filp,
  4625. +      char *buf,
  4626. +      int count);
  4627. + void umsdos_lookup_patch (struct inode *dir,
  4628. +      struct inode *inode,
  4629. +      struct umsdos_dirent *entry,
  4630. +      off_t emd_pos);
  4631. + int umsdos_inode2entry (struct inode *dir,
  4632. +      struct inode *inode,
  4633. +      struct umsdos_dirent *entry);
  4634. + int umsdos_locate_path (struct inode *inode, char *path);
  4635. + int umsdos_is_pseudodos (struct inode *dir, const char *name, int len);
  4636. + int UMSDOS_lookup (struct inode *dir,
  4637. +      const char *name,
  4638. +      int len,
  4639. +      struct inode **result);
  4640. + int umsdos_hlink2inode (struct inode *hlink, struct inode **result);
  4641. + /* emd.c 05/02/94 15.36.10 */
  4642. + int umsdos_emd_dir_write (struct inode *emd_dir,
  4643. +      struct file *filp,
  4644. +      char *buf,
  4645. +      int count);
  4646. + int umsdos_emd_dir_read (struct inode *emd_dir,
  4647. +      struct file *filp,
  4648. +      char *buf,
  4649. +      int count);
  4650. + struct inode *umsdos_emd_dir_lookup (struct inode *dir, int creat);
  4651. + int umsdos_emd_dir_readentry (struct inode *emd_dir,
  4652. +      struct file *filp,
  4653. +      struct umsdos_dirent *entry);
  4654. + int umsdos_writeentry (struct inode *dir,
  4655. +      struct inode *emd_dir,
  4656. +      struct umsdos_info *info,
  4657. +      int free_entry);
  4658. + int umsdos_newentry (struct inode *dir, struct umsdos_info *info);
  4659. + int umsdos_newhidden (struct inode *dir, struct umsdos_info *info);
  4660. + int umsdos_delentry (struct inode *dir,
  4661. +      struct umsdos_info *info,
  4662. +      int isdir);
  4663. + int umsdos_isempty (struct inode *dir);
  4664. + int umsdos_findentry (struct inode *dir,
  4665. +      struct umsdos_info *info,
  4666. +      int expect);
  4667. + /* file.c 05/02/94 15.36.10 */
  4668. + /* inode.c 23/04/94 23.57.54 */
  4669. + void UMSDOS_put_inode (struct inode *inode);
  4670. + void UMSDOS_put_super (struct super_block *sb);
  4671. + void UMSDOS_statfs (struct super_block *sb, struct statfs *buf);
  4672. + int umsdos_real_lookup (struct inode *dir,
  4673. +      const char *name,
  4674. +      int len,
  4675. +      struct inode **result);
  4676. + void umsdos_setup_dir_inode (struct inode *inode);
  4677. + void umsdos_set_dirinfo (struct inode *inode,
  4678. +      struct inode *dir,
  4679. +      off_t f_pos);
  4680. + int umsdos_isinit (struct inode *inode);
  4681. + void umsdos_patch_inode (struct inode *inode,
  4682. +      struct inode *dir,
  4683. +      off_t f_pos);
  4684. + int umsdos_get_dirowner (struct inode *inode, struct inode **result);
  4685. + void UMSDOS_read_inode (struct inode *inode);
  4686. + void UMSDOS_write_inode (struct inode *inode);
  4687. + int UMSDOS_notify_change (int flags, struct inode *inode);
  4688. + struct super_block *UMSDOS_read_super (struct super_block *s,
  4689. +      void *data,
  4690. +      int silent);
  4691. + /* ioctl.c 05/02/94 15.36.10 */
  4692. + int UMSDOS_ioctl_dir (struct inode *dir,
  4693. +      struct file *filp,
  4694. +      unsigned int cmd,
  4695. +      unsigned long data);
  4696. + /* mangle.c 05/02/94 15.36.10 */
  4697. + int printk (const char *msg, ...);
  4698. + void umsdos_manglename (struct umsdos_info *info);
  4699. + int umsdos_evalrecsize (int len);
  4700. + int umsdos_parse (const char *fname, int len, struct umsdos_info *info);
  4701. + /* namei.c 06/04/94 18.24.58 */
  4702. + void umsdos_lockcreate (struct inode *dir);
  4703. + void umsdos_startlookup (struct inode *dir);
  4704. + void umsdos_unlockcreate (struct inode *dir);
  4705. + void umsdos_endlookup (struct inode *dir);
  4706. + int UMSDOS_symlink (struct inode *dir,
  4707. +      const char *name,
  4708. +      int len,
  4709. +      const char *symname);
  4710. + int UMSDOS_link (struct inode *oldinode,
  4711. +      struct inode *dir,
  4712. +      const char *name,
  4713. +      int len);
  4714. + int UMSDOS_create (struct inode *dir,
  4715. +      const char *name,
  4716. +      int len,
  4717. +      int mode,
  4718. +      struct inode **result);
  4719. + int UMSDOS_mkdir (struct inode *dir,
  4720. +      const char *name,
  4721. +      int len,
  4722. +      int mode);
  4723. + int UMSDOS_mknod (struct inode *dir,
  4724. +      const char *name,
  4725. +      int len,
  4726. +      int mode,
  4727. +      int rdev);
  4728. + int UMSDOS_rmdir (struct inode *dir, const char *name, int len);
  4729. + int UMSDOS_unlink (struct inode *dir, const char *name, int len);
  4730. + int UMSDOS_rename (struct inode *old_dir,
  4731. +      const char *old_name,
  4732. +      int old_len,
  4733. +      struct inode *new_dir,
  4734. +      const char *new_name,
  4735. +      int new_len);
  4736. + /* rdir.c 23/04/94 10.51.44 */
  4737. + int UMSDOS_rlookup (struct inode *dir,
  4738. +      const char *name,
  4739. +      int len,
  4740. +      struct inode **result);
  4741. + /* symlink.c 05/02/94 15.36.10 */
  4742. diff -rc2P linux.1.1.12/include/linux/umsdos_fs_i.h linux/include/linux/umsdos_fs_i.h
  4743. *** linux.1.1.12/include/linux/umsdos_fs_i.h
  4744. --- linux/include/linux/umsdos_fs_i.h    Wed May 11 23:49:38 1994
  4745. ***************
  4746. *** 0 ****
  4747. --- 1,140 ----
  4748. + #ifndef UMSDOS_FS_I_H
  4749. + #define UMSDOS_FS_I_H
  4750. + #ifndef _LINUX_TYPES_H
  4751. + #include <linux/types.h>
  4752. + #endif
  4753. + #include <linux/msdos_fs_i.h>
  4754. + #include <linux/pipe_fs_i.h>
  4755. + /* #Specification: strategy / in memory inode
  4756. +     Here is the information specific to the inode of the UMSDOS file
  4757. +     system. This information is added to the end of the standard struct
  4758. +     inode. Each file system has its own extension to struct inode,
  4759. +     so do the umsdos file system.
  4760. +     The strategy is to have the umsdos_inode_info as a superset of
  4761. +     the msdos_inode_info, since most of the time the job is done
  4762. +     by the msdos fs code.
  4763. +     So we duplicate the msdos_inode_info, and add our own info at the
  4764. +     end.
  4765. +     For all file type (and directory) the inode has a reference to:
  4766. +         the directory which hold this entry: i_dir_owner
  4767. +         The EMD file of i_dir_owner: i_emd_owner
  4768. +         The offset in this EMD file of the entry: pos
  4769. +     For directory, we also have a reference to the inode of its
  4770. +     own EMD file. Also, we have dir_locking_info to help synchronise
  4771. +     file creation and file lookup. This data is sharing space with
  4772. +     the pipe_inode_info not used by directory. See also msdos_fs_i.h
  4773. +     for more information about pipe_inode_info and msdos_inode_info.
  4774. +     Special file and fifo do have an inode which correspond to an
  4775. +     empty MSDOS file.
  4776. +     symlink are processed mostly like regular file. The content is the
  4777. +     link.
  4778. +     fifos add there own extension to the inode. I have reserved some
  4779. +     space for fifos side by side with msdos_inode_info. This is just
  4780. +     to for the show, because msdos_inode_info already include the
  4781. +     pipe_inode_info.
  4782. +     The UMSDOS specific extension is placed after the union.
  4783. + */
  4784. + struct dir_locking_info {
  4785. +     struct wait_queue *p;
  4786. +     short int looking;        /* How many process doing a lookup */
  4787. +     short int creating;        /* Is there any creation going on here */
  4788. +                             /* Only one at a time, although one */
  4789. +                             /* may recursivly lock, so it is a counter */
  4790. +     long pid;                /* pid of the process owning the creation */
  4791. +                             /* lock */
  4792. + };
  4793. + struct umsdos_inode_info {
  4794. +     union {
  4795. +         struct msdos_inode_info msdos_info;
  4796. +         struct pipe_inode_info pipe_info;
  4797. +         struct dir_locking_info dir_info;
  4798. +     }u;    /* Simply a filler, never referenced by fs/umsdos/... */
  4799. +     unsigned long i_dir_owner;    /* Inode of the dir which hold this */
  4800. +                                 /* entry */
  4801. +     unsigned long i_emd_owner;    /* Inode of the EMD file of i_dir_owner */
  4802. +     off_t pos;                    /* Entry offset in the emd_owner file */
  4803. +     /* The rest is used only if this inode describe a directory */
  4804. +     unsigned long i_emd_dir;    /* Inode of the EMD file of this inode */
  4805. + };
  4806. + #endif
  4807. + #ifndef UMSDOS_FS_I_H
  4808. + #define UMSDOS_FS_I_H
  4809. + #ifndef _LINUX_TYPES_H
  4810. + #include <linux/types.h>
  4811. + #endif
  4812. + #include <linux/msdos_fs_i.h>
  4813. + #include <linux/pipe_fs_i.h>
  4814. + /* #Specification: strategy / in memory inode
  4815. +     Here is the information specific to the inode of the UMSDOS file
  4816. +     system. This information is added to the end of the standard struct
  4817. +     inode. Each file system has its own extension to struct inode,
  4818. +     so do the umsdos file system.
  4819. +     The strategy is to have the umsdos_inode_info as a superset of
  4820. +     the msdos_inode_info, since most of the time the job is done
  4821. +     by the msdos fs code.
  4822. +     So we duplicate the msdos_inode_info, and add our own info at the
  4823. +     end.
  4824. +     For all file type (and directory) the inode has a reference to:
  4825. +         the directory which hold this entry: i_dir_owner
  4826. +         The EMD file of i_dir_owner: i_emd_owner
  4827. +         The offset in this EMD file of the entry: pos
  4828. +     For directory, we also have a reference to the inode of its
  4829. +     own EMD file. Also, we have dir_locking_info to help synchronise
  4830. +     file creation and file lookup. This data is sharing space with
  4831. +     the pipe_inode_info not used by directory. See also msdos_fs_i.h
  4832. +     for more information about pipe_inode_info and msdos_inode_info.
  4833. +     Special file and fifo do have an inode which correspond to an
  4834. +     empty MSDOS file.
  4835. +     symlink are processed mostly like regular file. The content is the
  4836. +     link.
  4837. +     fifos add there own extension to the inode. I have reserved some
  4838. +     space for fifos side by side with msdos_inode_info. This is just
  4839. +     to for the show, because msdos_inode_info already include the
  4840. +     pipe_inode_info.
  4841. +     The UMSDOS specific extension is placed after the union.
  4842. + */
  4843. + struct dir_locking_info {
  4844. +     struct wait_queue *p;
  4845. +     short int looking;        /* How many process doing a lookup */
  4846. +     short int creating;        /* Is there any creation going on here */
  4847. +                             /* Only one at a time, although one */
  4848. +                             /* may recursivly lock, so it is a counter */
  4849. +     long pid;                /* pid of the process owning the creation */
  4850. +                             /* lock */
  4851. + };
  4852. + struct umsdos_inode_info {
  4853. +     union {
  4854. +         struct msdos_inode_info msdos_info;
  4855. +         struct pipe_inode_info pipe_info;
  4856. +         struct dir_locking_info dir_info;
  4857. +     }u;    /* Simply a filler, never referenced by fs/umsdos/... */
  4858. +     unsigned long i_dir_owner;    /* Inode of the dir which hold this */
  4859. +                                 /* entry */
  4860. +     unsigned long i_emd_owner;    /* Inode of the EMD file of i_dir_owner */
  4861. +     off_t pos;                    /* Entry offset in the emd_owner file */
  4862. +     /* The rest is used only if this inode describe a directory */
  4863. +     unsigned long i_emd_dir;    /* Inode of the EMD file of this inode */
  4864. + };
  4865. + #endif
  4866. diff -rc2P linux.1.1.12/init/main.c linux/init/main.c
  4867. *** linux.1.1.12/init/main.c    Fri May 20 23:49:25 1994
  4868. --- linux/init/main.c    Wed May 11 23:38:32 1994
  4869. ***************
  4870. *** 495,498 ****
  4871. --- 495,514 ----
  4872.       setup();
  4873.       sprintf(term, "TERM=con%dx%d", ORIG_VIDEO_COLS, ORIG_VIDEO_LINES);
  4874. +     #ifdef CONFIG_UMSDOS_FS
  4875. +     {
  4876. +         /*
  4877. +             When mounting a umsdos fs as root, we detect
  4878. +             the pseudo_root (/linux) and initialise it here.
  4879. +             pseudo_root is defined in fs/umsdos/inode.c
  4880. +         */
  4881. +         extern struct inode *pseudo_root;
  4882. +         if (pseudo_root != NULL){
  4883. +             current->fs->root = pseudo_root;
  4884. +             current->fs->pwd  = pseudo_root;
  4885. +         }
  4886. +     }
  4887. +     #endif
  4888.       (void) open("/dev/tty1",O_RDWR,0);
  4889.       (void) dup(0);
  4890. diff -rc2P linux.1.1.12/mm/swap.c linux/mm/swap.c
  4891. *** linux.1.1.12/mm/swap.c    Fri May 20 23:49:21 1994
  4892. --- linux/mm/swap.c    Wed May 11 23:38:32 1994
  4893. ***************
  4894. *** 18,21 ****
  4895. --- 18,22 ----
  4896.   #include <linux/string.h>
  4897.   #include <linux/stat.h>
  4898. + #include <linux/fs.h>
  4899.   
  4900.   #include <asm/system.h> /* for cli()/sti() */
  4901. ***************
  4902. *** 84,99 ****
  4903.           ll_rw_page(rw,p->swap_device,offset,buf);
  4904.       } else if (p->swap_file) {
  4905.           unsigned int zones[8];
  4906. !         unsigned int block;
  4907. !         int i, j;
  4908. !         block = offset << (12 - p->swap_file->i_sb->s_blocksize_bits);
  4909. !         for (i=0, j=0; j< PAGE_SIZE ; i++, j +=p->swap_file->i_sb->s_blocksize)
  4910. !             if (!(zones[i] = bmap(p->swap_file,block++))) {
  4911. !                 printk("rw_swap_page: bad swap file\n");
  4912. !                 return;
  4913.               }
  4914. !         ll_rw_swap_file(rw,p->swap_file->i_dev, zones, i,buf);
  4915.       } else
  4916.           printk("re_swap_page: no swap file or device\n");
  4917. --- 85,126 ----
  4918.           ll_rw_page(rw,p->swap_device,offset,buf);
  4919.       } else if (p->swap_file) {
  4920. +         struct inode *swapf = p->swap_file;
  4921.           unsigned int zones[8];
  4922. !         int i;
  4923. !         if (swapf->i_op->bmap == NULL
  4924. !             && swapf->i_op->smap != NULL){
  4925. !             /*
  4926. !                 With MsDOS, we use msdos_smap which return
  4927. !                 a sector number (not a cluster or block number).
  4928. !                 It is a patch to enable the UMSDOS project.
  4929. !                 Other people are working on better solution.
  4930. !                 It sounds like ll_rw_swap_file defined
  4931. !                 it operation size (sector size) based on
  4932. !                 PAGE_SIZE and the number of block to read.
  4933. !                 So using bmap ou smap should work even if
  4934. !                 smap will requiered more blocks.
  4935. !             */
  4936. !             int j;
  4937. !             unsigned int block = offset << 3;
  4938. !             for (i=0, j=0; j< PAGE_SIZE ; i++, j += 512){
  4939. !                 if (!(zones[i] = swapf->i_op->smap(swapf,block++))) {
  4940. !                     printk("rw_swap_page: bad swap file\n");
  4941. !                     return;
  4942. !                 }
  4943.               }
  4944. !         }else{
  4945. !             int j;
  4946. !             unsigned int block = offset
  4947. !                 << (12 - swapf->i_sb->s_blocksize_bits);
  4948. !             for (i=0, j=0; j< PAGE_SIZE ; i++, j +=swapf->i_sb->s_blocksize)
  4949. !                 if (!(zones[i] = bmap(swapf,block++))) {
  4950. !                     printk("rw_swap_page: bad swap file\n");
  4951. !                     return;
  4952. !                 }
  4953. !         }
  4954. !         ll_rw_swap_file(rw,swapf->i_dev, zones, i,buf);
  4955.       } else
  4956.           printk("re_swap_page: no swap file or device\n");
  4957.