root/fs/umsdos/rdir.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. UMSDOS_rreaddir
  2. UMSDOS_rlookup
  3. UMSDOS_rrmdir

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

/* [previous][next][first][last][top][bottom][index][help] */