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_x
  3. UMSDOS_rlookup
  4. 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 #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 (
     /* [previous][next][first][last][top][bottom][index][help] */
  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 /*
  70         Lookup into a non promoted directory.
  71         If the result is a directory, make sure we find out if it is
  72         a promoted one or not (calling umsdos_setup_dir_inode(inode)).
  73 */
  74 int umsdos_rlookup_x(
     /* [previous][next][first][last][top][bottom][index][help] */
  75         struct inode *dir,
  76         const char *name,
  77         int len,
  78         struct inode **result,  /* Will hold inode of the file, if successful */
  79         int nopseudo)                   /* Don't care about pseudo root mode */
  80                                                         /* so locating "linux" will work */
  81 {
  82         int ret;
  83         if (pseudo_root != NULL
  84                 && len == 2
  85                 && name[0] == '.'
  86                 && name[1] == '.'
  87                 && dir == dir->i_sb->s_mounted
  88                 && dir == pseudo_root->i_sb->s_mounted){
  89                 *result = pseudo_root;
  90                 pseudo_root->i_count++;
  91                 ret = 0;
  92                 /* #Specification: pseudo root / DOS/..
  93                         In the real root directory (c:\), the directory ..
  94                         is the pseudo root (c:\linux).
  95                 */
  96         }else{
  97                 ret = umsdos_real_lookup (dir,name,len,result);
  98                 if (ret == 0){
  99                         struct inode *inode = *result;
 100                         if (inode == pseudo_root && !nopseudo){
 101                                 /* #Specification: pseudo root / DOS/linux
 102                                         Even in the real root directory (c:\), the directory
 103                                         /linux won't show
 104                                 */
 105                                 ret = -ENOENT;
 106                                 iput (pseudo_root);
 107                                 *result = NULL;
 108                         }else if (S_ISDIR(inode->i_mode)){
 109                                 /* We must place the proper function table */
 110                                 /* depending if this is a MsDOS directory or an UMSDOS directory */
 111                                 umsdos_setup_dir_inode(inode);
 112                         }
 113                 }
 114         }
 115         iput (dir);
 116         return ret;
 117 }
 118 int UMSDOS_rlookup(
     /* [previous][next][first][last][top][bottom][index][help] */
 119         struct inode *dir,
 120         const char *name,
 121         int len,
 122         struct inode **result)  /* Will hold inode of the file, if successful */
 123 {
 124         return umsdos_rlookup_x(dir,name,len,result,0);
 125 }
 126 
 127 static int UMSDOS_rrmdir (
     /* [previous][next][first][last][top][bottom][index][help] */
 128         struct inode *dir,
 129         const char *name,
 130         int len)
 131 {
 132         /* #Specification: dual mode / rmdir in a DOS directory
 133                 In a DOS (not EMD in it) directory, we use a reverse strategy
 134                 compared with an Umsdos directory. We assume that a subdirectory
 135                 of a DOS directory is also a DOS directory. This is not always
 136                 true (umssync may be used anywhere), but make sense.
 137 
 138                 So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
 139                 then we check if it is a Umsdos directory. We check if it is
 140                 really empty (only . .. and --linux-.--- in it). If it is true
 141                 we remove the EMD and do a msdos_rmdir() again.
 142 
 143                 In a Umsdos directory, we assume all subdirectory are also
 144                 Umsdos directory, so we check the EMD file first.
 145         */
 146         int ret;
 147         if (umsdos_is_pseudodos(dir,name,len)){
 148                 /* #Specification: pseudo root / rmdir /DOS
 149                         The pseudo sub-directory /DOS can't be removed!
 150                         This is done even if the pseudo root is not a Umsdos
 151                         directory anymore (very unlikely), but an accident (under
 152                         MsDOS) is always possible.
 153 
 154                         EPERM is returned.
 155                 */
 156                 ret = -EPERM;
 157         }else{
 158                 umsdos_lockcreate (dir);
 159                 dir->i_count++;
 160                 ret = msdos_rmdir (dir,name,len);
 161                 if (ret == -ENOTEMPTY){
 162                         struct inode *sdir;
 163                         dir->i_count++;
 164                         ret = UMSDOS_rlookup (dir,name,len,&sdir);
 165                         PRINTK (("rrmdir lookup %d ",ret));
 166                         if (ret == 0){
 167                                 int empty;
 168                                 if ((empty = umsdos_isempty (sdir)) != 0){
 169                                         PRINTK (("isempty %d i_count %d ",empty,sdir->i_count));
 170                                         if (empty == 2){
 171                                                 /*
 172                                                         Not a Umsdos directory, so the previous msdos_rmdir
 173                                                         was not lying :-)
 174                                                 */
 175                                                 ret = -ENOTEMPTY;
 176                                         }else if (empty == 1){
 177                                                 /* We have to removed the EMD file */
 178                                                 ret = msdos_unlink(sdir,UMSDOS_EMD_FILE
 179                                                         ,UMSDOS_EMD_NAMELEN);
 180                                                 sdir = NULL;
 181                                                 if (ret == 0){
 182                                                         dir->i_count++;
 183                                                         ret = msdos_rmdir (dir,name,len);
 184                                                 }
 185                                         }
 186                                 }else{
 187                                         ret = -ENOTEMPTY;
 188                                 }
 189                                 iput (sdir);
 190                         }
 191                 }
 192                 umsdos_unlockcreate (dir);
 193         }
 194         iput (dir);
 195         return ret;
 196 }
 197 
 198 /* #Specification: dual mode / introduction
 199         One goal of UMSDOS is to allow a practical and simple coexistence
 200         between MsDOS and Linux in a single partition. Using the EMD file
 201         in each directory, UMSDOS add Unix semantics and capabilities to
 202         normal DOS file system. To help and simplify coexistence, here is
 203         the logic related to the EMD file.
 204 
 205         If it is missing, then the directory is managed by the MsDOS driver.
 206         The names are limited to DOS limits (8.3). No links, no device special
 207         and pipe and so on.
 208 
 209         If it is there, it is the directory. If it is there but empty, then
 210         the directory looks empty. The utility umssync allows synchronisation
 211         of the real DOS directory and the EMD.
 212 
 213         Whenever umssync is applied to a directory without EMD, one is
 214         created on the fly. The directory is promoted to full unix semantic.
 215         Of course, the ls command will show exactly the same content as before
 216         the umssync session.
 217 
 218         It is believed that the user/admin will promote directories to unix
 219         semantic as needed.
 220 
 221         The strategy to implement this is to use two function table (struct
 222         inode_operations). One for true UMSDOS directory and one for directory
 223         with missing EMD.
 224 
 225         Functions related to the DOS semantic (but aware of UMSDOS) generally
 226         have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
 227         from the one with full UMSDOS semantic.
 228 */
 229 static struct file_operations umsdos_rdir_operations = {
 230         NULL,                           /* lseek - default */
 231         UMSDOS_dir_read,        /* read */
 232         NULL,                           /* write - bad */
 233         UMSDOS_rreaddir,        /* readdir */
 234         NULL,                           /* select - default */
 235         UMSDOS_ioctl_dir,       /* ioctl - default */
 236         NULL,                           /* mmap */
 237         NULL,                           /* no special open code */
 238         NULL,                           /* no special release code */
 239         NULL                            /* fsync */
 240 };
 241 
 242 struct inode_operations umsdos_rdir_inode_operations = {
 243         &umsdos_rdir_operations,        /* default directory file-ops */
 244         msdos_create,           /* create */
 245         UMSDOS_rlookup,         /* lookup */
 246         NULL,                           /* link */
 247         msdos_unlink,           /* unlink */
 248         NULL,                           /* symlink */
 249         msdos_mkdir,            /* mkdir */
 250         UMSDOS_rrmdir,          /* rmdir */
 251         NULL,                           /* mknod */
 252         msdos_rename,           /* rename */
 253         NULL,                           /* readlink */
 254         NULL,                           /* follow_link */
 255         NULL,                           /* bmap */
 256         NULL,                           /* truncate */
 257         NULL                            /* permission */
 258 };
 259 
 260 

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