home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / umsdos / rdir.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-23  |  6.6 KB  |  246 lines

  1. /*
  2.  *  linux/fs/umsdos/rdir.c
  3.  *
  4.  *  Written 1994 by Jacques Gelinas
  5.  *
  6.  *  Extended MS-DOS directory pure MS-DOS handling functions
  7.  *  (For directory without EMD file).
  8.  */
  9.  
  10. #ifdef MODULE
  11. #include <linux/module.h>
  12. #endif
  13.  
  14. #include <asm/segment.h>
  15.  
  16. #include <linux/sched.h>
  17. #include <linux/fs.h>
  18. #include <linux/msdos_fs.h>
  19. #include <linux/errno.h>
  20. #include <linux/stat.h>
  21. #include <linux/limits.h>
  22. #include <linux/umsdos_fs.h>
  23. #include <linux/malloc.h>
  24.  
  25. #define PRINTK(x)
  26. #define Printk(x) printk x
  27.  
  28.  
  29. extern struct inode *pseudo_root;
  30.  
  31. static int UMSDOS_rreaddir (
  32.     struct inode *dir,
  33.     struct file *filp,
  34.     struct dirent *dirent,
  35.     int count)
  36. {
  37.     int ret = 0;
  38.     while (1){
  39.         int len = -1;
  40.         ret = msdos_readdir(dir,filp,dirent,count);
  41.         if (ret > 0) len = get_fs_word(&dirent->d_reclen);
  42.         if (len == 5
  43.             && pseudo_root != NULL
  44.             && dir->i_sb->s_mounted == pseudo_root->i_sb->s_mounted){
  45.             /*
  46.                 In pseudo root mode, we must eliminate logically
  47.                 the directory linux from the real root.
  48.             */
  49.             char name[5];
  50.             memcpy_fromfs (name,dirent->d_name,5);
  51.             if (memcmp(name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN)!=0) break;
  52.         }else{
  53.             if (pseudo_root != NULL
  54.                 && len == 2
  55.                 && dir == dir->i_sb->s_mounted
  56.                 && dir == pseudo_root->i_sb->s_mounted){
  57.                 char name[2];
  58.                 memcpy_fromfs (name,dirent->d_name,2);
  59.                 if (name[0] == '.' && name[1] == '.'){
  60.                     put_fs_long (pseudo_root->i_ino,&dirent->d_ino);
  61.                 }
  62.             }
  63.             break;
  64.         }
  65.     }
  66.     return ret;
  67. }
  68.  
  69. int UMSDOS_rlookup(
  70.     struct inode *dir,
  71.     const char *name,
  72.     int len,
  73.     struct inode **result)    /* Will hold inode of the file, if successful */
  74. {
  75.     int ret;
  76.     if (pseudo_root != NULL
  77.         && len == 2
  78.         && name[0] == '.'
  79.         && name[1] == '.'
  80.         && dir == dir->i_sb->s_mounted
  81.         && dir == pseudo_root->i_sb->s_mounted){
  82.         *result = pseudo_root;
  83.         pseudo_root->i_count++;
  84.         ret = 0;
  85.         /* #Specification: pseudo root / DOS/..
  86.             In the real root directory (c:\), the directory ..
  87.             is the pseudo root (c:\linux).
  88.         */
  89.     }else{
  90.         ret = umsdos_real_lookup (dir,name,len,result);
  91.         if (ret == 0){
  92.             struct inode *inode = *result;
  93.             if (inode == pseudo_root){
  94.                 /* #Specification: pseudo root / DOS/linux
  95.                     Even in the real root directory (c:\), the directory
  96.                     /linux won't show
  97.                 */
  98.                 ret = -ENOENT;
  99.                 iput (pseudo_root);
  100.                 *result = NULL;
  101.             }else if (S_ISDIR(inode->i_mode)){
  102.                 /* We must place the proper function table */
  103.                 /* depending if this is a MsDOS directory or an UMSDOS directory */
  104.                 umsdos_setup_dir_inode(inode);
  105.             }
  106.         }
  107.     }
  108.     iput (dir);
  109.     return ret;
  110. }
  111.  
  112. static int UMSDOS_rrmdir (
  113.     struct inode *dir,
  114.     const char *name,
  115.     int len)
  116. {
  117.     /* #Specification: dual mode / rmdir in a DOS directory
  118.         In a DOS (not EMD in it) directory, we use a reverse strategy
  119.         compared with an Umsdos directory. We assume that a subdirectory
  120.         of a DOS directory is also a DOS directory. This is not always
  121.         true (umssync may be used anywhere), but make sense.
  122.  
  123.         So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
  124.         then we check if it is a Umsdos directory. We check if it is
  125.         really empty (only . .. and --linux-.--- in it). If it is true
  126.         we remove the EMD and do a msdos_rmdir() again.
  127.  
  128.         In a Umsdos directory, we assume all subdirectory are also
  129.         Umsdos directory, so we check the EMD file first.
  130.     */
  131.     int ret;
  132.     if (umsdos_is_pseudodos(dir,name,len)){
  133.         /* #Specification: pseudo root / rmdir /DOS
  134.             The pseudo sub-directory /DOS can't be removed!
  135.             This is done even if the pseudo root is not a Umsdos
  136.             directory anymore (very unlikely), but an accident (under
  137.             MsDOS) is always possible.
  138.  
  139.             EPERM is returned.
  140.         */
  141.         ret = -EPERM;
  142.     }else{
  143.         umsdos_lockcreate (dir);
  144.         dir->i_count++;
  145.         ret = msdos_rmdir (dir,name,len);
  146.         if (ret == -ENOTEMPTY){
  147.             struct inode *sdir;
  148.             dir->i_count++;
  149.             ret = UMSDOS_rlookup (dir,name,len,&sdir);
  150.             PRINTK (("rrmdir lookup %d ",ret));
  151.             if (ret == 0){
  152.                 int empty;
  153.                 if ((empty = umsdos_isempty (sdir)) != 0){
  154.                     PRINTK (("isempty %d i_count %d ",empty,sdir->i_count));
  155.                     if (empty == 2){
  156.                         /*
  157.                             Not a Umsdos directory, so the previous msdos_rmdir
  158.                             was not lying :-)
  159.                         */
  160.                         ret = -ENOTEMPTY;
  161.                     }else if (empty == 1){
  162.                         /* We have to removed the EMD file */
  163.                         ret = msdos_unlink(sdir,UMSDOS_EMD_FILE
  164.                             ,UMSDOS_EMD_NAMELEN);
  165.                         sdir = NULL;
  166.                         if (ret == 0){
  167.                             dir->i_count++;
  168.                             ret = msdos_rmdir (dir,name,len);
  169.                         }
  170.                     }
  171.                 }else{
  172.                     ret = -ENOTEMPTY;
  173.                 }
  174.                 iput (sdir);
  175.             }
  176.         }
  177.         umsdos_unlockcreate (dir);
  178.     }
  179.     iput (dir);
  180.     return ret;
  181. }
  182.  
  183. /* #Specification: dual mode / introduction
  184.     One goal of UMSDOS is to allow a practical and simple coexistence
  185.     between MsDOS and Linux in a single partition. Using the EMD file
  186.     in each directory, UMSDOS add Unix semantics and capabilities to
  187.     normal DOS file system. To help and simplify coexistence, here is
  188.     the logic related to the EMD file.
  189.  
  190.     If it is missing, then the directory is managed by the MsDOS driver.
  191.     The names are limited to DOS limits (8.3). No links, no device special
  192.     and pipe and so on.
  193.  
  194.     If it is there, it is the directory. If it is there but empty, then
  195.     the directory looks empty. The utility umssync allows synchronisation
  196.     of the real DOS directory and the EMD.
  197.  
  198.     Whenever umssync is applied to a directory without EMD, one is
  199.     created on the fly. The directory is promoted to full unix semantic.
  200.     Of course, the ls command will show exactly the same content as before
  201.     the umssync session.
  202.  
  203.     It is believed that the user/admin will promote directories to unix
  204.     semantic as needed.
  205.  
  206.     The strategy to implement this is to use two function table (struct
  207.     inode_operations). One for true UMSDOS directory and one for directory
  208.     with missing EMD.
  209.  
  210.     Functions related to the DOS semantic (but aware of UMSDOS) generally
  211.     have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
  212.     from the one with full UMSDOS semantic.
  213. */
  214. static struct file_operations umsdos_rdir_operations = {
  215.     NULL,                /* lseek - default */
  216.     UMSDOS_dir_read,    /* read */
  217.     NULL,                /* write - bad */
  218.     UMSDOS_rreaddir,    /* readdir */
  219.     NULL,                /* select - default */
  220.     UMSDOS_ioctl_dir,    /* ioctl - default */
  221.     NULL,                /* mmap */
  222.     NULL,                /* no special open code */
  223.     NULL,                /* no special release code */
  224.     NULL                /* fsync */
  225. };
  226.  
  227. struct inode_operations umsdos_rdir_inode_operations = {
  228.     &umsdos_rdir_operations,    /* default directory file-ops */
  229.     msdos_create,        /* create */
  230.     UMSDOS_rlookup,        /* lookup */
  231.     NULL,                /* link */
  232.     msdos_unlink,        /* unlink */
  233.     NULL,                /* symlink */
  234.     msdos_mkdir,        /* mkdir */
  235.     UMSDOS_rrmdir,        /* rmdir */
  236.     NULL,                /* mknod */
  237.     msdos_rename,        /* rename */
  238.     NULL,                /* readlink */
  239.     NULL,                /* follow_link */
  240.     NULL,                /* bmap */
  241.     NULL,                /* truncate */
  242.     NULL                /* permission */
  243. };
  244.  
  245.  
  246.