root/fs/umsdos/ioctl.c

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

DEFINITIONS

This source file includes following definitions.
  1. UMSDOS_ioctl_dir

   1 /*
   2  *  linux/fs/umsdos/ioctl.c
   3  *
   4  *  Written 1993 by Jacques Gelinas
   5  *
   6  *  Extended MS-DOS ioctl directory handling functions
   7  */
   8 #ifdef MODULE
   9 #include <linux/module.h>
  10 #endif
  11 
  12 #include <asm/segment.h>
  13 #include <linux/errno.h>
  14 #include <linux/kernel.h>
  15 #include <linux/sched.h>
  16 #include <linux/fs.h>
  17 #include <linux/msdos_fs.h>
  18 #include <linux/umsdos_fs.h>
  19 
  20 #define PRINTK(x)
  21 #define Printk(x) printk x
  22 
  23 /*
  24         Perform special function on a directory
  25 */
  26 int UMSDOS_ioctl_dir (
     /* [previous][next][first][last][top][bottom][index][help] */
  27         struct inode *dir,
  28         struct file *filp,
  29         unsigned int cmd,
  30         unsigned long data)
  31 {
  32         int ret = -EPERM;
  33         /* #Specification: ioctl / acces
  34                 Only root (effective id) is allowed to do IOCTL on directory
  35                 in UMSDOS. EPERM is returned for other user.
  36         */
  37         if (current->euid == 0
  38                 || cmd == UMSDOS_GETVERSION){
  39                 struct umsdos_ioctl *idata = (struct umsdos_ioctl *)data;
  40                 ret = -EINVAL;
  41                 /* #Specification: ioctl / prototypes
  42                         The official prototype for the umsdos ioctl on directory
  43                         is:
  44 
  45                         int ioctl (
  46                                 int fd,         // File handle of the directory
  47                                 int cmd,        // command
  48                                 struct umsdos_ioctl *data)
  49 
  50                         The struct and the commands are defined in linux/umsdos_fs.h.
  51 
  52                         umsdos_progs/umsdosio.c provide an interface in C++ to all
  53                         these ioctl. umsdos_progs/udosctl is a small utility showing
  54                         all this.
  55 
  56                         These ioctl generally allow one to work on the EMD or the
  57                         DOS directory independently. These are essential to implement
  58                         the synchronise.
  59                 */
  60                 PRINTK (("ioctl %d ",cmd));
  61                 if (cmd == UMSDOS_GETVERSION){
  62                         /* #Specification: ioctl / UMSDOS_GETVERSION
  63                                 The field version and release of the structure
  64                                 umsdos_ioctl are filled with the version and release
  65                                 number of the fs code in the kernel. This will allow
  66                                 some form of checking. Users won't be able to run
  67                                 incompatible utility such as the synchroniser (umssync).
  68                                 umsdos_progs/umsdosio.c enforce this checking.
  69 
  70                                 Return always 0.
  71                         */
  72                         put_fs_byte (UMSDOS_VERSION,&idata->version);
  73                         put_fs_byte (UMSDOS_RELEASE,&idata->release);
  74                         ret = 0;
  75                 }else if (cmd == UMSDOS_READDIR_DOS){
  76                         /* #Specification: ioctl / UMSDOS_READDIR_DOS
  77                                 One entry is read from the DOS directory at the current
  78                                 file position. The entry is put as is in the dos_dirent
  79                                 field of struct umsdos_ioctl.
  80 
  81                                 Return > 0 if success.
  82                         */
  83                         ret = msdos_readdir(dir,filp,&idata->dos_dirent,1);
  84                 }else if (cmd == UMSDOS_READDIR_EMD){
  85                         /* #Specification: ioctl / UMSDOS_READDIR_EMD
  86                                 One entry is read from the EMD at the current
  87                                 file position. The entry is put as is in the umsdos_dirent
  88                                 field of struct umsdos_ioctl. The corresponding mangled
  89                                 DOS entry name is put in the dos_dirent field.
  90 
  91                                 All entries are read including hidden links. Blank
  92                                 entries are skipped.
  93 
  94                                 Return > 0 if success.
  95                         */
  96                         struct inode *emd_dir = umsdos_emd_dir_lookup (dir,0);
  97                         if (emd_dir != NULL){
  98                                 while (1){
  99                                         if (filp->f_pos >= emd_dir->i_size){
 100                                                 ret = 0;
 101                                                 break;
 102                                         }else{
 103                                                 struct umsdos_dirent entry;
 104                                                 off_t f_pos = filp->f_pos;
 105                                                 ret = umsdos_emd_dir_readentry (emd_dir,filp,&entry);
 106                                                 if (ret < 0){
 107                                                         break;
 108                                                 }else if (entry.name_len > 0){
 109                                                         struct umsdos_info info;
 110                                                         ret = entry.name_len;
 111                                                         umsdos_parse (entry.name,entry.name_len,&info);
 112                                                         info.f_pos = f_pos;
 113                                                         umsdos_manglename(&info);
 114                                                         memcpy_tofs(&idata->umsdos_dirent,&entry
 115                                                                 ,sizeof(entry));
 116                                                         memcpy_tofs(&idata->dos_dirent.d_name
 117                                                                 ,info.fake.fname,info.fake.len+1);
 118                                                         break;
 119                                                 }
 120                                         }
 121                                 }
 122                                 iput (emd_dir);
 123                         }else{
 124                                 /* The absence of the EMD is simply seen as an EOF */
 125                                 ret = 0;
 126                         }
 127                 }else if (cmd == UMSDOS_INIT_EMD){
 128                         /* #Specification: ioctl / UMSDOS_INIT_EMD
 129                                 The UMSDOS_INIT_EMD command make sure the EMD
 130                                 exist for a directory. If it does not, it is
 131                                 created. Also, it makes sure the directory functions
 132                                 table (struct inode_operations) is set to the UMSDOS
 133                                 semantic. This mean that umssync may be applied to
 134                                 an "opened" msdos directory, and it will change behavior
 135                                 on the fly.
 136 
 137                                 Return 0 if success.
 138                         */
 139                         extern struct inode_operations umsdos_rdir_inode_operations;
 140                         struct inode *emd_dir = umsdos_emd_dir_lookup (dir,1);
 141                         ret = emd_dir != NULL;
 142                         iput (emd_dir);
 143                                         
 144                         dir->i_op = ret
 145                                 ? &umsdos_dir_inode_operations
 146                                 : &umsdos_rdir_inode_operations;
 147                 }else{
 148                         struct umsdos_ioctl data;
 149                         memcpy_fromfs (&data,idata,sizeof(data));
 150                         if (cmd == UMSDOS_CREAT_EMD){
 151                                 /* #Specification: ioctl / UMSDOS_CREAT_EMD
 152                                         The umsdos_dirent field of the struct umsdos_ioctl is used
 153                                         as is to create a new entry in the EMD of the directory.
 154                                         The DOS directory is not modified.
 155                                         No validation is done (yet).
 156 
 157                                         Return 0 if success.
 158                                 */
 159                                 struct umsdos_info info;
 160                                 /* This makes sure info.entry and info in general is correctly */
 161                                 /* initialised */
 162                                 memcpy (&info.entry,&data.umsdos_dirent
 163                                         ,sizeof(data.umsdos_dirent));
 164                                 umsdos_parse (data.umsdos_dirent.name
 165                                         ,data.umsdos_dirent.name_len,&info);
 166                                 ret = umsdos_newentry (dir,&info);
 167                         }else if (cmd == UMSDOS_RENAME_DOS){
 168                                 /* #Specification: ioctl / UMSDOS_RENAME_DOS
 169                                         A file or directory is rename in a DOS directory
 170                                         (not moved across directory). The source name
 171                                         is in the dos_dirent.name field and the destination
 172                                         is in umsdos_dirent.name field.
 173 
 174                                         This ioctl allows umssync to rename a mangle file
 175                                         name before syncing it back in the EMD.
 176                                 */
 177                                 dir->i_count += 2;
 178                                 ret = msdos_rename (dir
 179                                         ,data.dos_dirent.d_name,data.dos_dirent.d_reclen
 180                                         ,dir
 181                                         ,data.umsdos_dirent.name,data.umsdos_dirent.name_len);
 182                         }else if (cmd == UMSDOS_UNLINK_EMD){
 183                                 /* #Specification: ioctl / UMSDOS_UNLINK_EMD
 184                                         The umsdos_dirent field of the struct umsdos_ioctl is used
 185                                         as is to remove an entry from the EMD of the directory.
 186                                         No validation is done (yet). The mode field is used
 187                                         to validate S_ISDIR or S_ISREG.
 188 
 189                                         Return 0 if success.
 190                                 */
 191                                 struct umsdos_info info;
 192                                 /* This makes sure info.entry and info in general is correctly */
 193                                 /* initialised */
 194                                 memcpy (&info.entry,&data.umsdos_dirent
 195                                         ,sizeof(data.umsdos_dirent));
 196                                 umsdos_parse (data.umsdos_dirent.name
 197                                         ,data.umsdos_dirent.name_len,&info);
 198                                 ret = umsdos_delentry (dir,&info
 199                                         ,S_ISDIR(data.umsdos_dirent.mode));
 200                         }else if (cmd == UMSDOS_UNLINK_DOS){
 201                                 /* #Specification: ioctl / UMSDOS_UNLINK_DOS
 202                                         The dos_dirent field of the struct umsdos_ioctl is used to
 203                                         execute a msdos_unlink operation. The d_name and d_reclen
 204                                         fields are used.
 205 
 206                                         Return 0 if success.
 207                                 */
 208                                 dir->i_count++;
 209                                 ret = msdos_unlink (dir,data.dos_dirent.d_name
 210                                         ,data.dos_dirent.d_reclen);
 211                         }else if (cmd == UMSDOS_RMDIR_DOS){
 212                                 /* #Specification: ioctl / UMSDOS_RMDIR_DOS
 213                                         The dos_dirent field of the struct umsdos_ioctl is used to
 214                                         execute a msdos_unlink operation. The d_name and d_reclen
 215                                         fields are used.
 216 
 217                                         Return 0 if success.
 218                                 */
 219                                 dir->i_count++;
 220                                 ret = msdos_rmdir (dir,data.dos_dirent.d_name
 221                                         ,data.dos_dirent.d_reclen);
 222                         }else if (cmd == UMSDOS_STAT_DOS){
 223                                 /* #Specification: ioctl / UMSDOS_STAT_DOS
 224                                         The dos_dirent field of the struct umsdos_ioctl is
 225                                         used to execute a stat operation in the DOS directory.
 226                                         The d_name and d_reclen fields are used.
 227 
 228                                         The following field of umsdos_ioctl.stat are filled.
 229 
 230                                         st_ino,st_mode,st_size,st_atime,st_mtime,st_ctime,
 231                                         Return 0 if success.
 232                                 */
 233                                 struct inode *inode;
 234                                 ret = umsdos_real_lookup (dir,data.dos_dirent.d_name
 235                                         ,data.dos_dirent.d_reclen,&inode);
 236                                 if (ret == 0){
 237                                         data.stat.st_ino = inode->i_ino;
 238                                         data.stat.st_mode = inode->i_mode;
 239                                         data.stat.st_size = inode->i_size;
 240                                         data.stat.st_atime = inode->i_atime;
 241                                         data.stat.st_ctime = inode->i_ctime;
 242                                         data.stat.st_mtime = inode->i_mtime;
 243                                         memcpy_tofs (&idata->stat,&data.stat,sizeof(data.stat));
 244                                         iput (inode);
 245                                 }
 246                         }else if (cmd == UMSDOS_DOS_SETUP){
 247                                 /* #Specification: ioctl / UMSDOS_DOS_SETUP
 248                                         The UMSDOS_DOS_SETUP ioctl allow changing the
 249                                         default permission of the MsDOS file system driver
 250                                         on the fly. The MsDOS driver apply global permission
 251                                         to every file and directory. Normally these permissions
 252                                         are controlled by a mount option. This is not
 253                                         available for root partition, so a special utility
 254                                         (umssetup) is provided to do this, normally in
 255                                         /etc/rc.local.
 256 
 257                                         Be aware that this apply ONLY to MsDOS directory
 258                                         (those without EMD --linux-.---). Umsdos directory
 259                                         have independent (standard) permission for each
 260                                         and every file.
 261 
 262                                         The field umsdos_dirent provide the information needed.
 263                                         umsdos_dirent.uid and gid sets the owner and group.
 264                                         umsdos_dirent.mode set the permissions flags.
 265                                 */
 266                                 dir->i_sb->u.msdos_sb.fs_uid = data.umsdos_dirent.uid;
 267                                 dir->i_sb->u.msdos_sb.fs_gid = data.umsdos_dirent.gid;
 268                                 dir->i_sb->u.msdos_sb.fs_umask = data.umsdos_dirent.mode;
 269                                 ret = 0;
 270                         }
 271                 }
 272         }
 273         PRINTK (("ioctl return %d\n",ret));
 274         return ret;
 275 }
 276 
 277 
 278 

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