!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/fs/umsdos/   drwxr-xr-x
Free 318.35 GB of 458.09 GB (69.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     ioctl.c (12.33 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 *  linux/fs/umsdos/ioctl.c
 *
 *  Written 1993 by Jacques Gelinas
 *
 *  Extended MS-DOS ioctl directory handling functions
 */

#include <asm/uaccess.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
#include <linux/umsdos_fs.h>

struct UMSDOS_DIR_ONCE {
    struct dirent *ent;
    int count;
};

/*
 * Record a single entry the first call.
 * Return -EINVAL the next one.
 */
static int umsdos_ioctl_fill (
                     void *buf,
                     const char *name,
                     int name_len,
                     loff_t offset,
                     ino_t ino,
                     unsigned type)
{
    int ret = -EINVAL;
    struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf;

    if (d->count == 0) {
        copy_to_user (d->ent->d_name, name, name_len);
        put_user ('\0', d->ent->d_name + name_len);
        put_user (name_len, &d->ent->d_reclen);
        put_user (ino, &d->ent->d_ino);
        put_user (offset, &d->ent->d_off);
        d->count = 1;
        ret = 0;
    }
    return ret;
}


/*
 * Perform special function on a directory
 */
/* #Specification: ioctl / prototypes
 * The official prototype for the umsdos ioctl on directory
 * is:
 * 
 * int ioctl (
 * int fd,          // File handle of the directory
 * int cmd, // command
 * struct umsdos_ioctl *data)
 * 
 * The struct and the commands are defined in linux/umsdos_fs.h.
 * 
 * umsdos_progs/umsdosio.c provide an interface in C++ to all
 * these ioctl. umsdos_progs/udosctl is a small utility showing
 * all this.
 * 
 * These ioctl generally allow one to work on the EMD or the
 * DOS directory independently. These are essential to implement
 * the synchronise.
 */
int UMSDOS_ioctl_dir(struct inode *dir, struct file *filp, unsigned int cmd,
            unsigned long data_ptr)
{
    struct dentry *dentry = filp->f_dentry;
    struct umsdos_ioctl *idata = (struct umsdos_ioctl *) data_ptr;
    int ret;
    struct umsdos_ioctl data;

Printk(("UMSDOS_ioctl_dir: %s/%s, cmd=%d, data=%08lx\n",
dentry->d_parent->d_name.name, dentry->d_name.name, cmd, data_ptr));

    /* forward non-umsdos ioctls - this hopefully doesn't cause conflicts */
    if (cmd != UMSDOS_GETVERSION
        && cmd != UMSDOS_READDIR_DOS
        && cmd != UMSDOS_READDIR_EMD
        && cmd != UMSDOS_INIT_EMD
        && cmd != UMSDOS_CREAT_EMD
        && cmd != UMSDOS_RENAME_DOS
        && cmd != UMSDOS_UNLINK_EMD
        && cmd != UMSDOS_UNLINK_DOS
        && cmd != UMSDOS_RMDIR_DOS
        && cmd != UMSDOS_STAT_DOS
        && cmd != UMSDOS_DOS_SETUP)
        return fat_dir_ioctl (dir, filp, cmd, data_ptr);

    /* #Specification: ioctl / access
     * Only root (effective id) is allowed to do IOCTL on directory
     * in UMSDOS. EPERM is returned for other user.
     */
    /*
     * Well, not all cases require write access, but it simplifies
     * the code, and let's face it, there is only one client (umssync)
     * for all this.
     */
    ret = verify_area (VERIFY_WRITE, (void *) data_ptr, 
                sizeof (struct umsdos_ioctl));
    if (ret < 0)
        goto out;

    ret = -EPERM;
    if (current->euid != 0 && cmd != UMSDOS_GETVERSION)
        goto out;

    ret = -EINVAL;
    if (cmd == UMSDOS_GETVERSION) {
        /* #Specification: ioctl / UMSDOS_GETVERSION
         * The field version and release of the structure
         * umsdos_ioctl are filled with the version and release
         * number of the fs code in the kernel. This will allow
         * some form of checking. Users won't be able to run
         * incompatible utility such as the synchroniser (umssync).
         * umsdos_progs/umsdosio.c enforce this checking.
         * 
         * Return always 0.
         */
        put_user (UMSDOS_VERSION, &idata->version);
        put_user (UMSDOS_RELEASE, &idata->release);
        ret = 0;
        goto out;
    }
    if (cmd == UMSDOS_READDIR_DOS) {
        /* #Specification: ioctl / UMSDOS_READDIR_DOS
         * One entry is read from the DOS directory at the current
         * file position. The entry is put as is in the dos_dirent
         * field of struct umsdos_ioctl.
         * 
         * Return > 0 if success.
         */
        struct UMSDOS_DIR_ONCE bufk;

        bufk.count = 0;
        bufk.ent = &idata->dos_dirent;

        fat_readdir (filp, &bufk, umsdos_ioctl_fill);

        ret = bufk.count == 1 ? 1 : 0;
        goto out;
    }
    if (cmd == UMSDOS_READDIR_EMD) {
        /* #Specification: ioctl / UMSDOS_READDIR_EMD
         * One entry is read from the EMD at the current
         * file position. The entry is put as is in the umsdos_dirent
         * field of struct umsdos_ioctl. The corresponding mangled
         * DOS entry name is put in the dos_dirent field.
         * 
         * All entries are read including hidden links. Blank
         * entries are skipped.
         * 
         * Return > 0 if success.
         */
        struct dentry *demd;
        loff_t pos = filp->f_pos;

        /* The absence of the EMD is simply seen as an EOF */
        demd = umsdos_get_emd_dentry(dentry);
        ret = PTR_ERR(demd);
        if (IS_ERR(demd))
            goto out;
        ret = 0;
        if (!demd->d_inode)
            goto read_dput;

        while (pos < demd->d_inode->i_size) {
            off_t f_pos = pos;
            struct umsdos_dirent entry;
            struct umsdos_info info;

            ret = umsdos_emd_dir_readentry (demd, &pos, &entry);

            if (ret == -ENAMETOOLONG) {
                printk (KERN_INFO "Fixing EMD entry with invalid size -- zeroing out\n");
                memset (&info, 0, sizeof (info));
                info.f_pos = f_pos;
                info.recsize = UMSDOS_REC_SIZE;
                ret = umsdos_writeentry (dentry, &info, 1);
                continue;
            }

            if (ret)
                break;
            if (entry.name_len <= 0)
                continue;

            umsdos_parse (entry.name, entry.name_len, &info);
            info.f_pos = f_pos;
            umsdos_manglename (&info);
            ret = -EFAULT;
            if (copy_to_user (&idata->umsdos_dirent, &entry,
                            sizeof (entry)))
                break;
            if (copy_to_user (&idata->dos_dirent.d_name,
                            info.fake.fname,
                             info.fake.len + 1))
                break;
            ret = entry.name_len;
            break;
        }
        /* update the original f_pos */
        filp->f_pos = pos;
    read_dput:
        d_drop(demd);
        dput(demd);
        goto out;
    }
    if (cmd == UMSDOS_INIT_EMD) {
        /* #Specification: ioctl / UMSDOS_INIT_EMD
         * The UMSDOS_INIT_EMD command makes sure the EMD
         * exists for a directory. If it does not, it is
         * created. Also, it makes sure the directory function
         * table (struct inode_operations) is set to the UMSDOS
         * semantic. This mean that umssync may be applied to
         * an "opened" msdos directory, and it will change behavior
         * on the fly.
         * 
         * Return 0 if success.
         */

        ret = umsdos_make_emd(dentry);
Printk(("UMSDOS_ioctl_dir: INIT_EMD %s/%s, ret=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, ret));
        umsdos_setup_dir (dentry);
        goto out;
    }

    ret = -EFAULT;
    if (copy_from_user (&data, idata, sizeof (data)))
        goto out;

    if (cmd == UMSDOS_CREAT_EMD) {
        /* #Specification: ioctl / UMSDOS_CREAT_EMD
         * The umsdos_dirent field of the struct umsdos_ioctl is used
         * as is to create a new entry in the EMD of the directory.
         * The DOS directory is not modified.
         * No validation is done (yet).
         * 
         * Return 0 if success.
         */
        struct umsdos_info info;

        /* This makes sure info.entry and info in general
         * is correctly initialised
         */
        memcpy (&info.entry, &data.umsdos_dirent,
            sizeof (data.umsdos_dirent));
        umsdos_parse (data.umsdos_dirent.name
            ,data.umsdos_dirent.name_len, &info);
        ret = umsdos_newentry (dentry, &info);
        goto out;
    }
    else if (cmd == UMSDOS_RENAME_DOS) {
        struct dentry *old_dentry, *new_dentry;        /* FIXME */

        /* #Specification: ioctl / UMSDOS_RENAME_DOS
         * A file or directory is renamed in a DOS directory
         * (not moved across directory). The source name
         * is in the dos_dirent.name field and the destination
         * is in umsdos_dirent.name field.
         * 
         * This ioctl allows umssync to rename a mangled file
         * name before syncing it back in the EMD.
         */
        old_dentry = umsdos_lookup_dentry (dentry, 
                        data.dos_dirent.d_name,
                        data.dos_dirent.d_reclen ,1);
        ret = PTR_ERR(old_dentry);
        if (IS_ERR(old_dentry))
            goto out;
        new_dentry = umsdos_lookup_dentry (dentry,
                        data.umsdos_dirent.name,
                        data.umsdos_dirent.name_len, 1);
        ret = PTR_ERR(new_dentry);
        if (!IS_ERR(new_dentry)) {
printk("umsdos_ioctl: renaming %s/%s to %s/%s\n",
old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
            ret = msdos_rename (dir, old_dentry, dir, new_dentry);
            d_drop(new_dentry);
            d_drop(old_dentry);
            dput(new_dentry);
        }
        dput(old_dentry);
        goto out;
    }
    else if (cmd == UMSDOS_UNLINK_EMD) {
        /* #Specification: ioctl / UMSDOS_UNLINK_EMD
         * The umsdos_dirent field of the struct umsdos_ioctl is used
         * as is to remove an entry from the EMD of the directory.
         * No validation is done (yet). The mode field is used
         * to validate S_ISDIR or S_ISREG.
         * 
         * Return 0 if success.
         */
        struct umsdos_info info;

        /* This makes sure info.entry and info in general
         * is correctly initialised
         */
        memcpy (&info.entry, &data.umsdos_dirent,
            sizeof (data.umsdos_dirent));
        umsdos_parse (data.umsdos_dirent.name,
                data.umsdos_dirent.name_len, &info);
        ret = umsdos_delentry (dentry, &info,
                S_ISDIR (data.umsdos_dirent.mode));
        if (ret) {
            printk(KERN_WARNING
                "umsdos_ioctl: delentry %s/%s failed, ret=%d\n",
                dentry->d_name.name, info.entry.name, ret);
        }
        goto out;
    }
    else if (cmd == UMSDOS_UNLINK_DOS) {
        struct dentry *temp;

        /* #Specification: ioctl / UMSDOS_UNLINK_DOS
         * The dos_dirent field of the struct umsdos_ioctl is used to
         * execute a msdos_unlink operation. The d_name and d_reclen
         * fields are used.
         * 
         * Return 0 if success.
         */
        temp = umsdos_lookup_dentry(dentry, data.dos_dirent.d_name,
                        data.dos_dirent.d_reclen, 1);
        ret = PTR_ERR(temp);
        if (IS_ERR(temp))
            goto out;
        ret = -ENOENT;
        if (temp->d_inode) {
            ret = -EISDIR;
            if (!S_ISDIR(temp->d_inode->i_mode))
                ret = msdos_unlink (dir, temp);
            if (!ret)
                d_delete(temp);
        }
        dput (temp);
        goto out;
    }
    else if (cmd == UMSDOS_RMDIR_DOS) {
        struct dentry *temp;

        /* #Specification: ioctl / UMSDOS_RMDIR_DOS
         * The dos_dirent field of the struct umsdos_ioctl is used to
         * execute a msdos_rmdir operation. The d_name and d_reclen
         * fields are used.
         * 
         * Return 0 if success.
         */
        temp = umsdos_lookup_dentry(dentry, data.dos_dirent.d_name,
                        data.dos_dirent.d_reclen, 1);
        ret = PTR_ERR(temp);
        if (IS_ERR(temp))
            goto out;
        ret = -ENOENT;
        if (temp->d_inode) {
            ret = -ENOTDIR;
            if (S_ISDIR(temp->d_inode->i_mode))
                ret = msdos_rmdir (dir, temp);
            if (!ret)
                d_delete(temp);
        }
        dput (temp);
        goto out;

    } else if (cmd == UMSDOS_STAT_DOS) {
        /* #Specification: ioctl / UMSDOS_STAT_DOS
         * The dos_dirent field of the struct umsdos_ioctl is
         * used to execute a stat operation in the DOS directory.
         * The d_name and d_reclen fields are used.
         * 
         * The following field of umsdos_ioctl.stat are filled.
         * 
         * st_ino,st_mode,st_size,st_atime,st_mtime,st_ctime,
         * Return 0 if success.
         */
        struct dentry *dret;
        struct inode *inode;

        dret = umsdos_lookup_dentry(dentry, data.dos_dirent.d_name,
                        data.dos_dirent.d_reclen, 1);
        ret = PTR_ERR(dret);
        if (IS_ERR(dret))
            goto out;
        ret = -ENOENT;
        inode = dret->d_inode;
        if (inode) {
            data.stat.st_ino = inode->i_ino;
            data.stat.st_mode = inode->i_mode;
            data.stat.st_size = inode->i_size;
            data.stat.st_atime = inode->i_atime;
            data.stat.st_ctime = inode->i_ctime;
            data.stat.st_mtime = inode->i_mtime;
            ret = -EFAULT;
            if (!copy_to_user (&idata->stat, &data.stat, 
                        sizeof (data.stat)))
                ret = 0;
        }
        dput(dret);
        goto out;
    }
    else if (cmd == UMSDOS_DOS_SETUP) {
        /* #Specification: ioctl / UMSDOS_DOS_SETUP
         * The UMSDOS_DOS_SETUP ioctl allow changing the
         * default permission of the MS-DOS filesystem driver
         * on the fly.  The MS-DOS driver applies global permissions
         * to every file and directory. Normally these permissions
         * are controlled by a mount option. This is not
         * available for root partition, so a special utility
         * (umssetup) is provided to do this, normally in
         * /etc/rc.local.
         * 
         * Be aware that this applies ONLY to MS-DOS directories
         * (those without EMD --linux-.---). Umsdos directory
         * have independent (standard) permission for each
         * and every file.
         * 
         * The field umsdos_dirent provide the information needed.
         * umsdos_dirent.uid and gid sets the owner and group.
         * umsdos_dirent.mode set the permissions flags.
         */
        dir->i_sb->u.msdos_sb.options.fs_uid = data.umsdos_dirent.uid;
        dir->i_sb->u.msdos_sb.options.fs_gid = data.umsdos_dirent.gid;
        dir->i_sb->u.msdos_sb.options.fs_umask = data.umsdos_dirent.mode;
        ret = 0;
    }
out:
    Printk (("ioctl %d, returning %d\n", cmd, ret));
    return ret;
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0277 ]--