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

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