home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / umsdos / ioctl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-31  |  8.9 KB  |  279 lines

  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 (
  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.  
  279.