root/fs/umsdos/rdir.c

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

DEFINITIONS

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

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