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

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