示例#1
0
/*
 * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
 * If FILE1 and FILE2 are special files, compare their salient characteristics
 * (i.e. major/minor device numbers, links, etc.
 */
int xcmp (const char *file1, const char *file2)
{
    char *buf1, *buf2;
    struct stat sb1, sb2;
    int fd1, fd2;
    int ret;

    if (CVS_LSTAT (file1, &sb1) < 0)
        error (1, errno, "cannot lstat %s", fn_root(file1));
    if (CVS_LSTAT (file2, &sb2) < 0)
        error (1, errno, "cannot lstat %s", fn_root(file2));

    /* If FILE1 and FILE2 are not the same file type, they are unequal. */
    if ((sb1.st_mode & S_IFMT) != (sb2.st_mode & S_IFMT))
        return 1;

    /* If FILE1 and FILE2 are symlinks, they are equal if they point to
       the same thing. */
    if (S_ISLNK (sb1.st_mode) && S_ISLNK (sb2.st_mode))
    {
        int result;
        buf1 = xreadlink (file1);
        buf2 = xreadlink (file2);
        result = (strcmp (buf1, buf2) == 0);
        xfree (buf1);
        xfree (buf2);
        return result;
    }

    /* If FILE1 and FILE2 are devices, they are equal if their device
       numbers match. */
    if (S_ISBLK (sb1.st_mode) || S_ISCHR (sb1.st_mode))
    {
#ifdef HAVE_STRUCT_STAT_ST_RDEV
        if (sb1.st_rdev == sb2.st_rdev)
            return 0;
        else
            return 1;
#else
        error (1, 0, "cannot compare device files on this system (%s and %s)",
               file1, file2);
#endif
    }

    if ((fd1 = CVS_OPEN (file1, O_RDONLY)) < 0)
        error (1, errno, "cannot open file %s for comparing", fn_root(file1));
    if ((fd2 = CVS_OPEN (file2, O_RDONLY)) < 0)
        error (1, errno, "cannot open file %s for comparing", fn_root(file2));

    /* A generic file compare routine might compare st_dev & st_ino here
       to see if the two files being compared are actually the same file.
       But that won't happen in CVS, so we won't bother. */

    if (sb1.st_size != sb2.st_size)
        ret = 1;
    else if (sb1.st_size == 0)
        ret = 0;
    else
    {
        /* FIXME: compute the optimal buffer size by computing the least
           common multiple of the files st_blocks field */
        size_t buf_size = 8 * 1024;
        size_t read1;
        size_t read2;

        buf1 = (char*)xmalloc (buf_size);
        buf2 = (char*)xmalloc (buf_size);

        do
        {
            read1 = block_read (fd1, buf1, buf_size);
            if (read1 == (size_t)-1)
                error (1, errno, "cannot read file %s for comparing", fn_root(file1));

            read2 = block_read (fd2, buf2, buf_size);
            if (read2 == (size_t)-1)
                error (1, errno, "cannot read file %s for comparing", fn_root(file2));

            /* assert (read1 == read2); */

            ret = memcmp(buf1, buf2, read1);
        } while (ret == 0 && read1 == buf_size);

        xfree (buf1);
        xfree (buf2);
    }

    (void) close (fd1);
    (void) close (fd2);
    return (ret);
}
示例#2
0
void hpfs_read_inode(struct inode *i)
{
	struct buffer_head *bh;
	struct fnode *fnode;
	struct super_block *sb = i->i_sb;
	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
	void *ea;
	int ea_size;

	if (!(fnode = hpfs_map_fnode(sb, i->i_ino, &bh))) {
		/*i->i_mode |= S_IFREG;
		i->i_mode &= ~0111;
		i->i_op = &hpfs_file_iops;
		i->i_fop = &hpfs_file_ops;
		i->i_nlink = 0;*/
		make_bad_inode(i);
		return;
	}
	if (hpfs_sb(i->i_sb)->sb_eas) {
		if ((ea = hpfs_get_ea(i->i_sb, fnode, "UID", &ea_size))) {
			if (ea_size == 2) {
				i->i_uid = le16_to_cpu(*(__le16*)ea);
				hpfs_inode->i_ea_uid = 1;
			}
			kfree(ea);
		}
		if ((ea = hpfs_get_ea(i->i_sb, fnode, "GID", &ea_size))) {
			if (ea_size == 2) {
				i->i_gid = le16_to_cpu(*(__le16*)ea);
				hpfs_inode->i_ea_gid = 1;
			}
			kfree(ea);
		}
		if ((ea = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &ea_size))) {
			kfree(ea);
			i->i_mode = S_IFLNK | 0777;
			i->i_op = &page_symlink_inode_operations;
			i->i_data.a_ops = &hpfs_symlink_aops;
			i->i_nlink = 1;
			i->i_size = ea_size;
			i->i_blocks = 1;
			brelse(bh);
			return;
		}
		if ((ea = hpfs_get_ea(i->i_sb, fnode, "MODE", &ea_size))) {
			int rdev = 0;
			umode_t mode = hpfs_sb(sb)->sb_mode;
			if (ea_size == 2) {
				mode = le16_to_cpu(*(__le16*)ea);
				hpfs_inode->i_ea_mode = 1;
			}
			kfree(ea);
			i->i_mode = mode;
			if (S_ISBLK(mode) || S_ISCHR(mode)) {
				if ((ea = hpfs_get_ea(i->i_sb, fnode, "DEV", &ea_size))) {
					if (ea_size == 4)
						rdev = le32_to_cpu(*(__le32*)ea);
					kfree(ea);
				}
			}
			if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
				brelse(bh);
				i->i_nlink = 1;
				i->i_size = 0;
				i->i_blocks = 1;
				init_special_inode(i, mode,
					new_decode_dev(rdev));
				return;
			}
		}
	}
	if (fnode->dirflag) {
		int n_dnodes, n_subdirs;
		i->i_mode |= S_IFDIR;
		i->i_op = &hpfs_dir_iops;
		i->i_fop = &hpfs_dir_ops;
		hpfs_inode->i_parent_dir = fnode->up;
		hpfs_inode->i_dno = fnode->u.external[0].disk_secno;
		if (hpfs_sb(sb)->sb_chk >= 2) {
			struct buffer_head *bh0;
			if (hpfs_map_fnode(sb, hpfs_inode->i_parent_dir, &bh0)) brelse(bh0);
		}
		n_dnodes = 0; n_subdirs = 0;
		hpfs_count_dnodes(i->i_sb, hpfs_inode->i_dno, &n_dnodes, &n_subdirs, NULL);
		i->i_blocks = 4 * n_dnodes;
		i->i_size = 2048 * n_dnodes;
		i->i_nlink = 2 + n_subdirs;
	} else {
		i->i_mode |= S_IFREG;
		if (!hpfs_inode->i_ea_mode) i->i_mode &= ~0111;
		i->i_op = &hpfs_file_iops;
		i->i_fop = &hpfs_file_ops;
		i->i_nlink = 1;
		i->i_size = fnode->file_size;
		i->i_blocks = ((i->i_size + 511) >> 9) + 1;
		i->i_data.a_ops = &hpfs_aops;
		hpfs_i(i)->mmu_private = i->i_size;
	}
	brelse(bh);
}
示例#3
0
static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
		      struct dentry *dentry)
{
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	struct inode *inode = old_dentry->d_inode;
	struct ubifs_inode *ui = ubifs_inode(inode);
	struct ubifs_inode *dir_ui = ubifs_inode(dir);
	int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
	struct ubifs_budget_req req = { .new_dent = 1, .dirtied_ino = 2,
				.dirtied_ino_d = ALIGN(ui->data_len, 8) };

	/*
	 * Budget request settings: new direntry, changing the target inode,
	 * changing the parent inode.
	 */

	dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu",
		dentry->d_name.len, dentry->d_name.name, inode->i_ino,
		inode->i_nlink, dir->i_ino);
	ubifs_assert(mutex_is_locked(&dir->i_mutex));
	ubifs_assert(mutex_is_locked(&inode->i_mutex));

	/*
	 * Return -ENOENT if we've raced with unlink and i_nlink is 0.  Doing
	 * otherwise has the potential to corrupt the orphan inode list.
	 *
	 * Indeed, consider a scenario when 'vfs_link(dirA/fileA)' and
	 * 'vfs_unlink(dirA/fileA, dirB/fileB)' race. 'vfs_link()' does not
	 * lock 'dirA->i_mutex', so this is possible. Both of the functions
	 * lock 'fileA->i_mutex' though. Suppose 'vfs_unlink()' wins, and takes
	 * 'fileA->i_mutex' mutex first. Suppose 'fileA->i_nlink' is 1. In this
	 * case 'ubifs_unlink()' will drop the last reference, and put 'inodeA'
	 * to the list of orphans. After this, 'vfs_link()' will link
	 * 'dirB/fileB' to 'inodeA'. This is a problem because, for example,
	 * the subsequent 'vfs_unlink(dirB/fileB)' will add the same inode
	 * to the list of orphans.
	 */
	 if (inode->i_nlink == 0)
		 return -ENOENT;

	err = dbg_check_synced_i_size(c, inode);
	if (err)
		return err;

	err = ubifs_budget_space(c, &req);
	if (err)
		return err;

	lock_2_inodes(dir, inode);
	inc_nlink(inode);
	atomic_inc(&inode->i_count);
	inode->i_ctime = ubifs_current_time(inode);
	dir->i_size += sz_change;
	dir_ui->ui_size = dir->i_size;
	dir->i_mtime = dir->i_ctime = inode->i_ctime;
	err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0);
	if (err)
		goto out_cancel;
	unlock_2_inodes(dir, inode);

	ubifs_release_budget(c, &req);
	d_instantiate(dentry, inode);
	return 0;

out_cancel:
	dir->i_size -= sz_change;
	dir_ui->ui_size = dir->i_size;
	drop_nlink(inode);
	unlock_2_inodes(dir, inode);
	ubifs_release_budget(c, &req);
	iput(inode);
	return err;
}

static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
{
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	struct inode *inode = dentry->d_inode;
	struct ubifs_inode *dir_ui = ubifs_inode(dir);
	int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
	int err, budgeted = 1;
	struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 };

	/*
	 * Budget request settings: deletion direntry, deletion inode (+1 for
	 * @dirtied_ino), changing the parent directory inode. If budgeting
	 * fails, go ahead anyway because we have extra space reserved for
	 * deletions.
	 */

	dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu",
		dentry->d_name.len, dentry->d_name.name, inode->i_ino,
		inode->i_nlink, dir->i_ino);
	ubifs_assert(mutex_is_locked(&dir->i_mutex));
	ubifs_assert(mutex_is_locked(&inode->i_mutex));
	err = dbg_check_synced_i_size(c, inode);
	if (err)
		return err;

	err = ubifs_budget_space(c, &req);
	if (err) {
		if (err != -ENOSPC)
			return err;
		budgeted = 0;
	}

	lock_2_inodes(dir, inode);
	inode->i_ctime = ubifs_current_time(dir);
	drop_nlink(inode);
	dir->i_size -= sz_change;
	dir_ui->ui_size = dir->i_size;
	dir->i_mtime = dir->i_ctime = inode->i_ctime;
	err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, 0);
	if (err)
		goto out_cancel;
	unlock_2_inodes(dir, inode);

	if (budgeted)
		ubifs_release_budget(c, &req);
	else {
		/* We've deleted something - clean the "no space" flags */
		c->bi.nospace = c->bi.nospace_rp = 0;
		smp_wmb();
	}
	return 0;

out_cancel:
	dir->i_size += sz_change;
	dir_ui->ui_size = dir->i_size;
	inc_nlink(inode);
	unlock_2_inodes(dir, inode);
	if (budgeted)
		ubifs_release_budget(c, &req);
	return err;
}

/**
 * check_dir_empty - check if a directory is empty or not.
 * @c: UBIFS file-system description object
 * @dir: VFS inode object of the directory to check
 *
 * This function checks if directory @dir is empty. Returns zero if the
 * directory is empty, %-ENOTEMPTY if it is not, and other negative error codes
 * in case of of errors.
 */
static int check_dir_empty(struct ubifs_info *c, struct inode *dir)
{
	struct qstr nm = { .name = NULL };
	struct ubifs_dent_node *dent;
	union ubifs_key key;
	int err;

	lowest_dent_key(c, &key, dir->i_ino);
	dent = ubifs_tnc_next_ent(c, &key, &nm);
	if (IS_ERR(dent)) {
		err = PTR_ERR(dent);
		if (err == -ENOENT)
			err = 0;
	} else {
		kfree(dent);
		err = -ENOTEMPTY;
	}
	return err;
}

static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
{
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	struct inode *inode = dentry->d_inode;
	int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
	int err, budgeted = 1;
	struct ubifs_inode *dir_ui = ubifs_inode(dir);
	struct ubifs_budget_req req = { .mod_dent = 1, .dirtied_ino = 2 };

	/*
	 * Budget request settings: deletion direntry, deletion inode and
	 * changing the parent inode. If budgeting fails, go ahead anyway
	 * because we have extra space reserved for deletions.
	 */

	dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len,
		dentry->d_name.name, inode->i_ino, dir->i_ino);
	ubifs_assert(mutex_is_locked(&dir->i_mutex));
	ubifs_assert(mutex_is_locked(&inode->i_mutex));
	err = check_dir_empty(c, dentry->d_inode);
	if (err)
		return err;

	err = ubifs_budget_space(c, &req);
	if (err) {
		if (err != -ENOSPC)
			return err;
		budgeted = 0;
	}

	lock_2_inodes(dir, inode);
	inode->i_ctime = ubifs_current_time(dir);
	clear_nlink(inode);
	drop_nlink(dir);
	dir->i_size -= sz_change;
	dir_ui->ui_size = dir->i_size;
	dir->i_mtime = dir->i_ctime = inode->i_ctime;
	err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 1, 0);
	if (err)
		goto out_cancel;
	unlock_2_inodes(dir, inode);

	if (budgeted)
		ubifs_release_budget(c, &req);
	else {
		/* We've deleted something - clean the "no space" flags */
		c->bi.nospace = c->bi.nospace_rp = 0;
		smp_wmb();
	}
	return 0;

out_cancel:
	dir->i_size += sz_change;
	dir_ui->ui_size = dir->i_size;
	inc_nlink(dir);
	inc_nlink(inode);
	inc_nlink(inode);
	unlock_2_inodes(dir, inode);
	if (budgeted)
		ubifs_release_budget(c, &req);
	return err;
}

static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
	struct inode *inode;
	struct ubifs_inode *dir_ui = ubifs_inode(dir);
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len);
	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 };

	/*
	 * Budget request settings: new inode, new direntry and changing parent
	 * directory inode.
	 */

	dbg_gen("dent '%.*s', mode %#x in dir ino %lu",
		dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino);

	err = ubifs_budget_space(c, &req);
	if (err)
		return err;

	inode = ubifs_new_inode(c, dir, S_IFDIR | mode);
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		goto out_budg;
	}

	mutex_lock(&dir_ui->ui_mutex);
	insert_inode_hash(inode);
	inc_nlink(inode);
	inc_nlink(dir);
	dir->i_size += sz_change;
	dir_ui->ui_size = dir->i_size;
	dir->i_mtime = dir->i_ctime = inode->i_ctime;
	err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0);
	if (err) {
		ubifs_err("cannot create directory, error %d", err);
		goto out_cancel;
	}
	mutex_unlock(&dir_ui->ui_mutex);

	ubifs_release_budget(c, &req);
	d_instantiate(dentry, inode);
	return 0;

out_cancel:
	dir->i_size -= sz_change;
	dir_ui->ui_size = dir->i_size;
	drop_nlink(dir);
	mutex_unlock(&dir_ui->ui_mutex);
	make_bad_inode(inode);
	iput(inode);
out_budg:
	ubifs_release_budget(c, &req);
	return err;
}

static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
		       int mode, dev_t rdev)
{
	struct inode *inode;
	struct ubifs_inode *ui;
	struct ubifs_inode *dir_ui = ubifs_inode(dir);
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	union ubifs_dev_desc *dev = NULL;
	int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
	int err, devlen = 0;
	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
					.new_ino_d = ALIGN(devlen, 8),
					.dirtied_ino = 1 };

	/*
	 * Budget request settings: new inode, new direntry and changing parent
	 * directory inode.
	 */

	dbg_gen("dent '%.*s' in dir ino %lu",
		dentry->d_name.len, dentry->d_name.name, dir->i_ino);

	if (!new_valid_dev(rdev))
		return -EINVAL;

	if (S_ISBLK(mode) || S_ISCHR(mode)) {
		dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
		if (!dev)
			return -ENOMEM;
		devlen = ubifs_encode_dev(dev, rdev);
	}

	err = ubifs_budget_space(c, &req);
	if (err) {
		kfree(dev);
		return err;
	}

	inode = ubifs_new_inode(c, dir, mode);
	if (IS_ERR(inode)) {
		kfree(dev);
		err = PTR_ERR(inode);
		goto out_budg;
	}

	init_special_inode(inode, inode->i_mode, rdev);
	inode->i_size = ubifs_inode(inode)->ui_size = devlen;
	ui = ubifs_inode(inode);
	ui->data = dev;
	ui->data_len = devlen;

	mutex_lock(&dir_ui->ui_mutex);
	dir->i_size += sz_change;
	dir_ui->ui_size = dir->i_size;
	dir->i_mtime = dir->i_ctime = inode->i_ctime;
	err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0);
	if (err)
		goto out_cancel;
	mutex_unlock(&dir_ui->ui_mutex);

	ubifs_release_budget(c, &req);
	insert_inode_hash(inode);
	d_instantiate(dentry, inode);
	return 0;

out_cancel:
	dir->i_size -= sz_change;
	dir_ui->ui_size = dir->i_size;
	mutex_unlock(&dir_ui->ui_mutex);
	make_bad_inode(inode);
	iput(inode);
out_budg:
	ubifs_release_budget(c, &req);
	return err;
}

static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
			 const char *symname)
{
	struct inode *inode;
	struct ubifs_inode *ui;
	struct ubifs_inode *dir_ui = ubifs_inode(dir);
	struct ubifs_info *c = dir->i_sb->s_fs_info;
	int err, len = strlen(symname);
	int sz_change = CALC_DENT_SIZE(dentry->d_name.len);
	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
					.new_ino_d = ALIGN(len, 8),
					.dirtied_ino = 1 };

	/*
	 * Budget request settings: new inode, new direntry and changing parent
	 * directory inode.
	 */

	dbg_gen("dent '%.*s', target '%s' in dir ino %lu", dentry->d_name.len,
		dentry->d_name.name, symname, dir->i_ino);

	if (len > UBIFS_MAX_INO_DATA)
		return -ENAMETOOLONG;

	err = ubifs_budget_space(c, &req);
	if (err)
		return err;

	inode = ubifs_new_inode(c, dir, S_IFLNK | S_IRWXUGO);
	if (IS_ERR(inode)) {
		err = PTR_ERR(inode);
		goto out_budg;
	}

	ui = ubifs_inode(inode);
	ui->data = kmalloc(len + 1, GFP_NOFS);
	if (!ui->data) {
		err = -ENOMEM;
		goto out_inode;
	}

	memcpy(ui->data, symname, len);
	((char *)ui->data)[len] = '\0';
	/*
	 * The terminating zero byte is not written to the flash media and it
	 * is put just to make later in-memory string processing simpler. Thus,
	 * data length is @len, not @len + %1.
	 */
	ui->data_len = len;
	inode->i_size = ubifs_inode(inode)->ui_size = len;

	mutex_lock(&dir_ui->ui_mutex);
	dir->i_size += sz_change;
	dir_ui->ui_size = dir->i_size;
	dir->i_mtime = dir->i_ctime = inode->i_ctime;
	err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0);
	if (err)
		goto out_cancel;
	mutex_unlock(&dir_ui->ui_mutex);

	ubifs_release_budget(c, &req);
	insert_inode_hash(inode);
	d_instantiate(dentry, inode);
	return 0;

out_cancel:
	dir->i_size -= sz_change;
	dir_ui->ui_size = dir->i_size;
	mutex_unlock(&dir_ui->ui_mutex);
out_inode:
	make_bad_inode(inode);
	iput(inode);
out_budg:
	ubifs_release_budget(c, &req);
	return err;
}

/**
 * lock_3_inodes - a wrapper for locking three UBIFS inodes.
 * @inode1: first inode
 * @inode2: second inode
 * @inode3: third inode
 *
 * This function is used for 'ubifs_rename()' and @inode1 may be the same as
 * @inode2 whereas @inode3 may be %NULL.
 *
 * We do not implement any tricks to guarantee strict lock ordering, because
 * VFS has already done it for us on the @i_mutex. So this is just a simple
 * wrapper function.
 */
static void lock_3_inodes(struct inode *inode1, struct inode *inode2,
			  struct inode *inode3)
{
	mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
	if (inode2 != inode1)
		mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
	if (inode3)
		mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3);
}

/**
 * unlock_3_inodes - a wrapper for unlocking three UBIFS inodes for rename.
 * @inode1: first inode
 * @inode2: second inode
 * @inode3: third inode
 */
static void unlock_3_inodes(struct inode *inode1, struct inode *inode2,
			    struct inode *inode3)
{
	if (inode3)
		mutex_unlock(&ubifs_inode(inode3)->ui_mutex);
	if (inode1 != inode2)
		mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
	mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
}

static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
			struct inode *new_dir, struct dentry *new_dentry)
{
	struct ubifs_info *c = old_dir->i_sb->s_fs_info;
	struct inode *old_inode = old_dentry->d_inode;
	struct inode *new_inode = new_dentry->d_inode;
	struct ubifs_inode *old_inode_ui = ubifs_inode(old_inode);
	int err, release, sync = 0, move = (new_dir != old_dir);
	int is_dir = S_ISDIR(old_inode->i_mode);
	int unlink = !!new_inode;
	int new_sz = CALC_DENT_SIZE(new_dentry->d_name.len);
	int old_sz = CALC_DENT_SIZE(old_dentry->d_name.len);
	struct ubifs_budget_req req = { .new_dent = 1, .mod_dent = 1,
					.dirtied_ino = 3 };
	struct ubifs_budget_req ino_req = { .dirtied_ino = 1,
			.dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
	struct timespec time;

	/*
	 * Budget request settings: deletion direntry, new direntry, removing
	 * the old inode, and changing old and new parent directory inodes.
	 *
	 * However, this operation also marks the target inode as dirty and
	 * does not write it, so we allocate budget for the target inode
	 * separately.
	 */

	dbg_gen("dent '%.*s' ino %lu in dir ino %lu to dent '%.*s' in "
		"dir ino %lu", old_dentry->d_name.len, old_dentry->d_name.name,
		old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len,
		new_dentry->d_name.name, new_dir->i_ino);
	ubifs_assert(mutex_is_locked(&old_dir->i_mutex));
	ubifs_assert(mutex_is_locked(&new_dir->i_mutex));
	if (unlink)
		ubifs_assert(mutex_is_locked(&new_inode->i_mutex));


	if (unlink && is_dir) {
		err = check_dir_empty(c, new_inode);
		if (err)
			return err;
	}

	err = ubifs_budget_space(c, &req);
	if (err)
		return err;
	err = ubifs_budget_space(c, &ino_req);
	if (err) {
		ubifs_release_budget(c, &req);
		return err;
	}

	lock_3_inodes(old_dir, new_dir, new_inode);

	/*
	 * Like most other Unix systems, set the @i_ctime for inodes on a
	 * rename.
	 */
	time = ubifs_current_time(old_dir);
	old_inode->i_ctime = time;

	/* We must adjust parent link count when renaming directories */
	if (is_dir) {
		if (move) {
			/*
			 * @old_dir loses a link because we are moving
			 * @old_inode to a different directory.
			 */
			drop_nlink(old_dir);
			/*
			 * @new_dir only gains a link if we are not also
			 * overwriting an existing directory.
			 */
			if (!unlink)
				inc_nlink(new_dir);
		} else {
			/*
			 * @old_inode is not moving to a different directory,
			 * but @old_dir still loses a link if we are
			 * overwriting an existing directory.
			 */
			if (unlink)
				drop_nlink(old_dir);
		}
	}

	old_dir->i_size -= old_sz;
	ubifs_inode(old_dir)->ui_size = old_dir->i_size;
	old_dir->i_mtime = old_dir->i_ctime = time;
	new_dir->i_mtime = new_dir->i_ctime = time;

	/*
	 * And finally, if we unlinked a direntry which happened to have the
	 * same name as the moved direntry, we have to decrement @i_nlink of
	 * the unlinked inode and change its ctime.
	 */
	if (unlink) {
		/*
		 * Directories cannot have hard-links, so if this is a
		 * directory, decrement its @i_nlink twice because an empty
		 * directory has @i_nlink 2.
		 */
		if (is_dir)
			drop_nlink(new_inode);
		new_inode->i_ctime = time;
		drop_nlink(new_inode);
	} else {
		new_dir->i_size += new_sz;
		ubifs_inode(new_dir)->ui_size = new_dir->i_size;
	}

	/*
	 * Do not ask 'ubifs_jnl_rename()' to flush write-buffer if @old_inode
	 * is dirty, because this will be done later on at the end of
	 * 'ubifs_rename()'.
	 */
	if (IS_SYNC(old_inode)) {
		sync = IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir);
		if (unlink && IS_SYNC(new_inode))
			sync = 1;
	}
	err = ubifs_jnl_rename(c, old_dir, old_dentry, new_dir, new_dentry,
			       sync);
	if (err)
		goto out_cancel;

	unlock_3_inodes(old_dir, new_dir, new_inode);
	ubifs_release_budget(c, &req);

	mutex_lock(&old_inode_ui->ui_mutex);
	release = old_inode_ui->dirty;
	mark_inode_dirty_sync(old_inode);
	mutex_unlock(&old_inode_ui->ui_mutex);

	if (release)
		ubifs_release_budget(c, &ino_req);
	if (IS_SYNC(old_inode))
		err = old_inode->i_sb->s_op->write_inode(old_inode, NULL);
	return err;

out_cancel:
	if (unlink) {
		if (is_dir)
			inc_nlink(new_inode);
		inc_nlink(new_inode);
	} else {
		new_dir->i_size -= new_sz;
		ubifs_inode(new_dir)->ui_size = new_dir->i_size;
	}
	old_dir->i_size += old_sz;
	ubifs_inode(old_dir)->ui_size = old_dir->i_size;
	if (is_dir) {
		if (move) {
			inc_nlink(old_dir);
			if (!unlink)
				drop_nlink(new_dir);
		} else {
			if (unlink)
				inc_nlink(old_dir);
		}
	}
	unlock_3_inodes(old_dir, new_dir, new_inode);
	ubifs_release_budget(c, &ino_req);
	ubifs_release_budget(c, &req);
	return err;
}

int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
		  struct kstat *stat)
{
	loff_t size;
	struct inode *inode = dentry->d_inode;
	struct ubifs_inode *ui = ubifs_inode(inode);

	mutex_lock(&ui->ui_mutex);
	stat->dev = inode->i_sb->s_dev;
	stat->ino = inode->i_ino;
	stat->mode = inode->i_mode;
	stat->nlink = inode->i_nlink;
	stat->uid = inode->i_uid;
	stat->gid = inode->i_gid;
	stat->rdev = inode->i_rdev;
	stat->atime = inode->i_atime;
	stat->mtime = inode->i_mtime;
	stat->ctime = inode->i_ctime;
	stat->blksize = UBIFS_BLOCK_SIZE;
	stat->size = ui->ui_size;

	/*
	 * Unfortunately, the 'stat()' system call was designed for block
	 * device based file systems, and it is not appropriate for UBIFS,
	 * because UBIFS does not have notion of "block". For example, it is
	 * difficult to tell how many block a directory takes - it actually
	 * takes less than 300 bytes, but we have to round it to block size,
	 * which introduces large mistake. This makes utilities like 'du' to
	 * report completely senseless numbers. This is the reason why UBIFS
	 * goes the same way as JFFS2 - it reports zero blocks for everything
	 * but regular files, which makes more sense than reporting completely
	 * wrong sizes.
	 */
	if (S_ISREG(inode->i_mode)) {
		size = ui->xattr_size;
		size += stat->size;
		size = ALIGN(size, UBIFS_BLOCK_SIZE);
		/*
		 * Note, user-space expects 512-byte blocks count irrespectively
		 * of what was reported in @stat->size.
		 */
		stat->blocks = size >> 9;
	} else
		stat->blocks = 0;
	mutex_unlock(&ui->ui_mutex);
	return 0;
}

const struct inode_operations ubifs_dir_inode_operations = {
	.lookup      = ubifs_lookup,
	.create      = ubifs_create,
	.link        = ubifs_link,
	.symlink     = ubifs_symlink,
	.unlink      = ubifs_unlink,
	.mkdir       = ubifs_mkdir,
	.rmdir       = ubifs_rmdir,
	.mknod       = ubifs_mknod,
	.rename      = ubifs_rename,
	.setattr     = ubifs_setattr,
	.getattr     = ubifs_getattr,
#ifdef CONFIG_UBIFS_FS_XATTR
	.setxattr    = ubifs_setxattr,
	.getxattr    = ubifs_getxattr,
	.listxattr   = ubifs_listxattr,
	.removexattr = ubifs_removexattr,
#endif
};

const struct file_operations ubifs_dir_operations = {
	.llseek         = ubifs_dir_llseek,
	.release        = ubifs_dir_release,
	.read           = generic_read_dir,
	.readdir        = ubifs_readdir,
	.fsync          = ubifs_fsync,
	.unlocked_ioctl = ubifs_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl   = ubifs_compat_ioctl,
#endif
};
示例#4
0
int fuse_valid_type(int m)
{
	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
}
示例#5
0
static int
main_init(int argc, const char *argv[], Source **sp, struct block **lp)
{
	int argi, i;
	Source *s = NULL;
	struct block *l;
	unsigned char restricted_shell, errexit, utf_flag;
	char *cp;
	const char *ccp, **wp;
	struct tbl *vp;
	struct stat s_stdin;
#if !defined(_PATH_DEFPATH) && defined(_CS_PATH)
	ssize_t k;
#endif

#ifdef __OS2__
	for (i = 0; i < 3; ++i)
		if (!isatty(i))
			setmode(i, O_BINARY);
#endif

	/* do things like getpgrp() et al. */
	chvt_reinit();

	/* make sure argv[] is sane, for weird OSes */
	if (!*argv) {
		argv = empty_argv;
		argc = 1;
	}
	kshname = argv[0];

	/* initialise permanent Area */
	ainit(&aperm);

	/* set up base environment */
	env.type = E_NONE;
	ainit(&env.area);
	/* set up global l->vars and l->funs */
	newblock();

	/* Do this first so output routines (eg, errorf, shellf) can work */
	initio();

	/* determine the basename (without '-' or path) of the executable */
	ccp = kshname;
	goto begin_parse_kshname;
	while ((i = ccp[argi++])) {
		if (i == '/') {
			ccp += argi;
 begin_parse_kshname:
			argi = 0;
			if (*ccp == '-')
				++ccp;
		}
	}
	if (!*ccp)
		ccp = empty_argv[0];

	/*
	 * Turn on nohup by default. (AT&T ksh does not have a nohup
	 * option - it always sends the hup).
	 */
	Flag(FNOHUP) = 1;

	/*
	 * Turn on brace expansion by default. AT&T kshs that have
	 * alternation always have it on.
	 */
	Flag(FBRACEEXPAND) = 1;

	/*
	 * Turn on "set -x" inheritance by default.
	 */
	Flag(FXTRACEREC) = 1;

	/* define built-in commands and see if we were called as one */
	ktinit(APERM, &builtins,
	    /* currently up to 54 builtins: 75% of 128 = 2^7 */
	    7);
	for (i = 0; mkshbuiltins[i].name != NULL; i++)
		if (!strcmp(ccp, builtin(mkshbuiltins[i].name,
		    mkshbuiltins[i].func)))
			Flag(FAS_BUILTIN) = 1;

	if (!Flag(FAS_BUILTIN)) {
		/* check for -T option early */
		argi = parse_args(argv, OF_FIRSTTIME, NULL);
		if (argi < 0)
			return (1);

#if defined(MKSH_BINSHPOSIX) || defined(MKSH_BINSHREDUCED)
		/* are we called as -sh or /bin/sh or so? */
		if (!strcmp(ccp, "sh" MKSH_EXE_EXT)) {
			/* either also turns off braceexpand */
#ifdef MKSH_BINSHPOSIX
			/* enable better POSIX conformance */
			change_flag(FPOSIX, OF_FIRSTTIME, true);
#endif
#ifdef MKSH_BINSHREDUCED
			/* enable kludge/compat mode */
			change_flag(FSH, OF_FIRSTTIME, true);
#endif
		}
#endif
	}

	initvar();

	initctypes();

	inittraps();

	coproc_init();

	/* set up variable and command dictionaries */
	ktinit(APERM, &taliases, 0);
	ktinit(APERM, &aliases, 0);
#ifndef MKSH_NOPWNAM
	ktinit(APERM, &homedirs, 0);
#endif

	/* define shell keywords */
	initkeywords();

	init_histvec();

	/* initialise tty size before importing environment */
	change_winsz();

#ifdef _PATH_DEFPATH
	def_path = _PATH_DEFPATH;
#else
#ifdef _CS_PATH
	if ((k = confstr(_CS_PATH, NULL, 0)) > 0 &&
	    confstr(_CS_PATH, cp = alloc(k + 1, APERM), k + 1) == k + 1)
		def_path = cp;
	else
#endif
		/*
		 * this is uniform across all OSes unless it
		 * breaks somewhere; don't try to optimise,
		 * e.g. add stuff for Interix or remove /usr
		 * for HURD, because e.g. Debian GNU/HURD is
		 * "keeping a regular /usr"; this is supposed
		 * to be a sane 'basic' default PATH
		 */
		def_path = MKSH_UNIXROOT "/bin" MKSH_PATHSEPS
		    MKSH_UNIXROOT "/usr/bin" MKSH_PATHSEPS
		    MKSH_UNIXROOT "/sbin" MKSH_PATHSEPS
		    MKSH_UNIXROOT "/usr/sbin";
#endif

	/*
	 * Set PATH to def_path (will set the path global variable).
	 * (import of environment below will probably change this setting).
	 */
	vp = global("PATH");
	/* setstr can't fail here */
	setstr(vp, def_path, KSH_RETURN_ERROR);

#ifndef MKSH_NO_CMDLINE_EDITING
	/*
	 * Set edit mode to emacs by default, may be overridden
	 * by the environment or the user. Also, we want tab completion
	 * on in vi by default.
	 */
	change_flag(FEMACS, OF_SPECIAL, true);
#if !MKSH_S_NOVI
	Flag(FVITABCOMPLETE) = 1;
#endif
#endif

	/* import environment */
	if (environ != NULL) {
		wp = (const char **)environ;
		while (*wp != NULL) {
			rndpush(*wp);
			typeset(*wp, IMPORT | EXPORT, 0, 0, 0);
			++wp;
		}
	}

	/* for security */
	typeset(initifs, 0, 0, 0, 0);

	/* assign default shell variable values */
	substitute(initsubs, 0);

	/* Figure out the current working directory and set $PWD */
	vp = global("PWD");
	cp = str_val(vp);
	/* Try to use existing $PWD if it is valid */
	set_current_wd((mksh_abspath(cp) && test_eval(NULL, TO_FILEQ, cp, ".",
	    true)) ? cp : NULL);
	if (current_wd[0])
		simplify_path(current_wd);
	/* Only set pwd if we know where we are or if it had a bogus value */
	if (current_wd[0] || *cp)
		/* setstr can't fail here */
		setstr(vp, current_wd, KSH_RETURN_ERROR);

	for (wp = initcoms; *wp != NULL; wp++) {
		shcomexec(wp);
		while (*wp != NULL)
			wp++;
	}
	setint_n(global("OPTIND"), 1, 10);

	kshuid = getuid();
	kshgid = getgid();
	kshegid = getegid();

	safe_prompt = ksheuid ? "$ " : "# ";
	vp = global("PS1");
	/* Set PS1 if unset or we are root and prompt doesn't contain a # */
	if (!(vp->flag & ISSET) ||
	    (!ksheuid && !strchr(str_val(vp), '#')))
		/* setstr can't fail here */
		setstr(vp, safe_prompt, KSH_RETURN_ERROR);
	setint_n((vp = global("BASHPID")), 0, 10);
	vp->flag |= INT_U;
	setint_n((vp = global("PGRP")), (mksh_uari_t)kshpgrp, 10);
	vp->flag |= INT_U;
	setint_n((vp = global("PPID")), (mksh_uari_t)kshppid, 10);
	vp->flag |= INT_U;
	setint_n((vp = global("USER_ID")), (mksh_uari_t)ksheuid, 10);
	vp->flag |= INT_U;
	setint_n((vp = global("KSHUID")), (mksh_uari_t)kshuid, 10);
	vp->flag |= INT_U;
	setint_n((vp = global("KSHEGID")), (mksh_uari_t)kshegid, 10);
	vp->flag |= INT_U;
	setint_n((vp = global("KSHGID")), (mksh_uari_t)kshgid, 10);
	vp->flag |= INT_U;
	setint_n((vp = global("RANDOM")), rndsetup(), 10);
	vp->flag |= INT_U;
	setint_n((vp_pipest = global("PIPESTATUS")), 0, 10);

	/* Set this before parsing arguments */
	Flag(FPRIVILEGED) = (kshuid != ksheuid || kshgid != kshegid) ? 2 : 0;

	/* this to note if monitor is set on command line (see below) */
#ifndef MKSH_UNEMPLOYED
	Flag(FMONITOR) = 127;
#endif
	/* this to note if utf-8 mode is set on command line (see below) */
	UTFMODE = 2;

	if (!Flag(FAS_BUILTIN)) {
		argi = parse_args(argv, OF_CMDLINE, NULL);
		if (argi < 0)
			return (1);
	}

	/* process this later only, default to off (hysterical raisins) */
	utf_flag = UTFMODE;
	UTFMODE = 0;

	if (Flag(FAS_BUILTIN)) {
		/* auto-detect from environment variables, always */
		utf_flag = 3;
	} else if (Flag(FCOMMAND)) {
		s = pushs(SSTRINGCMDLINE, ATEMP);
		if (!(s->start = s->str = argv[argi++]))
			errorf("%s %s", "-c", "requires an argument");
		while (*s->str) {
			if (*s->str != ' ' && ctype(*s->str, C_QUOTE))
				break;
			s->str++;
		}
		if (!*s->str)
			s->flags |= SF_MAYEXEC;
		s->str = s->start;
#ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
		/* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */
		if (Flag(FSH) && argv[argi] && !strcmp(argv[argi], "--"))
			++argi;
#endif
		if (argv[argi])
			kshname = argv[argi++];
	} else if (argi < argc && !Flag(FSTDIN)) {
		s = pushs(SFILE, ATEMP);
#ifdef __OS2__
		/*
		 * A bug in OS/2 extproc (like shebang) handling makes
		 * it not pass the full pathname of a script, so we need
		 * to search for it. This changes the behaviour of a
		 * simple "mksh foo", but can't be helped.
		 */
		s->file = search_path(argv[argi++], path, X_OK, NULL);
		if (!s->file || !*s->file)
			s->file = argv[argi - 1];
#else
		s->file = argv[argi++];
#endif
		s->u.shf = shf_open(s->file, O_RDONLY, 0,
		    SHF_MAPHI | SHF_CLEXEC);
		if (s->u.shf == NULL) {
			shl_stdout_ok = false;
			warningf(true, "%s: %s", s->file, cstrerror(errno));
			/* mandated by SUSv4 */
			exstat = 127;
			unwind(LERROR);
		}
		kshname = s->file;
	} else {
		Flag(FSTDIN) = 1;
		s = pushs(SSTDIN, ATEMP);
		s->file = "<stdin>";
		s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0),
		    NULL);
		if (isatty(0) && isatty(2)) {
			Flag(FTALKING) = Flag(FTALKING_I) = 1;
			/* The following only if isatty(0) */
			s->flags |= SF_TTY;
			s->u.shf->flags |= SHF_INTERRUPT;
			s->file = NULL;
		}
	}

	/* this bizarreness is mandated by POSIX */
	if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode) &&
	    Flag(FTALKING))
		reset_nonblock(0);

	/* initialise job control */
	j_init();
	/* do this after j_init() which calls tty_init_state() */
	if (Flag(FTALKING)) {
		if (utf_flag == 2) {
#ifndef MKSH_ASSUME_UTF8
			/* auto-detect from locale or environment */
			utf_flag = 4;
#else /* this may not be an #elif */
#if MKSH_ASSUME_UTF8
			utf_flag = 1;
#else
			/* always disable UTF-8 (for interactive) */
			utf_flag = 0;
#endif
#endif
		}
#ifndef MKSH_NO_CMDLINE_EDITING
		x_init();
#endif
	}

#ifdef SIGWINCH
	sigtraps[SIGWINCH].flags |= TF_SHELL_USES;
	setsig(&sigtraps[SIGWINCH], x_sigwinch,
	    SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP);
#endif

	l = e->loc;
	if (Flag(FAS_BUILTIN)) {
		l->argc = argc;
		l->argv = argv;
		l->argv[0] = ccp;
	} else {
		l->argc = argc - argi;
		/*
		 * allocate a new array because otherwise, when we modify
		 * it in-place, ps(1) output changes; the meaning of argc
		 * here is slightly different as it excludes kshname, and
		 * we add a trailing NULL sentinel as well
		 */
		l->argv = alloc2(l->argc + 2, sizeof(void *), APERM);
		l->argv[0] = kshname;
		memcpy(&l->argv[1], &argv[argi], l->argc * sizeof(void *));
		l->argv[l->argc + 1] = NULL;
		getopts_reset(1);
	}

	/* divine the initial state of the utf8-mode Flag */
	ccp = null;
	switch (utf_flag) {

	/* auto-detect from locale or environment */
	case 4:
#if HAVE_SETLOCALE_CTYPE
		ccp = setlocale(LC_CTYPE, "");
#if HAVE_LANGINFO_CODESET
		if (!isuc(ccp))
			ccp = nl_langinfo(CODESET);
#endif
		if (!isuc(ccp))
			ccp = null;
		/* FALLTHROUGH */
#endif

	/* auto-detect from environment */
	case 3:
		/* these were imported from environ earlier */
		if (ccp == null)
			ccp = str_val(global("LC_ALL"));
		if (ccp == null)
			ccp = str_val(global("LC_CTYPE"));
		if (ccp == null)
			ccp = str_val(global("LANG"));
		UTFMODE = isuc(ccp);
		break;

	/* not set on command line, not FTALKING */
	case 2:
	/* unknown values */
	default:
		utf_flag = 0;
		/* FALLTHROUGH */

	/* known values */
	case 1:
	case 0:
		UTFMODE = utf_flag;
		break;
	}

	/* Disable during .profile/ENV reading */
	restricted_shell = Flag(FRESTRICTED);
	Flag(FRESTRICTED) = 0;
	errexit = Flag(FERREXIT);
	Flag(FERREXIT) = 0;

	/*
	 * Do this before profile/$ENV so that if it causes problems in them,
	 * user will know why things broke.
	 */
	if (!current_wd[0] && Flag(FTALKING))
		warningf(false, "can't determine current directory");

	if (Flag(FLOGIN))
		include(MKSH_SYSTEM_PROFILE, 0, NULL, true);
	if (!Flag(FPRIVILEGED)) {
		if (Flag(FLOGIN))
			include(substitute("$HOME/.profile", 0), 0, NULL, true);
		if (Flag(FTALKING)) {
			cp = substitute(substitute("${ENV:-" MKSHRC_PATH "}",
			    0), DOTILDE);
			if (cp[0] != '\0')
				include(cp, 0, NULL, true);
		}
	} else {
		include(MKSH_SUID_PROFILE, 0, NULL, true);
		/* turn off -p if not set explicitly */
		if (Flag(FPRIVILEGED) != 1)
			change_flag(FPRIVILEGED, OF_INTERNAL, false);
	}

	if (restricted_shell) {
		shcomexec(restr_com);
		/* After typeset command... */
		Flag(FRESTRICTED) = 1;
	}
	Flag(FERREXIT) = errexit;

	if (Flag(FTALKING) && s)
		hist_init(s);
	else
		/* set after ENV */
		Flag(FTRACKALL) = 1;

	alarm_init();

	*sp = s;
	*lp = l;
	return (0);
}
示例#6
0
void
openAudioOutDevice (dsd_opts * opts, int speed)
{
  // get info of device/file
  struct stat stat_buf;
  if(stat(opts->audio_out_dev, &stat_buf) != 0) {
    printf("Error, couldn't open %s\n", opts->audio_out_dev);
    exit(1);
  }

  if( !(S_ISCHR(stat_buf.st_mode) || S_ISBLK(stat_buf.st_mode))) { // this is not a device
    printf("Error, %s is not a device. use -w filename for wav output.\n", opts->audio_out_dev);
    exit(1);
  }
#ifdef SOLARIS
  sample_info_t aset, aget;

  opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
  if (opts->audio_out_fd == -1)
    {
      printf ("Error, couldn't open %s\n", opts->audio_out_dev);
      exit (1);
    }

  // get current
  ioctl (opts->audio_out_fd, AUDIO_GETINFO, &aset);

  aset.record.sample_rate = speed;
  aset.play.sample_rate = speed;
  aset.record.channels = 1;
  aset.play.channels = 1;
  aset.record.precision = 16;
  aset.play.precision = 16;
  aset.record.encoding = AUDIO_ENCODING_LINEAR;
  aset.play.encoding = AUDIO_ENCODING_LINEAR;

  if (ioctl (opts->audio_out_fd, AUDIO_SETINFO, &aset) == -1)
    {
      printf ("Error setting sample device parameters\n");
      exit (1);
    }
#endif

#if defined(BSD) && !defined(__APPLE__)

  int fmt;

  opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
  if (opts->audio_out_fd == -1)
    {
      printf ("Error, couldn't open %s\n", opts->audio_out_dev);
      opts->audio_out = 0;
      exit(1);
    }

  fmt = 0;
  if (ioctl (opts->audio_out_fd, SNDCTL_DSP_RESET) < 0)
    {
      printf ("ioctl reset error \n");
    }
  fmt = speed;
  if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
    {
      printf ("ioctl speed error \n");
    }
  fmt = 0;
  if (ioctl (opts->audio_out_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
    {
      printf ("ioctl stereo error \n");
    }
  fmt = AFMT_S16_LE;
  if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
    {
      printf ("ioctl setfmt error \n");
    }

#endif
  printf ("Audio Out Device: %s\n", opts->audio_out_dev);
}
示例#7
0
/* Store at most BUFLEN character of the pathname of the terminal FD is
   open on in BUF.  Return 0 on success,  otherwise an error number.  */
int
__ttyname_r (int fd, char *buf, size_t buflen)
{
  char procname[30];
  struct stat64 st, st1;
  int dostat = 0;
  int save = errno;

  /* Test for the absolute minimal size.  This makes life easier inside
     the loop.  */
  if (!buf)
    {
      __set_errno (EINVAL);
      return EINVAL;
    }

  if (buflen < sizeof ("/dev/pts/"))
    {
      __set_errno (ERANGE);
      return ERANGE;
    }

  /* isatty check, tcgetattr is used because it sets the correct
     errno (EBADF resp. ENOTTY) on error.  */
  struct termios term;
  if (__builtin_expect (__tcgetattr (fd, &term) < 0, 0))
    return errno;

  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
    return errno;

  /* We try using the /proc filesystem.  */
  *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';

  ssize_t ret = __readlink (procname, buf, buflen - 1);
  if (__builtin_expect (ret == -1 && errno == ENAMETOOLONG, 0))
    {
      __set_errno (ERANGE);
      return ERANGE;
    }

  if (__builtin_expect (ret != -1, 1))
    {
#define UNREACHABLE_LEN strlen ("(unreachable)")
      if (ret > UNREACHABLE_LEN
	  && memcmp (buf, "(unreachable)", UNREACHABLE_LEN) == 0)
	{
	  memmove (buf, buf + UNREACHABLE_LEN, ret - UNREACHABLE_LEN);
	  ret -= UNREACHABLE_LEN;
	}

      /* readlink need not terminate the string.  */
      buf[ret] = '\0';

      /* Verify readlink result, fall back on iterating through devices.  */
      if (buf[0] == '/'
	  && __xstat64 (_STAT_VER, buf, &st1) == 0
#ifdef _STATBUF_ST_RDEV
	  && S_ISCHR (st1.st_mode)
	  && st1.st_rdev == st.st_rdev
#else
	  && st1.st_ino == st.st_ino
	  && st1.st_dev == st.st_dev
#endif
	  )
	return 0;
    }

  /* Prepare the result buffer.  */
  memcpy (buf, "/dev/pts/", sizeof ("/dev/pts/"));
  buflen -= sizeof ("/dev/pts/") - 1;

  if (__xstat64 (_STAT_VER, buf, &st1) == 0 && S_ISDIR (st1.st_mode))
    {
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
			  &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
			  &dostat);
#endif
    }
  else
    {
      __set_errno (save);
      ret = ENOENT;
    }

  if (ret && dostat != -1)
    {
      buf[sizeof ("/dev/") - 1] = '\0';
      buflen += sizeof ("pts/") - 1;
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save,
			  &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save,
			  &dostat);
#endif
    }

  if (ret && dostat != -1)
    {
      buf[sizeof ("/dev/") - 1] = '\0';
      dostat = 1;
#ifdef _STATBUF_ST_RDEV
      ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino,
			  save, &dostat);
#else
      ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino,
			  save, &dostat);
#endif
    }

  return ret;
}
示例#8
0
static int compare_files(const char *inp, const char *out, const char *output_prefix) {
	struct stat st_in, st_out;
	int ret = 0;

	if (lstat(inp, &st_in)) {
		perror("lstat(INPUT) failed");
		return 2;
	}
	if (lstat(out, &st_out)) {
		perror("lstat(OUTPUT) failed");
		return 2;
	}

	if (st_in.st_size != st_out.st_size) {
		print_diff(output_prefix, "Size differs",
				st_in.st_size, st_out.st_size);
		ret = 1;
	}

	if (st_in.st_size > 0) {
		if (S_ISREG(st_in.st_mode)) {
			FILE *f = fopen(out, "rb");
			char buf[sizeof(randumness)];

			if (!f) {
				perror("Unable to open output file for reading");
				ret = 2;
			} else {
				if (fread(buf, sizeof(buf), 1, f) != 1) {
					perror("Output file read failed");
					ret = 2;
				} else if (memcmp(buf, randumness, sizeof(buf))) {
					fprintf(stderr, "[%s] File contents differ\n",
							output_prefix);
					ret = 1;
				}

				fclose(f);
			}
		} else if (S_ISLNK(st_in.st_mode)) {
			char buf[sizeof(ex_linkdest)];

			switch (readlink(out, buf, sizeof(buf))) {
				case -1:
					perror("readlink(OUTPUT) failed");
					ret = 2;
					break;
				case sizeof(buf) - 1:
					if (memcmp(buf, ex_linkdest, sizeof(buf))) {
						buf[sizeof(buf) - 1] = 0;
						fprintf(stderr, "[%s] Symlink target differs: %s vs %s\n",
								output_prefix, ex_linkdest, buf);
						ret = 1;
					}
					break;
				default:
					fprintf(stderr, "[%s] Invalid length when getting symlink target\n",
							output_prefix);
			}
		} else {
			fprintf(stderr, "[%s] Unhandled non-empty file format\n",
					output_prefix);
			ret = 77;
		}
	}

#ifdef S_ISCHR
	if (S_ISCHR(st_in.st_mode) && st_in.st_rdev != st_out.st_rdev) {
		print_diff_x(output_prefix, "Character device rdev differs",
				st_in.st_rdev, st_out.st_rdev);
		ret = 1;
	}
#endif
#ifdef S_ISBLK
	if (S_ISBLK(st_in.st_mode) && st_in.st_rdev != st_out.st_rdev) {
		print_diff_x(output_prefix, "Block device rdev differs",
				st_in.st_rdev, st_out.st_rdev);
		ret = 1;
	}
#endif

	if (st_in.st_mode != st_out.st_mode) {
		print_diff_x(output_prefix, "Mode differs",
				st_in.st_mode, st_out.st_mode);
		ret = 1;
	}

	if (st_in.st_uid != st_out.st_uid) {
		print_diff(output_prefix, "UID differs",
				st_in.st_uid, st_out.st_uid);
		ret = 1;
	}

	if (st_in.st_gid != st_out.st_gid) {
		print_diff(output_prefix, "GID differs",
				st_in.st_gid, st_out.st_gid);
		ret = 1;
	}

	if (st_in.st_mtime != st_out.st_mtime) {
		print_diff(output_prefix, "mtime (in seconds) differs",
				st_in.st_mtime, st_out.st_mtime);
		ret = 1;
	}

	return ret;
}
// Настройки захвата (~2мс)
unsigned int grab_init(char *dev, int chnum){
	struct v4l2_capability cap;
	struct v4l2_cropcap cropcap;
	struct v4l2_crop crop;
	struct v4l2_format fmt;
	int i = 0;
	bool ret = 0;
	unsigned int bufsize;
	if(dev) grab_dev = strdup(dev);
	if(grab_fd < 0){ // при первой инициализации открываем
		struct stat st; 
		if(-1 == stat(grab_dev, &st)){
			ERR("Cannot identify '%s': %d, %s\n", grab_dev, errno, strerror (errno));
			exit (EXIT_FAILURE);
		}
		if(!S_ISCHR(st.st_mode)){
			ERR("%s is no device\n", grab_dev);
			exit(EXIT_FAILURE);
		}
		grab_fd = open(grab_dev, O_RDWR | O_NONBLOCK, 0);
		if(-1 == grab_fd){
			ERR("Cannot open '%s': %d, %s\n", grab_dev, errno, strerror (errno));
			exit(EXIT_FAILURE);
		}
	}
	if(-1 == xioctl(grab_fd, VIDIOC_QUERYCAP, &cap)){
		if(EINVAL == errno){
			ERR("%s is not V4L2 device\n", grab_dev);
			exit(EXIT_FAILURE);
		} else
			errno_exit ("VIDIOC_QUERYCAP");
	}
	if(!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)){
		ERR("%s is no video capture device\n", grab_dev);
		exit (EXIT_FAILURE);
	}
	
	
	
	
	
struct v4l2_queryctrl queryctrl;
struct v4l2_querymenu querymenu;
struct v4l2_control control;

void
enumerate_menu (void)
{
        printf ("  Menu items:\n");

        CLEAR(querymenu);
        querymenu.id = queryctrl.id;

        for (querymenu.index = queryctrl.minimum;
             querymenu.index <= queryctrl.maximum;
              querymenu.index++) {
                if (0 == ioctl (grab_fd, VIDIOC_QUERYMENU, &querymenu)) {
                        printf ("  %s\n", querymenu.name);
                } else {
                        perror ("VIDIOC_QUERYMENU");
                        exit (EXIT_FAILURE);
                }
        }
}
示例#10
0
struct inode *nilfs_ilookup(struct super_block *sb, struct nilfs_root *root,
			    unsigned long ino)
{
	struct nilfs_iget_args args = {
		.ino = ino, .root = root, .cno = 0, .for_gc = 0
	};

	return ilookup5(sb, ino, nilfs_iget_test, &args);
}

struct inode *nilfs_iget_locked(struct super_block *sb, struct nilfs_root *root,
				unsigned long ino)
{
	struct nilfs_iget_args args = {
		.ino = ino, .root = root, .cno = 0, .for_gc = 0
	};

	return iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args);
}

struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
			 unsigned long ino)
{
	struct inode *inode;
	int err;

	inode = nilfs_iget_locked(sb, root, ino);
	if (unlikely(!inode))
		return ERR_PTR(-ENOMEM);
	if (!(inode->i_state & I_NEW))
		return inode;

	err = __nilfs_read_inode(sb, root, ino, inode);
	if (unlikely(err)) {
		iget_failed(inode);
		return ERR_PTR(err);
	}
	unlock_new_inode(inode);
	return inode;
}

struct inode *nilfs_iget_for_gc(struct super_block *sb, unsigned long ino,
				__u64 cno)
{
	struct nilfs_iget_args args = {
		.ino = ino, .root = NULL, .cno = cno, .for_gc = 1
	};
	struct inode *inode;
	int err;

	inode = iget5_locked(sb, ino, nilfs_iget_test, nilfs_iget_set, &args);
	if (unlikely(!inode))
		return ERR_PTR(-ENOMEM);
	if (!(inode->i_state & I_NEW))
		return inode;

	err = nilfs_init_gcinode(inode);
	if (unlikely(err)) {
		iget_failed(inode);
		return ERR_PTR(err);
	}
	unlock_new_inode(inode);
	return inode;
}

void nilfs_write_inode_common(struct inode *inode,
			      struct nilfs_inode *raw_inode, int has_bmap)
{
	struct nilfs_inode_info *ii = NILFS_I(inode);

	raw_inode->i_mode = cpu_to_le16(inode->i_mode);
	raw_inode->i_uid = cpu_to_le32(inode->i_uid);
	raw_inode->i_gid = cpu_to_le32(inode->i_gid);
	raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
	raw_inode->i_size = cpu_to_le64(inode->i_size);
	raw_inode->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
	raw_inode->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
	raw_inode->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
	raw_inode->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
	raw_inode->i_blocks = cpu_to_le64(inode->i_blocks);

	raw_inode->i_flags = cpu_to_le32(ii->i_flags);
	raw_inode->i_generation = cpu_to_le32(inode->i_generation);

	if (NILFS_ROOT_METADATA_FILE(inode->i_ino)) {
		struct the_nilfs *nilfs = inode->i_sb->s_fs_info;

		
		raw_inode->i_xattr = 0;
		raw_inode->i_pad = 0;
		memset((void *)raw_inode + sizeof(*raw_inode), 0,
		       nilfs->ns_inode_size - sizeof(*raw_inode));
	}

	if (has_bmap)
		nilfs_bmap_write(ii->i_bmap, raw_inode);
	else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
		raw_inode->i_device_code =
			cpu_to_le64(huge_encode_dev(inode->i_rdev));
}

void nilfs_update_inode(struct inode *inode, struct buffer_head *ibh)
{
	ino_t ino = inode->i_ino;
	struct nilfs_inode_info *ii = NILFS_I(inode);
	struct inode *ifile = ii->i_root->ifile;
	struct nilfs_inode *raw_inode;

	raw_inode = nilfs_ifile_map_inode(ifile, ino, ibh);

	if (test_and_clear_bit(NILFS_I_NEW, &ii->i_state))
		memset(raw_inode, 0, NILFS_MDT(ifile)->mi_entry_size);
	set_bit(NILFS_I_INODE_DIRTY, &ii->i_state);

	nilfs_write_inode_common(inode, raw_inode, 0);
	nilfs_ifile_unmap_inode(ifile, ino, ibh);
}

#define NILFS_MAX_TRUNCATE_BLOCKS	16384  

static void nilfs_truncate_bmap(struct nilfs_inode_info *ii,
				unsigned long from)
{
	unsigned long b;
	int ret;

	if (!test_bit(NILFS_I_BMAP, &ii->i_state))
		return;
repeat:
	ret = nilfs_bmap_last_key(ii->i_bmap, &b);
	if (ret == -ENOENT)
		return;
	else if (ret < 0)
		goto failed;

	if (b < from)
		return;

	b -= min_t(unsigned long, NILFS_MAX_TRUNCATE_BLOCKS, b - from);
	ret = nilfs_bmap_truncate(ii->i_bmap, b);
	nilfs_relax_pressure_in_lock(ii->vfs_inode.i_sb);
	if (!ret || (ret == -ENOMEM &&
		     nilfs_bmap_truncate(ii->i_bmap, b) == 0))
		goto repeat;

failed:
	nilfs_warning(ii->vfs_inode.i_sb, __func__,
		      "failed to truncate bmap (ino=%lu, err=%d)",
		      ii->vfs_inode.i_ino, ret);
}

void nilfs_truncate(struct inode *inode)
{
	unsigned long blkoff;
	unsigned int blocksize;
	struct nilfs_transaction_info ti;
	struct super_block *sb = inode->i_sb;
	struct nilfs_inode_info *ii = NILFS_I(inode);

	if (!test_bit(NILFS_I_BMAP, &ii->i_state))
		return;
	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
		return;

	blocksize = sb->s_blocksize;
	blkoff = (inode->i_size + blocksize - 1) >> sb->s_blocksize_bits;
	nilfs_transaction_begin(sb, &ti, 0); 

	block_truncate_page(inode->i_mapping, inode->i_size, nilfs_get_block);

	nilfs_truncate_bmap(ii, blkoff);

	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
	if (IS_SYNC(inode))
		nilfs_set_transaction_flag(NILFS_TI_SYNC);

	nilfs_mark_inode_dirty(inode);
	nilfs_set_file_dirty(inode, 0);
	nilfs_transaction_commit(sb);
}
示例#11
0
void
xf86OpenConsole(void)
{
    int i, fd = -1, ret, current_vt = -1;
    struct vt_mode VT;
    struct vt_stat vts;
    struct stat st;
    MessageType from = X_PROBED;
    const char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
    const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };

    if (serverGeneration == 1) {
        /*
         * setup the virtual terminal manager
         */
        if (xf86Info.vtno != -1) {
            from = X_CMDLINE;
        }
        else {

            i = 0;
            while (tty0[i] != NULL) {
                if ((fd = open(tty0[i], O_WRONLY, 0)) >= 0)
                    break;
                i++;
            }

            if (fd < 0)
                FatalError("xf86OpenConsole: Cannot open /dev/tty0 (%s)\n",
                           strerror(errno));

            if (xf86Info.ShareVTs) {
                SYSCALL(ret = ioctl(fd, VT_GETSTATE, &vts));
                if (ret < 0)
                    FatalError("xf86OpenConsole: Cannot find the current"
                               " VT (%s)\n", strerror(errno));
                xf86Info.vtno = vts.v_active;
            }
            else {
                SYSCALL(ret = ioctl(fd, VT_OPENQRY, &xf86Info.vtno));
                if (ret < 0)
                    FatalError("xf86OpenConsole: Cannot find a free VT: "
                               "%s\n", strerror(errno));
                if (xf86Info.vtno == -1)
                    FatalError("xf86OpenConsole: Cannot find a free VT\n");
            }
            close(fd);
        }

        xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);

        /* Some of stdin / stdout / stderr maybe redirected to a file */
        for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) {
            ret = fstat(i, &st);
            if (ret == 0 && S_ISCHR(st.st_mode) && major(st.st_rdev) == 4) {
                current_vt = minor(st.st_rdev);
                break;
            }
        }

        if (!KeepTty && current_vt == xf86Info.vtno) {
            xf86Msg(X_PROBED,
                    "controlling tty is VT number %d, auto-enabling KeepTty\n",
                    current_vt);
            KeepTty = TRUE;
        }

        if (!KeepTty) {
            pid_t ppid = getppid();
            pid_t ppgid;

            ppgid = getpgid(ppid);

            /*
             * change to parent process group that pgid != pid so
             * that setsid() doesn't fail and we become process
             * group leader
             */
            if (setpgid(0, ppgid) < 0)
                xf86Msg(X_WARNING, "xf86OpenConsole: setpgid failed: %s\n",
                        strerror(errno));

            /* become process group leader */
            if ((setsid() < 0))
                xf86Msg(X_WARNING, "xf86OpenConsole: setsid failed: %s\n",
                        strerror(errno));
        }

        i = 0;
        while (vcs[i] != NULL) {
            snprintf(vtname, sizeof(vtname), vcs[i], xf86Info.vtno);    /* /dev/tty1-64 */
            if ((xf86Info.consoleFd = open(vtname, O_RDWR | O_NDELAY, 0)) >= 0)
                break;
            i++;
        }

        if (xf86Info.consoleFd < 0)
            FatalError("xf86OpenConsole: Cannot open virtual console"
                       " %d (%s)\n", xf86Info.vtno, strerror(errno));

        /*
         * Linux doesn't switch to an active vt after the last close of a vt,
         * so we do this ourselves by remembering which is active now.
         */
        SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_GETSTATE, &vts));
        if (ret < 0)
            xf86Msg(X_WARNING, "xf86OpenConsole: VT_GETSTATE failed: %s\n",
                    strerror(errno));
        else
            activeVT = vts.v_active;

#if 0
        if (!KeepTty) {
            /*
             * Detach from the controlling tty to avoid char loss
             */
            if ((i = open("/dev/tty", O_RDWR)) >= 0) {
                SYSCALL(ioctl(i, TIOCNOTTY, 0));
                close(i);
            }
        }
#endif

        if (!xf86Info.ShareVTs) {
            struct termios nTty;

            /*
             * now get the VT.  This _must_ succeed, or else fail completely.
             */
            if (!switch_to(xf86Info.vtno, "xf86OpenConsole"))
                FatalError("xf86OpenConsole: Switching VT failed\n");

            SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_GETMODE, &VT));
            if (ret < 0)
                FatalError("xf86OpenConsole: VT_GETMODE failed %s\n",
                           strerror(errno));

            signal(SIGUSR1, xf86VTRequest);

            VT.mode = VT_PROCESS;
            VT.relsig = SIGUSR1;
            VT.acqsig = SIGUSR1;

            SYSCALL(ret = ioctl(xf86Info.consoleFd, VT_SETMODE, &VT));
            if (ret < 0)
                FatalError
                    ("xf86OpenConsole: VT_SETMODE VT_PROCESS failed: %s\n",
                     strerror(errno));

            SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSETMODE, KD_GRAPHICS));
            if (ret < 0)
                FatalError("xf86OpenConsole: KDSETMODE KD_GRAPHICS failed %s\n",
                           strerror(errno));

            tcgetattr(xf86Info.consoleFd, &tty_attr);
            SYSCALL(ioctl(xf86Info.consoleFd, KDGKBMODE, &tty_mode));

            /* disable kernel special keys and buffering, new style */
            SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSKBMUTE, 1));
            if (ret < 0)
            {
                /* disable kernel special keys and buffering, old style */
                SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSKBMODE, K_OFF));
                if (ret < 0)
                {
                    /* fine, just disable special keys */
                    SYSCALL(ret = ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW));
                    if (ret < 0)
                        FatalError("xf86OpenConsole: KDSKBMODE K_RAW failed %s\n",
                                   strerror(errno));

                    /* ... and drain events, else the kernel gets angry */
                    xf86SetConsoleHandler(drain_console, NULL);
                }
            }

            nTty = tty_attr;
            nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
            nTty.c_oflag = 0;
            nTty.c_cflag = CREAD | CS8;
            nTty.c_lflag = 0;
            nTty.c_cc[VTIME] = 0;
            nTty.c_cc[VMIN] = 1;
            cfsetispeed(&nTty, 9600);
            cfsetospeed(&nTty, 9600);
            tcsetattr(xf86Info.consoleFd, TCSANOW, &nTty);
        }
    }
    else {                      /* serverGeneration != 1 */
        if (!xf86Info.ShareVTs && xf86Info.autoVTSwitch) {
            /* now get the VT */
            if (!switch_to(xf86Info.vtno, "xf86OpenConsole"))
                FatalError("xf86OpenConsole: Switching VT failed\n");
        }
    }
}
示例#12
0
static int hfsplus_readdir(struct file *file, struct dir_context *ctx)
{
	struct inode *inode = file_inode(file);
	struct super_block *sb = inode->i_sb;
	int len, err;
	char *strbuf;
	hfsplus_cat_entry entry;
	struct hfs_find_data fd;
	struct hfsplus_readdir_data *rd;
	u16 type;

	if (file->f_pos >= inode->i_size)
		return 0;

	err = hfs_find_init(HFSPLUS_SB(sb)->cat_tree, &fd);
	if (err)
		return err;
	strbuf = kmalloc(NLS_MAX_CHARSET_SIZE * HFSPLUS_MAX_STRLEN + 1, GFP_KERNEL);
	if (!strbuf) {
		err = -ENOMEM;
		goto out;
	}
	hfsplus_cat_build_key_with_cnid(sb, fd.search_key, inode->i_ino);
	err = hfs_brec_find(&fd, hfs_find_rec_by_key);
	if (err)
		goto out;

	if (ctx->pos == 0) {
		/* This is completely artificial... */
		if (!dir_emit_dot(file, ctx))
			goto out;
		ctx->pos = 1;
	}
	if (ctx->pos == 1) {
		if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
			err = -EIO;
			goto out;
		}

		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
			fd.entrylength);
		if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
			pr_err("bad catalog folder thread\n");
			err = -EIO;
			goto out;
		}
		if (fd.entrylength < HFSPLUS_MIN_THREAD_SZ) {
			pr_err("truncated catalog thread\n");
			err = -EIO;
			goto out;
		}
		if (!dir_emit(ctx, "..", 2,
			    be32_to_cpu(entry.thread.parentID), DT_DIR))
			goto out;
		ctx->pos = 2;
	}
	if (ctx->pos >= inode->i_size)
		goto out;
	err = hfs_brec_goto(&fd, ctx->pos - 1);
	if (err)
		goto out;
	for (;;) {
		if (be32_to_cpu(fd.key->cat.parent) != inode->i_ino) {
			pr_err("walked past end of dir\n");
			err = -EIO;
			goto out;
		}

		if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
			err = -EIO;
			goto out;
		}

		hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
			fd.entrylength);
		type = be16_to_cpu(entry.type);
		len = NLS_MAX_CHARSET_SIZE * HFSPLUS_MAX_STRLEN;
		err = hfsplus_uni2asc(sb, &fd.key->cat.name, strbuf, &len);
		if (err)
			goto out;
		if (type == HFSPLUS_FOLDER) {
			if (fd.entrylength <
					sizeof(struct hfsplus_cat_folder)) {
				pr_err("small dir entry\n");
				err = -EIO;
				goto out;
			}
			if (HFSPLUS_SB(sb)->hidden_dir &&
			    HFSPLUS_SB(sb)->hidden_dir->i_ino ==
					be32_to_cpu(entry.folder.id))
				goto next;
			if (!dir_emit(ctx, strbuf, len,
				    be32_to_cpu(entry.folder.id), DT_DIR))
				break;
		} else if (type == HFSPLUS_FILE) {
			u16 mode;
			unsigned type = DT_UNKNOWN;

			if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
				pr_err("small file entry\n");
				err = -EIO;
				goto out;
			}

			mode = be16_to_cpu(entry.file.permissions.mode);
			if (S_ISREG(mode))
				type = DT_REG;
			else if (S_ISLNK(mode))
				type = DT_LNK;
			else if (S_ISFIFO(mode))
				type = DT_FIFO;
			else if (S_ISCHR(mode))
				type = DT_CHR;
			else if (S_ISBLK(mode))
				type = DT_BLK;
			else if (S_ISSOCK(mode))
				type = DT_SOCK;

			if (!dir_emit(ctx, strbuf, len,
				      be32_to_cpu(entry.file.id), type))
				break;
		} else {
			pr_err("bad catalog entry type\n");
			err = -EIO;
			goto out;
		}
next:
		ctx->pos++;
		if (ctx->pos >= inode->i_size)
			goto out;
		err = hfs_brec_goto(&fd, 1);
		if (err)
			goto out;
	}
	rd = file->private_data;
	if (!rd) {
		rd = kmalloc(sizeof(struct hfsplus_readdir_data), GFP_KERNEL);
		if (!rd) {
			err = -ENOMEM;
			goto out;
		}
		file->private_data = rd;
		rd->file = file;
		spin_lock(&HFSPLUS_I(inode)->open_dir_lock);
		list_add(&rd->list, &HFSPLUS_I(inode)->open_dir_list);
		spin_unlock(&HFSPLUS_I(inode)->open_dir_lock);
	}
	/*
	 * Can be done after the list insertion; exclusion with
	 * hfsplus_delete_cat() is provided by directory lock.
	 */
	memcpy(&rd->key, fd.key, sizeof(struct hfsplus_cat_key));
out:
	kfree(strbuf);
	hfs_find_exit(&fd);
	return err;
}
示例#13
0
/* Init xbee input */
int in_xbee_init(struct flb_config *config, void *data)
{
    int ret;
    struct stat dev_st;
    struct xbee *xbee;
    struct xbee_conAddress address;
    struct flb_in_xbee_config *ctx;
    struct xbee_conSettings settings;
    (void) data;

    /* Prepare the configuration context */
    ctx = calloc(1, sizeof(struct flb_in_xbee_config));
    if (!ctx) {
        perror("calloc");
        return -1;
    }

    if (!config->file) {
        flb_utils_error_c("XBee input plugin needs configuration file");
        return -1;
    }

    xbee_config_read(ctx, config->file);

    /* initialize MessagePack buffers */
    msgpack_sbuffer_init(&ctx->mp_sbuf);
    msgpack_packer_init(&ctx->mp_pck, &ctx->mp_sbuf, msgpack_sbuffer_write);

    flb_info("XBee device=%s, baudrate=%i", ctx->file, ctx->baudrate);

    ret = stat(ctx->file, &dev_st);
    if (ret < 0) {
        printf("Error: could not open %s device\n", ctx->file);
        free(ctx->file);
        exit(EXIT_FAILURE);
    }

    if (!S_ISCHR(dev_st.st_mode)) {
        printf("Error: invalid device %s \n", ctx->file);
        free(ctx->file);
        exit(EXIT_FAILURE);
    }

    if (access(ctx->file, R_OK | W_OK) == -1) {
        printf("Error: cannot open the device %s (permission denied ?)\n",
               ctx->file);
        free(ctx->file);
        exit(EXIT_FAILURE);
    }

    ctx->config = config;
    pthread_mutex_init(&ctx->mtx_mp, NULL);
    ctx->buffer_len = 0;

    /* Init library */
    xbee_init();

    ret = xbee_setup(&xbee, ctx->xbeeMode, ctx->file, ctx->baudrate);
    if (ret != XBEE_ENONE) {
        flb_utils_error_c("xbee_setup");
        return ret;
    }

    /* 000000000000FFFF: broadcast address */
    memset(&address, 0, sizeof(address));
    address.addr64_enabled = 1;
    address.addr64[0] = 0x00;
    address.addr64[1] = 0x00;
    address.addr64[2] = 0x00;
    address.addr64[3] = 0x00;
    address.addr64[4] = 0x00;
    address.addr64[5] = 0x00;
    address.addr64[6] = 0xFF;
    address.addr64[7] = 0xFF;

    if (ctx->xbeeLogLevel >= 0)
        xbee_logLevelSet(xbee, ctx->xbeeLogLevel);

    /* Prepare a connection with the peer XBee */

    if ((ret = xbee_conNew(xbee, &ctx->con_data, "Data", &address)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret));
        return ret;
    }

    xbee_conSettings(ctx->con_data, NULL, &settings);
    settings.disableAck = ctx->xbeeDisableAck ? 1 : 0;
    settings.catchAll = ctx->xbeeCatchAll ? 1 : 0;
    xbee_conSettings(ctx->con_data, &settings, NULL);

    if ((ret = xbee_conDataSet(ctx->con_data, ctx, NULL)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conDataSet() returned: %d", ret);
        return ret;
    }

    if ((ret = xbee_conCallbackSet(ctx->con_data, in_xbee_cb, NULL)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret);
        return ret;
    }


    if ((ret = xbee_conNew(xbee, &ctx->con_io, "I/O", &address)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conNew() returned: %d (%s)", ret, xbee_errorToStr(ret));
        return ret;
    }

    xbee_conSettings(ctx->con_io, NULL, &settings);
    settings.disableAck = ctx->xbeeDisableAck ? 1 : 0;
    settings.catchAll = ctx->xbeeCatchAll ? 1 : 0;
    xbee_conSettings(ctx->con_io, &settings, NULL);

    if ((ret = xbee_conDataSet(ctx->con_io, ctx, NULL)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conDataSet() returned: %d", ret);
        return ret;
    }

    if ((ret = xbee_conCallbackSet(ctx->con_io, in_xbee_iosampling_cb, NULL)) != XBEE_ENONE) {
        xbee_log(xbee, -1, "xbee_conCallbackSet() returned: %d", ret);
        return ret;
    }

    /* Set the context */
    ret = flb_input_set_context("xbee", ctx, config);
    if (ret == -1) {
        flb_utils_error_c("Could not set configuration for xbee input plugin");
    }

    return 0;
}
static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, dev_t rdev)
{
	struct jffs2_inode_info *f, *dir_f;
	struct jffs2_sb_info *c;
	struct inode *inode;
	struct jffs2_raw_inode *ri;
	struct jffs2_raw_dirent *rd;
	struct jffs2_full_dnode *fn;
	struct jffs2_full_dirent *fd;
	int namelen;
	jint16_t dev;
	int devlen = 0;
	uint32_t alloclen, phys_ofs;
	int ret;

	if (!old_valid_dev(rdev))
		return -EINVAL;

	ri = jffs2_alloc_raw_inode();
	if (!ri)
		return -ENOMEM;

	c = JFFS2_SB_INFO(dir_i->i_sb);

	if (S_ISBLK(mode) || S_ISCHR(mode)) {
		dev = cpu_to_je16(old_encode_dev(rdev));
		devlen = sizeof(dev);
	}

	/* Try to reserve enough space for both node and dirent.
	 * Just the node will do for now, though
	 */
	namelen = dentry->d_name.len;
	ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen,
				ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);

	if (ret) {
		jffs2_free_raw_inode(ri);
		return ret;
	}

	inode = jffs2_new_inode(dir_i, mode, ri);

	if (IS_ERR(inode)) {
		jffs2_free_raw_inode(ri);
		jffs2_complete_reservation(c);
		return PTR_ERR(inode);
	}
	inode->i_op = &jffs2_file_inode_operations;
	init_special_inode(inode, inode->i_mode, rdev);

	f = JFFS2_INODE_INFO(inode);

	ri->dsize = ri->csize = cpu_to_je32(devlen);
	ri->totlen = cpu_to_je32(sizeof(*ri) + devlen);
	ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));

	ri->compr = JFFS2_COMPR_NONE;
	ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen));
	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));

	fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, ALLOC_NORMAL);

	jffs2_free_raw_inode(ri);

	if (IS_ERR(fn)) {
		/* Eeek. Wave bye bye */
		up(&f->sem);
		jffs2_complete_reservation(c);
		jffs2_clear_inode(inode);
		return PTR_ERR(fn);
	}
	/* No data here. Only a metadata node, which will be
	   obsoleted by the first data write
	*/
	f->metadata = fn;
	up(&f->sem);

	jffs2_complete_reservation(c);
	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
	if (ret) {
		/* Eep. */
		jffs2_clear_inode(inode);
		return ret;
	}

	rd = jffs2_alloc_raw_dirent();
	if (!rd) {
		/* Argh. Now we treat it like a normal delete */
		jffs2_complete_reservation(c);
		jffs2_clear_inode(inode);
		return -ENOMEM;
	}

	dir_f = JFFS2_INODE_INFO(dir_i);
	down(&dir_f->sem);

	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));

	rd->pino = cpu_to_je32(dir_i->i_ino);
	rd->version = cpu_to_je32(++dir_f->highest_version);
	rd->ino = cpu_to_je32(inode->i_ino);
	rd->mctime = cpu_to_je32(get_seconds());
	rd->nsize = namelen;

	/* XXX: This is ugly. */
	rd->type = (mode & S_IFMT) >> 12;

	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
	rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));

	fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL);

	if (IS_ERR(fd)) {
		/* dirent failed to write. Delete the inode normally
		   as if it were the final unlink() */
		jffs2_complete_reservation(c);
		jffs2_free_raw_dirent(rd);
		up(&dir_f->sem);
		jffs2_clear_inode(inode);
		return PTR_ERR(fd);
	}

	dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));

	jffs2_free_raw_dirent(rd);

	/* Link the fd into the inode's list, obsoleting an old
	   one if necessary. */
	jffs2_add_fd_to_list(c, fd, &dir_f->dents);

	up(&dir_f->sem);
	jffs2_complete_reservation(c);

	d_instantiate(dentry, inode);

	return 0;
}
示例#15
0
int
main(int argc,char *argv[])
{
	int ch, i;
	int num_options;
	unsigned long action;
	char config_filename[PATH_MAX];
	char dev_name[PATH_MAX];
	char name[PATH_MAX];
	char component[PATH_MAX];
	char autoconf[10];
	char *parityconf = NULL;
	int parityparams[3];
	int do_output;
	int do_recon;
	int do_rewrite;
	int raidID;
	int serial_number;
	struct stat st;
	int fd;
	int force;
	int openmode;
	int last_unit;

	num_options = 0;
	action = 0;
	do_output = 0;
	do_recon = 0;
	do_rewrite = 0;
	serial_number = 0;
	force = 0;
	last_unit = 0;
	openmode = O_RDWR;	/* default to read/write */

	while ((ch = getopt(argc, argv, "a:A:Bc:C:f:F:g:GiI:l:mM:r:R:sSpPuU:v"))
	       != -1)
		switch(ch) {
		case 'a':
			action = RAIDFRAME_ADD_HOT_SPARE;
			strlcpy(component, optarg, sizeof(component));
			num_options++;
			break;
		case 'A':
			action = RAIDFRAME_SET_AUTOCONFIG;
			strlcpy(autoconf, optarg, sizeof(autoconf));
			num_options++;
			break;
		case 'B':
			action = RAIDFRAME_COPYBACK;
			num_options++;
			break;
		case 'c':
			action = RAIDFRAME_CONFIGURE;
			strlcpy(config_filename, optarg,
			    sizeof(config_filename));
			force = 0;
			num_options++;
			break;
		case 'C':
			strlcpy(config_filename, optarg,
			    sizeof(config_filename));
			action = RAIDFRAME_CONFIGURE;
			force = 1;
			num_options++;
			break;
		case 'f':
			action = RAIDFRAME_FAIL_DISK;
			strlcpy(component, optarg, sizeof(component));
			do_recon = 0;
			num_options++;
			break;
		case 'F':
			action = RAIDFRAME_FAIL_DISK;
			strlcpy(component, optarg, sizeof(component));
			do_recon = 1;
			num_options++;
			break;
		case 'g':
			action = RAIDFRAME_GET_COMPONENT_LABEL;
			strlcpy(component, optarg, sizeof(component));
			openmode = O_RDONLY;
			num_options++;
			break;
		case 'G':
			action = RAIDFRAME_GET_INFO;
			openmode = O_RDONLY;
			do_output = 1;
			num_options++;
			break;
		case 'i':
			action = RAIDFRAME_REWRITEPARITY;
			num_options++;
			break;
		case 'I':
			action = RAIDFRAME_INIT_LABELS;
			serial_number = xstrtouint(optarg);
			num_options++;
			break;
		case 'm':
			action = RAIDFRAME_PARITYMAP_STATUS;
			openmode = O_RDONLY;
			num_options++;
			break;
		case 'M':
			action = RAIDFRAME_PARITYMAP_SET_DISABLE;
			parityconf = strdup(optarg);
			num_options++;
			/* XXXjld: should rf_pm_configure do the strtol()s? */
			i = 0;
			while (i < 3 && optind < argc &&
			    isdigit((int)argv[optind][0]))
				parityparams[i++] = xstrtouint(argv[optind++]);
			while (i < 3)
				parityparams[i++] = 0;
			break;
		case 'l': 
			action = RAIDFRAME_SET_COMPONENT_LABEL;
			strlcpy(component, optarg, sizeof(component));
			num_options++;
			break;
		case 'r':
			action = RAIDFRAME_REMOVE_HOT_SPARE;
			strlcpy(component, optarg, sizeof(component));
			num_options++;
			break;
		case 'R':
			strlcpy(component, optarg, sizeof(component));
			action = RAIDFRAME_REBUILD_IN_PLACE;
			num_options++;
			break;
		case 's':
			action = RAIDFRAME_GET_INFO;
			openmode = O_RDONLY;
			num_options++;
			break;
		case 'S':
			action = RAIDFRAME_CHECK_RECON_STATUS_EXT;
			openmode = O_RDONLY;
			num_options++;
			break;
		case 'p':
			action = RAIDFRAME_CHECK_PARITY;
			openmode = O_RDONLY;
			num_options++;
			break;
		case 'P':
			action = RAIDFRAME_CHECK_PARITY;
			do_rewrite = 1;
			num_options++;
			break;
		case 'u':
			action = RAIDFRAME_SHUTDOWN;
			num_options++;
			break;
		case 'U':
			action = RAIDFRAME_SET_LAST_UNIT;
			num_options++;
			last_unit = atoi(optarg);
			if (last_unit < 0)
				errx(1, "Bad last unit %s", optarg);
			break;
		case 'v':
			verbose = 1;
			/* Don't bump num_options, as '-v' is not 
			   an option like the others */
			/* num_options++; */
			break;
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	if ((num_options > 1) || (argc == 0)) 
		usage();

	if (prog_init && prog_init() == -1)
		err(1, "init failed");

	strlcpy(name, argv[0], sizeof(name));
	fd = opendisk1(name, openmode, dev_name, sizeof(dev_name), 0,
	    prog_open);
	if (fd == -1)
		err(1, "Unable to open device file: %s", name);
	if (prog_fstat(fd, &st) == -1)
		err(1, "stat failure on: %s", dev_name);
	if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
		err(1, "invalid device: %s", dev_name);

	raidID = DISKUNIT(st.st_rdev);

	switch(action) {
	case RAIDFRAME_ADD_HOT_SPARE:
		add_hot_spare(fd, component);
		break;
	case RAIDFRAME_REMOVE_HOT_SPARE:
		remove_hot_spare(fd, component);
		break;
	case RAIDFRAME_CONFIGURE:
		rf_configure(fd, config_filename, force);
		break;
	case RAIDFRAME_SET_AUTOCONFIG:
		set_autoconfig(fd, raidID, autoconf);
		break;
	case RAIDFRAME_COPYBACK:
		printf("Copyback.\n");
		do_ioctl(fd, RAIDFRAME_COPYBACK, NULL, "RAIDFRAME_COPYBACK");
		if (verbose) {
			sleep(3); /* XXX give the copyback a chance to start */
			printf("Copyback status:\n");
			do_meter(fd,RAIDFRAME_CHECK_COPYBACK_STATUS_EXT);
		}
		break;
	case RAIDFRAME_FAIL_DISK:
		rf_fail_disk(fd, component, do_recon);
		break;
	case RAIDFRAME_SET_COMPONENT_LABEL:
		set_component_label(fd, component);
		break;
	case RAIDFRAME_GET_COMPONENT_LABEL:
		get_component_label(fd, component);
		break;
	case RAIDFRAME_INIT_LABELS:
		init_component_labels(fd, serial_number);
		break;
	case RAIDFRAME_REWRITEPARITY:
		printf("Initiating re-write of parity\n");
		do_ioctl(fd, RAIDFRAME_REWRITEPARITY, NULL, 
			 "RAIDFRAME_REWRITEPARITY");
		if (verbose) {
			sleep(3); /* XXX give it time to get started */
			printf("Parity Re-write status:\n");
			do_meter(fd, RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT);
		}
		break;
	case RAIDFRAME_CHECK_RECON_STATUS_EXT:
		check_status(fd,1);
		break;
	case RAIDFRAME_GET_INFO:
		if (do_output)
			rf_output_configuration(fd, dev_name);
		else
			rf_get_device_status(fd);
		break;
	case RAIDFRAME_PARITYMAP_STATUS:
		rf_output_pmstat(fd, raidID);
		break;
	case RAIDFRAME_PARITYMAP_SET_DISABLE:
		rf_pm_configure(fd, raidID, parityconf, parityparams);
		break;
	case RAIDFRAME_REBUILD_IN_PLACE:
		rebuild_in_place(fd, component);
		break;
	case RAIDFRAME_CHECK_PARITY:
		check_parity(fd, do_rewrite, dev_name);
		break;
	case RAIDFRAME_SHUTDOWN:
		do_ioctl(fd, RAIDFRAME_SHUTDOWN, NULL, "RAIDFRAME_SHUTDOWN");
		break;
	case RAIDFRAME_SET_LAST_UNIT:
		do_ioctl(fd, RAIDFRAME_SET_LAST_UNIT, &last_unit,
		    "RAIDFRAME_SET_LAST_UNIT");
		break;
	default:
		break;
	}

	prog_close(fd);
	exit(0);
}
示例#16
0
文件: entry.c 项目: sjclemen/rdup
/* ALmost the same of entry_print_data in gfunc.c, but
 * not quite as we don't don't use FILE* structs here
 * for instance. TODO: integrate the two functions?
 * entry_print_data()
 */
gint rdup_write_header(struct rdup * e)
{
	char *out;
	char t;

	if (S_ISDIR(e->f_mode)) {
		t = 'd';
	} else if (S_ISCHR(e->f_mode)) {
		t = 'c';
	} else if (S_ISBLK(e->f_mode)) {
		t = 'b';
	} else if (S_ISFIFO(e->f_mode)) {
		t = 'p';
	} else if (S_ISSOCK(e->f_mode)) {
		t = 's';
	} else if (S_ISLNK(e->f_mode)) {
		t = 'l';
	} else {
		if (e->f_lnk == 1)
			t = 'h';
		else
			t = '-';
	}

	if (t == 'b' || t == 'c') {
		/* device */
		out =
		    g_strdup_printf("%c%c %.4o %ld %ld %s %ld %s %ld %d,%d\n%s",
				    e->plusmin == PLUS ? '+' : '-', t,
				    (int)e->f_mode & 07777,
				    (unsigned long)e->f_mtime,
				    (unsigned long)e->f_uid, e->f_user,
				    (unsigned long)e->f_gid, e->f_group,
				    (unsigned long)e->f_name_size,
				    (unsigned int)major(e->f_rdev),
				    (unsigned int)minor(e->f_rdev), e->f_name);
	} else if (t == 'l' || t == 'h') {
		/* link */
		gchar *n;
		n = g_strdup_printf("%s -> %s", e->f_name, e->f_target);
		e->f_name_size = strlen(n);
		out = g_strdup_printf("%c%c %.4o %ld %ld %s %ld %s %ld %zd\n%s",
				      e->plusmin == PLUS ? '+' : '-',
				      t,
				      (int)e->f_mode & 07777,
				      (unsigned long)e->f_mtime,
				      (unsigned long)e->f_uid,
				      e->f_user,
				      (unsigned long)e->f_gid,
				      e->f_group,
				      (unsigned long)e->f_name_size,
				      (size_t) e->f_size, n);
		g_free(n);
	} else {
		out = g_strdup_printf("%c%c %.4o %ld %ld %s %ld %s %ld %zd\n%s",
				      e->plusmin == PLUS ? '+' : '-',
				      t,
				      (int)e->f_mode & 07777,
				      (unsigned long)e->f_mtime,
				      (unsigned long)e->f_uid,
				      e->f_user,
				      (unsigned long)e->f_gid,
				      e->f_group,
				      (unsigned long)e->f_name_size,
				      (size_t) e->f_size, e->f_name);
	}

	if (sig != 0)
		signal_abort(sig);

	if (write(1, out, strlen(out)) == -1) {
		msg(_("Failed to write to stdout: %s"), strerror(errno));
		return -1;
	}
	g_free(out);
	return 0;
}
示例#17
0
static int process_directory(int parent, const char *path, int fixstats)
{

	DIR *dir;
	struct dirent *entry;
	char *secontext = NULL;

	nDirectories++;
	
	dir = opendir(path);
	
	if(dir)
	{
		while((entry = readdir(dir)) != NULL)
		{
		
			/* Ignore . and .. */
			if(strcmp(entry->d_name,".") &&
			   strcmp(entry->d_name,".."))
 			{
 				char full_name[500];
#ifdef HAVE_SELINUX
				char *suffix, dest_name[500];
				int ret;
#endif
				struct stat stats;
				int equivalentObj;
				int newObj;
				
				sprintf(full_name,"%s/%s",path,entry->d_name);
				
				lstat(full_name,&stats);

#ifdef HAVE_SELINUX
				if (sehnd) {
					suffix = full_name + seprefixlen;
					ret = snprintf(dest_name,
						       sizeof dest_name,
						       "%s%s", mntpoint,
						       suffix);
					if (ret < 0 ||
					    (size_t) ret >= sizeof dest_name) {
						fprintf(stderr,
							"snprintf failed on %s%s\n",
							mntpoint, suffix);
						exit(1);
					}

					char *sepath = NULL;
					if (dest_name[0] == '/')
					        sepath = strdup(dest_name);
					else if (asprintf(&sepath, "/%s", dest_name) < 0)
                                                sepath = NULL;

					if (!sepath) {
					        perror("malloc");
					        exit(1);
					}

					if (selabel_lookup(sehnd, &secontext,
							   sepath,
							   stats.st_mode) < 0) {
						perror("selabel_lookup");
					        free(sepath);
						exit(1);
					}
					free(sepath);
				}
#endif

				if(S_ISLNK(stats.st_mode) ||
				    S_ISREG(stats.st_mode) ||
				    S_ISDIR(stats.st_mode) ||
				    S_ISFIFO(stats.st_mode) ||
				    S_ISBLK(stats.st_mode) ||
				    S_ISCHR(stats.st_mode) ||
				    S_ISSOCK(stats.st_mode))
				{
				
					newObj = obj_id++;
					nObjects++;

                    if (fixstats) {
                        fix_stat(full_name, &stats);
                    }

					//printf("Object %d, %s is a ",newObj,full_name);
					
					/* We're going to create an object for it */
					if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0)
					{
					 	/* we need to make a hard link */
					 	//printf("hard link to object %d\n",equivalentObj);
						error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL, secontext);
					}
					else 
					{
						
						add_obj_to_list(stats.st_dev,stats.st_ino,newObj);
						
						if(S_ISLNK(stats.st_mode))
						{
					
							char symname[500];
						
							memset(symname,0, sizeof(symname));
					
							readlink(full_name,symname,sizeof(symname) -1);
						
							//printf("symlink to \"%s\"\n",symname);
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname, secontext);

						}
						else if(S_ISREG(stats.st_mode))
						{
							//printf("file, ");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL, secontext);

							if(error >= 0)
							{
								int h;
								__u8 bytes[chunkSize];
								int nBytes;
								int chunk = 0;
								
								h = open(full_name,O_RDONLY);
								if(h >= 0)
								{
									memset(bytes,0xff,sizeof(bytes));
									while((nBytes = read(h,bytes,sizeof(bytes))) > 0)
									{
										chunk++;
										write_chunk(bytes,newObj,chunk,nBytes);
										memset(bytes,0xff,sizeof(bytes));
									}
									if(nBytes < 0) 
									   error = nBytes;
									   
									//printf("%d data chunks written\n",chunk);
								}
								else
								{
									perror("Error opening file");
								}
								close(h);
								
							}							
														
						}
						else if(S_ISSOCK(stats.st_mode))
						{
							//printf("socket\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
						}
						else if(S_ISFIFO(stats.st_mode))
						{
							//printf("fifo\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
						}
						else if(S_ISCHR(stats.st_mode))
						{
							//printf("character device\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
						}
						else if(S_ISBLK(stats.st_mode))
						{
							//printf("block device\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL, secontext);
						}
						else if(S_ISDIR(stats.st_mode))
						{
							//printf("directory\n");
							error =  write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL, secontext);
// NCB modified 10/9/2001				process_directory(1,full_name);
							process_directory(newObj,full_name,fixstats);
						}
					}
				}
				else
				{
					//printf(" we don't handle this type\n");
				}
			}
		}
		closedir(dir);
	}
	
	return 0;

}
示例#18
0
文件: entry.c 项目: sjclemen/rdup
/*
 * or parse a new style rdup -c output entry
 * +- 0775 1000 1000 18 2947\n
 * /home/miekg/bin/tt
 * <contents>
 *
 * where contents is block based
 * 1BLOCK8192
 * 8192 bytes of data
 * 1BLOCK15
 * 15 bytes of data
 * 1BLOCK0
 * the-end
 */
struct rdup *parse_entry(char *buf, size_t l)
{
	struct rdup *e;
	struct stat s;
	gint i;
	char *n, *pos;
	e = g_malloc(sizeof(struct rdup));
	e->f_ctime = 0;		/* not used in rdup-* */

	switch (opt_input) {
	case I_LIST:
		if (lstat(buf, &s) == -1) {
			msg(_("Could not stat path `%s\': %s"), buf,
			    strerror(errno));
			g_free(e);
			return NULL;
		}
		e->plusmin = PLUS;
		e->f_name = g_strdup(buf);
		e->f_name_size = strlen(buf);
		e->f_target = NULL;
		e->f_mode = s.st_mode;
		e->f_uid = s.st_uid;
		e->f_gid = s.st_gid;
		e->f_size = s.st_size;
		e->f_dev = s.st_dev;
		e->f_ino = s.st_ino;
		e->f_rdev = s.st_rdev;
		e->f_lnk = 0;
		e->f_ctime = s.st_ctime;
		e->f_mtime = s.st_mtime;
		e->f_atime = s.st_atime;
		e->f_hash = NULL;

		/* you will loose hardlink information here
		 * as 'stat' cannot check this */
		if (S_ISLNK(e->f_mode))
			e->f_target = slink(e);

		break;

	case I_RDUP:
		if (strlen(buf) < LIST_MINSIZE) {
			msg(_("Corrupt entry `%s\' in input at line: %zd"), buf,
			    l);
			g_free(e);
			return NULL;
		}

		/* defaults */
		e->f_dev = 0;
		e->f_rdev = 0;
		e->f_ino = 0;
		e->f_lnk = 0;
		e->f_target = NULL;
		e->f_name = NULL;
		e->f_hash = NULL;

		/* 1st char should + or - */
		if (buf[0] != '-' && buf[0] != '+') {
			msg(_
			    ("First character should \'-\' or \'+\', `%s\' at line: %zd"),
			    buf, l);
			g_free(e);
			return NULL;
		}
		if (buf[0] == '+')
			e->plusmin = PLUS;
		if (buf[0] == '-')
			e->plusmin = MINUS;

		if (opt_output != O_RDUP && e->plusmin == MINUS) {
			msg(_
			    ("Removing files is not supported for any output except rdup"));
			g_free(e);
			return NULL;
		}

		/* type */
		switch (buf[1]) {
		case '-':
			e->f_mode = S_IFREG;
			break;
		case 'd':
			e->f_mode = S_IFDIR;
			break;
		case 'l':
			e->f_mode = S_IFLNK;
			break;
		case 'h':
			e->f_mode = S_IFREG;
			e->f_lnk = 1;
			break;
		case 'c':
			e->f_mode = S_IFCHR;
			break;
		case 'b':
			e->f_mode = S_IFBLK;
			break;
		case 'p':
			e->f_mode = S_IFIFO;
			break;
		case 's':
			e->f_mode = S_IFSOCK;
			break;
		default:
			msg(_("Type must be one of d, l, h, -, c, b, p or s"));
			g_free(e);
			return NULL;
		}

		/* perm */
		i = (buf[3] - 48) * 512 + (buf[4] - 48) * 64 +	/* oct -> dec */
		    (buf[5] - 48) * 8 + (buf[6] - 48);
		if (i < 0 || i > 07777) {
			msg(_("Invalid permissions at line: %zd"), l);
			g_free(e);
			return NULL;
		}
		e->f_mode |= i;

		/* m_time */
		n = strchr(buf + 8, ' ');
		if (!n) {
			msg(_("Malformed input for m_time at line: %zd"), l);
			g_free(e);
			return NULL;
		}
		e->f_mtime = (time_t) atol(buf + 8);
		pos = n + 1;

		/* uid  */
		n = strchr(pos, ' ');
		if (!n) {
			msg(_("Malformed input for uid at line: %zd"), l);
			g_free(e);
			return NULL;
		} else {
			*n = '\0';
		}
		e->f_uid = atoi(pos);
		pos = n + 1;

		/* username */
		n = strchr(pos, ' ');
		if (!n) {
			msg(_("Malformed input for user at line: %zd"), l);
			g_free(e);
			return NULL;
		} else {
			*n = '\0';
		}
		e->f_user = g_strdup(pos);
		pos = n + 1;

		/* gid */
		n = strchr(pos, ' ');
		if (!n) {
			msg(_("Malformed input for gid at line: %zd"), l);
			g_free(e);
			return NULL;
		} else {
			*n = '\0';
		}
		e->f_gid = atoi(pos);
		pos = n + 1;

		/* groupname */
		n = strchr(pos, ' ');
		if (!n) {
			msg(_("Malformed input for group at line: %zd"), l);
			g_free(e);
			return NULL;
		} else {
			*n = '\0';
		}
		e->f_group = g_strdup(pos);
		pos = n + 1;

		/* pathname length */
		n = strchr(pos, ' ');
		if (!n) {
			msg(_("Malformed input for path length at line: %zd"),
			    l);
			g_free(e);
			return NULL;
		}
		e->f_name_size = atoi(pos);	/* checks */
		pos = n + 1;

		/* dev file? */
		if (S_ISCHR(e->f_mode) || S_ISBLK(e->f_mode)) {
			int major, minor;
			n = strchr(pos, ',');
			if (!n) {
				msg("No major,minor found for device at line: %zd", l);
				g_free(e);
				return NULL;
			}
			*n = '\0';
			major = atoi(pos);
			minor = atoi(n + 1);
			e->f_size = 0;
			e->f_rdev = makedev(major, minor);
		} else
			e->f_size = atoi(pos);

		break;
	}
	return e;
}
示例#19
0
Errors Device_getDeviceInfo(DeviceInfo   *deviceInfo,
                            const String deviceName
                           )
{
  FileStat fileStat;
  int      handle;
  #if defined(HAVE_IOCTL) && defined(HAVE_BLKSSZGET)
    int      i;
  #endif
  #if defined(HAVE_IOCTL) && defined(HAVE_BLKGETSIZE)
    long     l;
  #endif
  FILE          *mtab;
  struct mntent mountEntry;
  char          buffer[4096];

  assert(deviceName != NULL);
  assert(deviceInfo != NULL);

  // initialize variables
  deviceInfo->type        = DEVICE_TYPE_UNKNOWN;
  deviceInfo->size        = -1LL;
  deviceInfo->blockSize   = 0L;
//  deviceInfo->freeBlocks  = 0LL;
//  deviceInfo->totalBlocks = 0LL;
  deviceInfo->mountedFlag = FALSE;

  // get device meta data
  if (LSTAT(String_cString(deviceName),&fileStat) == 0)
  {
    deviceInfo->timeLastAccess  = fileStat.st_atime;
    deviceInfo->timeModified    = fileStat.st_mtime;
    deviceInfo->timeLastChanged = fileStat.st_ctime;
    deviceInfo->userId          = fileStat.st_uid;
    deviceInfo->groupId         = fileStat.st_gid;
    deviceInfo->permission      = (DevicePermission)fileStat.st_mode;
    #ifdef HAVE_MAJOR
      deviceInfo->major         = major(fileStat.st_rdev);
    #else
      deviceInfo->major         = 0;
    #endif
    #ifdef HAVE_MINOR
      deviceInfo->minor         = minor(fileStat.st_rdev);
    #else
      deviceInfo->minor         = 0;
    #endif
    deviceInfo->id              = (uint64)fileStat.st_ino;

    if      (S_ISCHR(fileStat.st_mode)) deviceInfo->type = DEVICE_TYPE_CHARACTER;
    else if (S_ISBLK(fileStat.st_mode)) deviceInfo->type = DEVICE_TYPE_BLOCK;
  }

  if (deviceInfo->type == DEVICE_TYPE_BLOCK)
  {
    // try to get block size, total size
    handle = open(String_cString(deviceName),O_RDONLY);
    if (handle != -1)
    {
      #if defined(HAVE_IOCTL) && defined(HAVE_BLKSSZGET)
        if (ioctl(handle,BLKSSZGET, &i) == 0) deviceInfo->blockSize = (ulong)i;
      #endif
      #if defined(HAVE_IOCTL) && defined(HAVE_BLKGETSIZE)
        if (ioctl(handle,BLKGETSIZE,&l) == 0) deviceInfo->size      = (int64)l*512;
      #endif
      close(handle);
    }
  }

  // check if mounted
  mtab = setmntent("/etc/mtab","r");
  if (mtab != NULL)
  {
    while (getmntent_r(mtab,&mountEntry,buffer,sizeof(buffer)) != NULL)
    {
      if (String_equalsCString(deviceName,mountEntry.mnt_fsname))
      {
        deviceInfo->mountedFlag = TRUE;
        break;
      }
    }
    endmntent(mtab);
  }

  return ERROR_NONE;
}
示例#20
0
文件: test.c 项目: 0x6e3078/toybox
void test_main(void)
{
  int id, not;
  char *s, *err_fmt = "Bad flag '%s'";

  toys.exitval = 2;
  if (!strcmp("[", toys.which->name))
    if (!strcmp("]", toys.optargs[--toys.optc])) error_exit("Missing ']'");
  if (!strcmp("!", toys.optargs[0])) {
    not = 1;
    toys.optargs++;
    toys.optc--;
  }
  if (!toys.optc) toys.exitval = 0;
  else if (toys.optargs[0][0] == '-') {
    id = stridx("bcdefghLpSsurwxznt", toys.optargs[0][1]);
    if (id == -1 || toys.optargs[0][2]) error_exit(err_fmt, toys.optargs[0]);
    if (id < 12) {
      struct stat st;
      int nolink;

      toys.exitval = 1;
      if (lstat(toys.optargs[1], &st) == -1) return;
      nolink = !S_ISLNK(st.st_mode);
      if (!nolink && (stat(toys.optargs[1], &st) == -1)) return;

      if (id == 0) toys.exitval = !S_ISBLK(st.st_mode); // b
      else if (id == 1) toys.exitval = !S_ISCHR(st.st_mode); // c
      else if (id == 2) toys.exitval = !S_ISDIR(st.st_mode); // d
      else if (id == 3) toys.exitval = 0; // e
      else if (id == 4) toys.exitval = !S_ISREG(st.st_mode); // f
      else if (id == 5) toys.exitval = !(st.st_mode & S_ISGID); // g
      else if ((id == 6) || (id == 7)) toys.exitval = nolink; // hL
      else if (id == 8) toys.exitval = !S_ISFIFO(st.st_mode); // p
      else if (id == 9) toys.exitval = !S_ISSOCK(st.st_mode); // S
      else if (id == 10) toys.exitval = st.st_size == 0; // s
      else toys.exitval = !(st.st_mode & S_ISUID); // u
    }
    else if (id < 15) // rwx
      toys.exitval = access(toys.optargs[1], 1 << (id - 12)) == -1;
    else if (id < 17) // zn
      toys.exitval = toys.optargs[1] && !*toys.optargs[1] ^ (id - 15);
    else { // t
      struct termios termios;
      toys.exitval = tcgetattr(atoi(toys.optargs[1]), &termios) == -1;
    }
  }
  else if (toys.optc == 1) toys.exitval = *toys.optargs[0] == 0;
  else if (toys.optc == 3) {
    if (*toys.optargs[1] == '-') {
      long a = atol(toys.optargs[0]), b = atol(toys.optargs[2]);
      
      s = toys.optargs[1] + 1;
      if (!strcmp("eq", s)) toys.exitval = a != b;
      else if (!strcmp("ne", s)) toys.exitval = a == b;
      else if (!strcmp("gt", s)) toys.exitval = a < b;
      else if (!strcmp("ge", s)) toys.exitval = a <= b;
      else if (!strcmp("lt", s)) toys.exitval = a > b;
      else if (!strcmp("le", s)) toys.exitval = a >= b;
      else error_exit(err_fmt, toys.optargs[1]);
    }
    else {
      int result = strcmp(toys.optargs[0], toys.optargs[2]);

      s = toys.optargs[1];
      if (!strcmp("=", s)) toys.exitval = !!result;
      else if (!strcmp("!=", s)) toys.exitval = !result;
      else error_exit(err_fmt, toys.optargs[1]);
    }
  }
  toys.exitval ^= not;
  return;
}
示例#21
0
const char *
fifolog_create(const char *fn, off_t size, ssize_t recsize)
{
	int i, fd;
	ssize_t u;
	u_int uu;
	off_t ms;
	struct stat st;
	char *buf;
	int created;

	fd = open(fn, O_WRONLY | O_TRUNC | O_EXCL | O_CREAT, 0644);
	if (fd < 0) {
		created = 0;
		fd = open(fn, O_WRONLY);
		if (fd < 0)
			return ("Could not open");
	} else
		created = 1;

	/* Default sectorsize is 512 */
	if (recsize == 0)
		recsize = 512;

	/* See what we got... */
	i = fstat(fd, &st);
	assert(i == 0);
	if (!S_ISBLK(st.st_mode) &&
	    !S_ISCHR(st.st_mode) &&
	    !S_ISREG(st.st_mode)) {
		assert(!close (fd));
		return ("Wrong file type");
	}

	if(!created && S_ISREG(st.st_mode)) {
		assert(!close (fd));
		return ("Wrong file type");
	}

	/* For raw disk with larger sectors: use 1 sector */
	i = ioctl(fd, DIOCGSECTORSIZE, &uu);
	u = uu;
	if (i == 0 && (u > recsize || (recsize % u) != 0))
		recsize = u;

	/* If no configured size, or too large for disk, use device size */
	i = ioctl(fd, DIOCGMEDIASIZE, &ms);
	if (i == 0 && (size == 0 || size > ms))
		size = ms;

	if (size == 0 && S_ISREG(st.st_mode))
		size = st.st_size;

	if (size == 0)
		size = recsize * (off_t)(24*60*60);

	if (S_ISREG(st.st_mode) && ftruncate(fd, size) < 0)
		return ("Could not ftrunc");

	buf = calloc(1, recsize);
	if (buf == NULL)
		return ("Could not malloc");

	strcpy(buf, FIFOLOG_FMT_MAGIC);		/*lint !e64 */
	be32enc(buf + FIFOLOG_OFF_BS, recsize);
	if (recsize != pwrite(fd, buf, recsize, 0)) {
		i = errno;
		free(buf);
		errno = i;
		return ("Could not write first sector");
	}
	memset(buf, 0, recsize);
	if ((int)recsize != pwrite(fd, buf, recsize, recsize)) {
		i = errno;
		free(buf);
		errno = i;
		return ("Could not write second sector");
	}
	free(buf);
	assert(0 == close(fd));
	return (NULL);
}
示例#22
0
static int ocfs2_read_locked_inode(struct inode *inode,
				   struct ocfs2_find_inode_args *args)
{
	struct super_block *sb;
	struct ocfs2_super *osb;
	struct ocfs2_dinode *fe;
	struct buffer_head *bh = NULL;
	int status, can_lock;
	u32 generation = 0;

	status = -EINVAL;
	if (inode == NULL || inode->i_sb == NULL) {
		mlog(ML_ERROR, "bad inode\n");
		return status;
	}
	sb = inode->i_sb;
	osb = OCFS2_SB(sb);

	if (!args) {
		mlog(ML_ERROR, "bad inode args\n");
		make_bad_inode(inode);
		return status;
	}

	/*
	 * To improve performance of cold-cache inode stats, we take
	 * the cluster lock here if possible.
	 *
	 * Generally, OCFS2 never trusts the contents of an inode
	 * unless it's holding a cluster lock, so taking it here isn't
	 * a correctness issue as much as it is a performance
	 * improvement.
	 *
	 * There are three times when taking the lock is not a good idea:
	 *
	 * 1) During startup, before we have initialized the DLM.
	 *
	 * 2) If we are reading certain system files which never get
	 *    cluster locks (local alloc, truncate log).
	 *
	 * 3) If the process doing the iget() is responsible for
	 *    orphan dir recovery. We're holding the orphan dir lock and
	 *    can get into a deadlock with another process on another
	 *    node in ->delete_inode().
	 *
	 * #1 and #2 can be simply solved by never taking the lock
	 * here for system files (which are the only type we read
	 * during mount). It's a heavier approach, but our main
	 * concern is user-accessible files anyway.
	 *
	 * #3 works itself out because we'll eventually take the
	 * cluster lock before trusting anything anyway.
	 */
	can_lock = !(args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
		&& !(args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY)
		&& !ocfs2_mount_local(osb);

	trace_ocfs2_read_locked_inode(
		(unsigned long long)OCFS2_I(inode)->ip_blkno, can_lock);

	/*
	 * To maintain backwards compatibility with older versions of
	 * ocfs2-tools, we still store the generation value for system
	 * files. The only ones that actually matter to userspace are
	 * the journals, but it's easier and inexpensive to just flag
	 * all system files similarly.
	 */
	if (args->fi_flags & OCFS2_FI_FLAG_SYSFILE)
		generation = osb->fs_generation;

	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_inode_lockres,
				  OCFS2_LOCK_TYPE_META,
				  generation, inode);

	ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_open_lockres,
				  OCFS2_LOCK_TYPE_OPEN,
				  0, inode);

	if (can_lock) {
		status = ocfs2_open_lock(inode);
		if (status) {
			make_bad_inode(inode);
			mlog_errno(status);
			return status;
		}
		status = ocfs2_inode_lock(inode, NULL, 0);
		if (status) {
			make_bad_inode(inode);
			mlog_errno(status);
			return status;
		}
	}

	if (args->fi_flags & OCFS2_FI_FLAG_ORPHAN_RECOVERY) {
		status = ocfs2_try_open_lock(inode, 0);
		if (status) {
			make_bad_inode(inode);
			return status;
		}
	}

	if (can_lock) {
		status = ocfs2_read_inode_block_full(inode, &bh,
						     OCFS2_BH_IGNORE_CACHE);
	} else {
		status = ocfs2_read_blocks_sync(osb, args->fi_blkno, 1, &bh);
		/*
		 * If buffer is in jbd, then its checksum may not have been
		 * computed as yet.
		 */
		if (!status && !buffer_jbd(bh))
			status = ocfs2_validate_inode_block(osb->sb, bh);
	}
	if (status < 0) {
		mlog_errno(status);
		goto bail;
	}

	status = -EINVAL;
	fe = (struct ocfs2_dinode *) bh->b_data;

	/*
	 * This is a code bug. Right now the caller needs to
	 * understand whether it is asking for a system file inode or
	 * not so the proper lock names can be built.
	 */
	mlog_bug_on_msg(!!(fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) !=
			!!(args->fi_flags & OCFS2_FI_FLAG_SYSFILE),
			"Inode %llu: system file state is ambigous\n",
			(unsigned long long)args->fi_blkno);

	if (S_ISCHR(le16_to_cpu(fe->i_mode)) ||
	    S_ISBLK(le16_to_cpu(fe->i_mode)))
		inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));

	ocfs2_populate_inode(inode, fe, 0);

	BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno));

	status = 0;

bail:
	if (can_lock)
		ocfs2_inode_unlock(inode, 0);

	if (status < 0)
		make_bad_inode(inode);

	if (args && bh)
		brelse(bh);

	return status;
}
示例#23
0
void show_attr(char *name)
{
	struct stat buf;
	struct passwd *pwd;
	struct group *grp;
	char type;
	char permission[9];
	int i = 0;
	
	memset(permission, '-', 9*sizeof(char));
	printf("name=[%s]\n", name);
	if (!stat(name, &buf))
	{
		printf("Got Here\n");
		//get the type of file
		if (S_ISLNK(buf.st_mode))
			type = 'l';
		else if (S_ISREG(buf.st_mode))
			type = '-';
		else if (S_ISDIR(buf.st_mode))
			type = 'd';
		else if (S_ISCHR(buf.st_mode))
			type = 'c';
		else if (S_ISBLK(buf.st_mode))
			type = 'b';
		else if (S_ISFIFO(buf.st_mode))
			type = 'p';
		else if (S_ISSOCK(buf.st_mode))
			type = 's';
		else
			type = '*';
			
		//get the permission of file
		if (buf.st_mode & S_IRUSR)
		{
			permission[0] = 'r';
		}
		if (buf.st_mode & S_IWUSR)
		{
			permission[1] = 'w';
		}
		if (buf.st_mode & S_IXUSR)
		{
			permission[2] = 'x';
		}
		if (buf.st_mode & S_IRGRP)
		{
			permission[3] = 'r';
		}
		if (buf.st_mode & S_IWGRP)
		{
			permission[4] = 'w';
		}
		if (buf.st_mode & S_IXGRP)
		{
			permission[5] = 'x';
		}
		if (buf.st_mode & S_IROTH)
		{
			permission[6] = 'r';
		}
		if (buf.st_mode & S_IWOTH)
		{
			permission[7] = 'w';
		}
		if (buf.st_mode & S_IXOTH)
		{
			permission[8] = 'x';
		}
		printf("Got Here2\n");
		// get the user name and group name
		
		pwd = getpwuid(buf.st_uid);
		printf("Got Here3\n");
		grp = getgrgid(buf.st_gid);
		printf("Got Here4\n");
		if (NULL == pwd)
		{
			printf("pw is null \n");
			exit(1);
		}
		if (NULL == grp)
		{
			printf("grp is null \n");
			exit(1);
		}
		printf("Got Here5\n");
		printf("%c", type);
		printf("Got Here6\n");
		
		i = 0;
		while (i<9)
		{
			printf("%c", permission[i]);
			i++;
		}
		printf("Got Here7\n");
		
		printf("%2d ", buf.st_nlink);
		printf("Got Here8\n");
		printf("%-4s", pwd->pw_name);
		printf("Got Here9\n");
		printf("%-4s", grp->gr_name);
		printf("Got Here10\n");
		
		printf("%6ld ", buf.st_size);
		printf("Got Here11\n");
		printf("%ld\n", buf.st_mtime);
		//printf("%s", ctime(&(buf.st_mtime)));
		/**
		 * [51206.712157] ls[31218]: segfault at 2ae5bc80 ip 00007fc42ab208d4 sp 00007ffd2151c128 error 4 in libc-2.21.so[7fc42aa95000+1c0000]
		 * 
		 * 
		 * Breakpoint 2, show_attr (name=0x7fffffffe14f "ls.c") at ls.c:117
			117			printf("%s", ctime(&(buf.st_mtime)));
			(gdb) n

			Program received signal SIGSEGV, Segmentation fault.
			0x00007ffff7a5d4b2 in _IO_vfprintf_internal (s=<optimized out>, format=<optimized out>, ap=ap@entry=0x7fffffffdaa8) at vfprintf.c:1642
			1642	vfprintf.c: No such file or directory.

		 * */
		//printf("%.12s",ctime(&buf.st_mtime)+4);
		printf("Got Here12\n");
		printf(" %s\n", name);
		printf("Got Here13\n");
	}
	else
	{
		printf("can't get the state of %s \n", name);
		exit(1);
	}
}
示例#24
0
/*
 * Arranges output according to a single parsed format substring.
 */
int
format1(const struct stat *st,
    const char *file,
    const char *fmt, int flen,
    char *buf, size_t blen,
    int flags, int size, int prec, int ofmt,
    int hilo, int what)
{
	u_int64_t data;
	char *stmp, lfmt[24], tmp[20];
	const char *sdata;
	char smode[12], sid[12], path[PATH_MAX + 4];
	struct passwd *pw;
	struct group *gr;
	const struct timespec *tsp;
	struct timespec ts;
	struct tm *tm;
	int l, small, formats;

	tsp = NULL;
	formats = 0;
	small = 0;

	/*
	 * First, pick out the data and tweak it based on hilo or
	 * specified output format (symlink output only).
	 */
	switch (what) {
	case SHOW_st_dev:
	case SHOW_st_rdev:
		small = (sizeof(st->st_dev) == 4);
		data = (what == SHOW_st_dev) ? st->st_dev : st->st_rdev;
#if HAVE_DEVNAME
		sdata = (what == SHOW_st_dev) ?
		    devname(st->st_dev, S_IFBLK) :
		    devname(st->st_rdev, 
		    S_ISCHR(st->st_mode) ? S_IFCHR :
		    S_ISBLK(st->st_mode) ? S_IFBLK :
		    0U);
		if (sdata == NULL)
			sdata = "???";
#endif /* HAVE_DEVNAME */
		if (hilo == HIGH_PIECE) {
			data = major(data);
			hilo = 0;
		}
		else if (hilo == LOW_PIECE) {
			data = minor((unsigned)data);
			hilo = 0;
		}
		formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX |
#if HAVE_DEVNAME
		    FMTF_STRING;
#else /* HAVE_DEVNAME */
		    0;
#endif /* HAVE_DEVNAME */
		if (ofmt == 0)
			ofmt = FMTF_UNSIGNED;
		break;
	case SHOW_st_ino:
		small = (sizeof(st->st_ino) == 4);
		data = st->st_ino;
		sdata = NULL;
		formats = FMTF_DECIMAL | FMTF_OCTAL | FMTF_UNSIGNED | FMTF_HEX;
		if (ofmt == 0)
			ofmt = FMTF_UNSIGNED;
		break;
	case SHOW_st_mode:
		small = (sizeof(st->st_mode) == 4);
		data = st->st_mode;
		strmode(st->st_mode, smode);
		stmp = smode;
		l = strlen(stmp);
		if (stmp[l - 1] == ' ')
			stmp[--l] = '\0';
		if (hilo == HIGH_PIECE) {
			data >>= 12;
			stmp += 1;
			stmp[3] = '\0';
			hilo = 0;
		}
		else if (hilo == MIDDLE_PIECE) {
示例#25
0
Errors File_getFileInfo(const String fileName,
                        FileInfo     *fileInfo
                       )
{
  struct stat64 fileStat;
  struct
  {
    time_t d0;
    time_t d1;
  } cast;

  assert(fileName != NULL);
  assert(fileInfo != NULL);

  if (lstat64(String_cString(fileName),&fileStat) != 0)
  {
    return ERRORX(IO_ERROR,errno,String_cString(fileName));
  }

  if      (S_ISREG(fileStat.st_mode)) fileInfo->type = FILE_TYPE_FILE;
  else if (S_ISDIR(fileStat.st_mode)) fileInfo->type = FILE_TYPE_DIRECTORY;
  else if (S_ISLNK(fileStat.st_mode)) fileInfo->type = FILE_TYPE_LINK;
  else if (S_ISCHR(fileStat.st_mode))
  {
    fileInfo->type        = FILE_TYPE_SPECIAL;
    fileInfo->specialType = FILE_SPECIAL_TYPE_CHARACTER_DEVICE;
  }
  else if (S_ISBLK(fileStat.st_mode))
  {
    fileInfo->type        = FILE_TYPE_SPECIAL;
    fileInfo->specialType = FILE_SPECIAL_TYPE_BLOCK_DEVICE;
  }
  else if (S_ISFIFO(fileStat.st_mode))
  {
    fileInfo->type        = FILE_TYPE_SPECIAL;
    fileInfo->specialType = FILE_SPECIAL_TYPE_FIFO;
  }
  else if (S_ISSOCK(fileStat.st_mode))
  {
    fileInfo->type        = FILE_TYPE_SPECIAL;
    fileInfo->specialType = FILE_SPECIAL_TYPE_SOCKET;
  }
  else
  {
    fileInfo->type        = FILE_TYPE_UNKNOWN;
  }
  fileInfo->size            = fileStat.st_size;
  fileInfo->timeLastAccess  = fileStat.st_atime;
  fileInfo->timeModified    = fileStat.st_mtime;
  fileInfo->timeLastChanged = fileStat.st_ctime;
  fileInfo->userId          = fileStat.st_uid;
  fileInfo->groupId         = fileStat.st_gid;
  fileInfo->permission      = fileStat.st_mode;
  fileInfo->major           = major(fileStat.st_rdev);
  fileInfo->minor           = minor(fileStat.st_rdev);
  cast.d0 = fileStat.st_mtime;
  cast.d1 = fileStat.st_ctime;
  memcpy(fileInfo->cast,&cast,sizeof(FileCast));

  return ERROR_NONE;
}
示例#26
0
static int handle_vma(pid_t pid, struct vma_area *vma_area,
			char *file_path, DIR *map_files_dir,
			struct vma_file_info *vfi,
			struct vma_file_info *prev_vfi,
			struct vm_area_list *vma_area_list)
{
	if (vma_get_mapfile(file_path, vma_area, map_files_dir, vfi, prev_vfi))
		goto err_bogus_mapfile;

	if (vma_area->e->status != 0) {
		if (vma_area->e->status & VMA_AREA_AIORING)
			vma_area_list->nr_aios++;
		return 0;
	} else if (!strcmp(file_path, "[vsyscall]") ||
		   !strcmp(file_path, "[vectors]")) {
		vma_area->e->status |= VMA_AREA_VSYSCALL;
	} else if (!strcmp(file_path, "[vdso]")) {
		if (handle_vdso_vma(vma_area))
			goto err;
	} else if (!strcmp(file_path, "[vvar]")) {
		if (handle_vvar_vma(vma_area))
			goto err;
	} else if (!strcmp(file_path, "[heap]")) {
		vma_area->e->status |= VMA_AREA_REGULAR | VMA_AREA_HEAP;
	} else {
		vma_area->e->status = VMA_AREA_REGULAR;
	}

	/*
	 * Some mapping hints for restore, we save this on
	 * disk and restore might need to analyze it.
	 */
	if (vma_area->file_borrowed) {
		struct vma_area *prev = prev_vfi->vma;

		/*
		 * Pick-up flags that might be set in the branch below.
		 * Status is copied as-is as it should be zero here,
		 * and have full match with the previous.
		 */
		vma_area->e->flags |= (prev->e->flags & MAP_ANONYMOUS);
		vma_area->e->status = prev->e->status;
		vma_area->e->shmid = prev->e->shmid;
		vma_area->vmst = prev->vmst;
		vma_area->mnt_id = prev->mnt_id;
	} else if (vma_area->vm_file_fd >= 0) {
		struct stat *st_buf = vma_area->vmst;

		if (S_ISREG(st_buf->st_mode))
			/* regular file mapping -- supported */;
		else if (S_ISCHR(st_buf->st_mode) && (st_buf->st_rdev == DEVZERO))
			/* devzero mapping -- also makes sense */;
		else {
			pr_err("Can't handle non-regular mapping on %d's map %"PRIx64"\n", pid, vma_area->e->start);
			goto err;
		}

		/*
		 * /dev/zero stands for anon-shared mapping
		 * otherwise it's some file mapping.
		 */
		if (is_anon_shmem_map(st_buf->st_dev)) {
			if (!(vma_area->e->flags & MAP_SHARED))
				goto err_bogus_mapping;
			vma_area->e->flags  |= MAP_ANONYMOUS;
			vma_area->e->status |= VMA_ANON_SHARED;
			vma_area->e->shmid = st_buf->st_ino;

			if (!strncmp(file_path, "/SYSV", 5)) {
				pr_info("path: %s\n", file_path);
				vma_area->e->status |= VMA_AREA_SYSVIPC;
			}
		} else {
			if (vma_area->e->flags & MAP_PRIVATE)
				vma_area->e->status |= VMA_FILE_PRIVATE;
			else
				vma_area->e->status |= VMA_FILE_SHARED;
		}

		/*
		 * We cannot use the mnt_id value provided by the kernel
		 * for vm_file_fd if it is an AUFS file (the value is
		 * wrong).  In such a case, fixup_aufs_vma_fd() has set
		 * mnt_id to -1 to mimic pre-3.15 kernels that didn't
		 * have mnt_id.
		 */
		if (vma_area->mnt_id != -1 &&
		    get_fd_mntid(vma_area->vm_file_fd, &vma_area->mnt_id))
			return -1;
	} else {
		/*
		 * No file but mapping -- anonymous one.
		 */
		if (vma_area->e->flags & MAP_SHARED) {
			vma_area->e->status |= VMA_ANON_SHARED;
			vma_area->e->shmid = vfi->ino;
		} else {
			vma_area->e->status |= VMA_ANON_PRIVATE;
		}
		vma_area->e->flags  |= MAP_ANONYMOUS;
	}

	return 0;
err:
	return -1;
err_bogus_mapping:
	pr_err("Bogus mapping 0x%"PRIx64"-0x%"PRIx64" (flags: %#x vm_file_fd: %d)\n",
	       vma_area->e->start, vma_area->e->end,
	       vma_area->e->flags, vma_area->vm_file_fd);
	goto err;

err_bogus_mapfile:
	pr_perror("Can't open %d's mapfile link %"PRIx64, pid, vma_area->e->start);
	goto err;
}
示例#27
0
/*
 * Create the file, or the directory
 *
 * fname is the original filename
 * ofile is the output filename (may be in a different directory)
 *
 * Returns:  CF_SKIP     if file should be skipped
 *           CF_ERROR    on error
 *           CF_EXTRACT  file created and data to restore
 *           CF_CREATED  file created no data to restore
 *
 * Note, we create the file here, except for special files,
 * we do not set the attributes because we want to first
 * write the file, then when the writing is done, set the
 * attributes.
 *
 * So, we return with the file descriptor open for normal files.
 */
int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace)
{
   mode_t new_mode, parent_mode;
   int flags;
   uid_t uid;
   gid_t gid;
   int pnl;
   bool exists = false;
   struct stat mstatp;
#ifndef HAVE_WIN32
   bool isOnRoot;
#endif

   bfd->reparse_point = false;
   if (is_win32_stream(attr->data_stream)) {
      set_win32_backup(bfd);
   } else {
      set_portable_backup(bfd);
   }

   new_mode = attr->statp.st_mode;
   Dmsg3(200, "type=%d newmode=%x file=%s\n", attr->type, new_mode, attr->ofname);
   parent_mode = S_IWUSR | S_IXUSR | new_mode;
   gid = attr->statp.st_gid;
   uid = attr->statp.st_uid;

#ifdef HAVE_WIN32
   if (!bfd->use_backup_api) {
      /*
       * Eliminate invalid windows filename characters from foreign filenames
       */
      char *ch = (char *)attr->ofname;
      if (ch[0] != 0 && ch[1] != 0) {
         ch += 2;
         while (*ch) {
            switch (*ch) {
            case ':':
            case '<':
            case '>':
            case '*':
            case '?':
            case '|':
               *ch = '_';
                break;
            }
            ch++;
         }
      }
   }
#endif

   Dmsg2(400, "Replace=%c %d\n", (char)replace, replace);
   if (lstat(attr->ofname, &mstatp) == 0) {
      exists = true;
      switch (replace) {
      case REPLACE_IFNEWER:
         if (attr->statp.st_mtime <= mstatp.st_mtime) {
            Qmsg(jcr, M_INFO, 0, _("File skipped. Not newer: %s\n"), attr->ofname);
            return CF_SKIP;
         }
         break;
      case REPLACE_IFOLDER:
         if (attr->statp.st_mtime >= mstatp.st_mtime) {
            Qmsg(jcr, M_INFO, 0, _("File skipped. Not older: %s\n"), attr->ofname);
            return CF_SKIP;
         }
         break;
      case REPLACE_NEVER:
         /*
          * Set attributes if we created this directory
          */
         if (attr->type == FT_DIREND && path_list_lookup(jcr->path_list, attr->ofname)) {
            break;
         }
         Qmsg(jcr, M_INFO, 0, _("File skipped. Already exists: %s\n"), attr->ofname);
         return CF_SKIP;
      case REPLACE_ALWAYS:
         break;
      }
   }

   switch (attr->type) {
   case FT_RAW:                       /* Raw device to be written */
   case FT_FIFO:                      /* FIFO to be written to */
   case FT_LNKSAVED:                  /* Hard linked, file already saved */
   case FT_LNK:
   case FT_SPEC:                      /* Fifo, ... to be backed up */
   case FT_REGE:                      /* Empty file */
   case FT_REG:                       /* Regular file */
      /*
       * Note, we do not delete FT_RAW because these are device files
       * or FIFOs that should already exist. If we blow it away,
       * we may blow away a FIFO that is being used to read the
       * restore data, or we may blow away a partition definition.
       */
      if (exists && attr->type != FT_RAW && attr->type != FT_FIFO) {
         /* Get rid of old copy */
         Dmsg1(400, "unlink %s\n", attr->ofname);
         if (secure_erase(jcr, attr->ofname) == -1) {
            berrno be;

            Qmsg(jcr, M_ERROR, 0, _("File %s already exists and could not be replaced. ERR=%s.\n"),
                 attr->ofname, be.bstrerror());
            /* Continue despite error */
         }
      }

      /*
       * Here we do some preliminary work for all the above
       *   types to create the path to the file if it does
       *   not already exist.  Below, we will split to
       *   do the file type specific work
       */
      pnl = separate_path_and_file(jcr, attr->fname, attr->ofname);
      if (pnl < 0) {
         return CF_ERROR;
      }

      /*
       * If path length is <= 0 we are making a file in the root
       *  directory. Assume that the directory already exists.
       */
      if (pnl > 0) {
         char savechr;
         savechr = attr->ofname[pnl];
         attr->ofname[pnl] = 0;                 /* terminate path */

         if (!path_already_seen(jcr, attr->ofname, pnl)) {
            Dmsg1(400, "Make path %s\n", attr->ofname);
            /*
             * If we need to make the directory, ensure that it is with
             * execute bit set (i.e. parent_mode), and preserve what already
             * exists. Normally, this should do nothing.
             */
            if (!makepath(attr, attr->ofname, parent_mode, parent_mode, uid, gid, 1)) {
               Dmsg1(10, "Could not make path. %s\n", attr->ofname);
               attr->ofname[pnl] = savechr;     /* restore full name */
               return CF_ERROR;
            }
         }
         attr->ofname[pnl] = savechr;           /* restore full name */
      }

      /*
       * Now we do the specific work for each file type
       */
      switch(attr->type) {
      case FT_REGE:
      case FT_REG:
         Dmsg1(100, "Create=%s\n", attr->ofname);
         flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; /*  O_NOFOLLOW; */
         if (IS_CTG(attr->statp.st_mode)) {
            flags |= O_CTG;              /* set contiguous bit if needed */
         }

         if (is_bopen(bfd)) {
            Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
            bclose(bfd);
         }

         if (bopen(bfd, attr->ofname, flags, 0, attr->statp.st_rdev) < 0) {
            berrno be;

            be.set_errno(bfd->berrno);
            Qmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"), attr->ofname, be.bstrerror());
            Dmsg2(100,"Could not create %s: ERR=%s\n", attr->ofname, be.bstrerror());

            return CF_ERROR;
         }

         return CF_EXTRACT;

#ifndef HAVE_WIN32 /* None of these exist in MS Windows */
      case FT_RAW:                    /* Bareos raw device e.g. /dev/sda1 */
      case FT_FIFO:                   /* Bareos fifo to save data */
      case FT_SPEC:
         flags = O_WRONLY | O_BINARY;

         isOnRoot = bstrcmp(attr->fname, attr->ofname) ? 1 : 0;
         if (S_ISFIFO(attr->statp.st_mode)) {
            Dmsg1(400, "Restore fifo: %s\n", attr->ofname);
            if (mkfifo(attr->ofname, attr->statp.st_mode) != 0 && errno != EEXIST) {
               berrno be;
               Qmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"),
                     attr->ofname, be.bstrerror());
               return CF_ERROR;
            }
         } else if (S_ISSOCK(attr->statp.st_mode)) {
             Dmsg1(200, "Skipping restore of socket: %s\n", attr->ofname);
#ifdef S_IFDOOR /* Solaris high speed RPC mechanism */
         } else if (S_ISDOOR(attr->statp.st_mode)) {
             Dmsg1(200, "Skipping restore of door file: %s\n", attr->ofname);
#endif
#ifdef S_IFPORT /* Solaris event port for handling AIO */
         } else if (S_ISPORT(attr->statp.st_mode)) {
             Dmsg1(200, "Skipping restore of event port file: %s\n", attr->ofname);
#endif
         } else if ((S_ISBLK(attr->statp.st_mode) || S_ISCHR(attr->statp.st_mode)) && !exists && isOnRoot) {
             /*
              * Fatal: Restoring a device on root-file system, but device node does not exist.
              * Should not create a dump file.
              */
             Qmsg1(jcr, M_ERROR, 0, _("Device restore on root failed, device %s missing.\n"), attr->fname);
             return CF_ERROR;
         } else if (S_ISBLK(attr->statp.st_mode) || S_ISCHR(attr->statp.st_mode)) {
             Dmsg1(400, "Restoring a device as a file: %s\n", attr->ofname);
             flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY;
         } else {
            Dmsg1(400, "Restore node: %s\n", attr->ofname);
            if (mknod(attr->ofname, attr->statp.st_mode, attr->statp.st_rdev) != 0 && errno != EEXIST) {
               berrno be;
               Qmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"),
                     attr->ofname, be.bstrerror());
               return CF_ERROR;
            }
         }

         /*
          * Here we are going to attempt to restore to a FIFO, which
          * means that the FIFO must already exist, AND there must
          * be some process already attempting to read from the
          * FIFO, so we open it write-only.
          */
         if (attr->type == FT_RAW || attr->type == FT_FIFO) {
            btimer_t *tid;
            Dmsg1(400, "FT_RAW|FT_FIFO %s\n", attr->ofname);
            /*
             * Timeout open() in 60 seconds
             */
            if (attr->type == FT_FIFO) {
               Dmsg0(400, "Set FIFO timer\n");
               tid = start_thread_timer(jcr, pthread_self(), 60);
            } else {
               tid = NULL;
            }
            if (is_bopen(bfd)) {
               Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
            }
            Dmsg2(400, "open %s flags=0x%x\n", attr->ofname, flags);
            if ((bopen(bfd, attr->ofname, flags, 0, 0)) < 0) {
               berrno be;
               be.set_errno(bfd->berrno);
               Qmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
                     attr->ofname, be.bstrerror());
               Dmsg2(400, "Could not open %s: ERR=%s\n", attr->ofname, be.bstrerror());
               stop_thread_timer(tid);
               return CF_ERROR;
            }
            stop_thread_timer(tid);
            return CF_EXTRACT;
         }
         Dmsg1(400, "FT_SPEC %s\n", attr->ofname);
         return CF_CREATED;

      case FT_LNKSAVED:                  /* Hard linked, file already saved */
         Dmsg2(130, "Hard link %s => %s\n", attr->ofname, attr->olname);
         if (link(attr->olname, attr->ofname) != 0) {
            berrno be;
#ifdef HAVE_CHFLAGS
            struct stat s;

            /*
             * If using BSD user flags, maybe has a file flag preventing this.
             * So attempt to disable, retry link, and reset flags.
             * Note that BSD securelevel may prevent disabling flag.
             */
            if (stat(attr->olname, &s) == 0 && s.st_flags != 0) {
               if (chflags(attr->olname, 0) == 0) {
                  if (link(attr->olname, attr->ofname) != 0) {
                     /*
                      * Restore original file flags even when linking failed
                      */
                     if (chflags(attr->olname, s.st_flags) < 0) {
                        Qmsg2(jcr, M_ERROR, 0, _("Could not restore file flags for file %s: ERR=%s\n"),
                              attr->olname, be.bstrerror());
                     }
#endif /* HAVE_CHFLAGS */
            Qmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"),
                  attr->ofname, attr->olname, be.bstrerror());
            Dmsg3(200, "Could not hard link %s -> %s: ERR=%s\n",
                  attr->ofname, attr->olname, be.bstrerror());
            return CF_ERROR;
#ifdef HAVE_CHFLAGS
                  }
                  /*
                   * Finally restore original file flags
                   */
                  if (chflags(attr->olname, s.st_flags) < 0) {
                     Qmsg2(jcr, M_ERROR, 0, _("Could not restore file flags for file %s: ERR=%s\n"),
                            attr->olname, be.bstrerror());
                  }
               } else {
                 Qmsg2(jcr, M_ERROR, 0, _("Could not reset file flags for file %s: ERR=%s\n"),
                       attr->olname, be.bstrerror());
               }
            } else {
              Qmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"),
                    attr->ofname, attr->olname, be.bstrerror());
              return CF_ERROR;
            }
#endif /* HAVE_CHFLAGS */

         }
         return CF_CREATED;

#endif /* HAVE_WIN32 */
#ifdef HAVE_WIN32
      case FT_LNK:
         /*
          * Handle Windows Symlink-Like Reparse Points
          * - Directory Symlinks
          * - File Symlinks
          * - Volume Mount Points
          * - Junctions
          */
         Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname);
         if (attr->statp.st_rdev & FILE_ATTRIBUTE_VOLUME_MOUNT_POINT) {
            /*
             * We do not restore volume mount points
             */
            Dmsg0(130, "Skipping Volume Mount Point\n");
            return CF_SKIP;
         }
         if (win32_symlink(attr->olname, attr->ofname, attr->statp.st_rdev) != 0 && errno != EEXIST) {
            berrno be;
            Qmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"),
                  attr->ofname, attr->olname, be.bstrerror());
            return CF_ERROR;
         }
         return CF_CREATED;
#else
      case FT_LNK:
         /*
          * Unix/Linux symlink handling
          */
         Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname);
         if (symlink(attr->olname, attr->ofname) != 0 && errno != EEXIST) {
            berrno be;
            Qmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"),
                  attr->ofname, attr->olname, be.bstrerror());
            return CF_ERROR;
         }
         return CF_CREATED;
#endif
      } /* End inner switch */

   case FT_REPARSE:
   case FT_JUNCTION:
      bfd->reparse_point = true;
      /*
       * Fall through wanted
       */
   case FT_DIRBEGIN:
   case FT_DIREND:
      Dmsg2(200, "Make dir mode=%o dir=%s\n", new_mode, attr->ofname);
      if (!makepath(attr, attr->ofname, new_mode, parent_mode, uid, gid, 0)) {
         return CF_ERROR;
      }
      /*
       * If we are using the Win32 Backup API, we open the directory so
       * that the security info will be read and saved.
       */
      if (!is_portable_backup(bfd)) {
         if (is_bopen(bfd)) {
            Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
         }
         if (bopen(bfd, attr->ofname, O_WRONLY | O_BINARY, 0, attr->statp.st_rdev) < 0) {
            berrno be;
            be.set_errno(bfd->berrno);
#ifdef HAVE_WIN32
            /*
             * Check for trying to create a drive, if so, skip
             */
            if (attr->ofname[1] == ':' &&
                IsPathSeparator(attr->ofname[2]) &&
                attr->ofname[3] == '\0') {
               return CF_SKIP;
            }
#endif
            Qmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
                  attr->ofname, be.bstrerror());
            return CF_ERROR;
         }
         return CF_EXTRACT;
      } else {
         return CF_CREATED;
      }

   case FT_DELETED:
      Qmsg2(jcr, M_INFO, 0, _("Original file %s have been deleted: type=%d\n"), attr->fname, attr->type);
      break;
   /*
    * The following should not occur
    */
   case FT_NOACCESS:
   case FT_NOFOLLOW:
   case FT_NOSTAT:
   case FT_DIRNOCHG:
   case FT_NOCHG:
   case FT_ISARCH:
   case FT_NORECURSE:
   case FT_NOFSCHG:
   case FT_NOOPEN:
      Qmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), attr->fname, attr->type);
      break;
   default:
      Qmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), attr->type, attr->fname);
      break;
   }
   return CF_ERROR;
}
示例#28
0
文件: ps.c 项目: Bluerise/openbsd-src
int
main(int argc, char *argv[])
{
	struct kinfo_proc *kp, **kinfo;
	struct varent *vent;
	struct winsize ws;
	dev_t ttydev;
	pid_t pid;
	uid_t uid;
	int all, ch, flag, i, fmt, lineno, nentries;
	int prtheader, showthreads, wflag, kflag, what, Uflag, xflg;
	char *nlistf, *memf, *swapf, *cols, errbuf[_POSIX2_LINE_MAX];

	setlocale(LC_CTYPE, "");

	termwidth = 0;
	if ((cols = getenv("COLUMNS")) != NULL)
		termwidth = strtonum(cols, 1, INT_MAX, NULL);
	if (termwidth == 0 &&
	    (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 ||
	    ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == 0 ||
	    ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == 0) &&
	    ws.ws_col > 0)
		termwidth = ws.ws_col - 1;
	if (termwidth == 0)
		termwidth = 79;

	if (argc > 1)
		argv[1] = kludge_oldps_options(argv[1]);

	all = fmt = prtheader = showthreads = wflag = kflag = Uflag = xflg = 0;
	pid = -1;
	uid = 0;
	ttydev = NODEV;
	memf = nlistf = swapf = NULL;
	while ((ch = getopt(argc, argv,
	    "AaCcegHhjkLlM:mN:O:o:p:rSTt:U:uvW:wx")) != -1)
		switch (ch) {
		case 'A':
			all = 1;
			xflg = 1;
			break;
		case 'a':
			all = 1;
			break;
		case 'C':
			break;			/* no-op */
		case 'c':
			commandonly = 1;
			break;
		case 'e':			/* XXX set ufmt */
			needenv = 1;
			break;
		case 'g':
			break;			/* no-op */
		case 'H':
			showthreads = 1;
			break;
		case 'h':
			prtheader = ws.ws_row > 5 ? ws.ws_row : 22;
			break;
		case 'j':
			parsefmt(jfmt);
			fmt = 1;
			jfmt[0] = '\0';
			break;
		case 'k':
			kflag = 1;
			break;
		case 'L':
			showkey();
			exit(0);
		case 'l':
			parsefmt(lfmt);
			fmt = 1;
			lfmt[0] = '\0';
			break;
		case 'M':
			memf = optarg;
			break;
		case 'm':
			sortby = SORTMEM;
			break;
		case 'N':
			nlistf = optarg;
			break;
		case 'O':
			parsefmt(o1);
			parsefmt(optarg);
			parsefmt(o2);
			o1[0] = o2[0] = '\0';
			fmt = 1;
			break;
		case 'o':
			parsefmt(optarg);
			fmt = 1;
			break;
		case 'p':
			pid = atol(optarg);
			xflg = 1;
			break;
		case 'r':
			sortby = SORTCPU;
			break;
		case 'S':
			sumrusage = 1;
			break;
		case 'T':
			if ((optarg = ttyname(STDIN_FILENO)) == NULL)
				errx(1, "stdin: not a terminal");
			/* FALLTHROUGH */
		case 't': {
			struct stat sb;
			char *ttypath, pathbuf[PATH_MAX];

			if (strcmp(optarg, "co") == 0)
				ttypath = _PATH_CONSOLE;
			else if (*optarg != '/') {
				int r = snprintf(pathbuf, sizeof(pathbuf), "%s%s",
				    _PATH_TTY, optarg);
				if (r < 0 || r > sizeof(pathbuf))
					errx(1, "%s: too long\n", optarg);
				ttypath = pathbuf;
			} else
				ttypath = optarg;
			if (stat(ttypath, &sb) == -1)
				err(1, "%s", ttypath);
			if (!S_ISCHR(sb.st_mode))
				errx(1, "%s: not a terminal", ttypath);
			ttydev = sb.st_rdev;
			break;
		}
		case 'U':
			if (uid_from_user(optarg, &uid) == -1)
				errx(1, "%s: no such user", optarg);
			Uflag = xflg = 1;
			break;
		case 'u':
			parsefmt(ufmt);
			sortby = SORTCPU;
			fmt = 1;
			ufmt[0] = '\0';
			break;
		case 'v':
			parsefmt(vfmt);
			sortby = SORTMEM;
			fmt = 1;
			vfmt[0] = '\0';
			break;
		case 'W':
			swapf = optarg;
			break;
		case 'w':
			if (wflag)
				termwidth = UNLIMITED;
			else if (termwidth < 131)
				termwidth = 131;
			wflag = 1;
			break;
		case 'x':
			xflg = 1;
			break;
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

#define	BACKWARD_COMPATIBILITY
#ifdef	BACKWARD_COMPATIBILITY
	if (*argv) {
		nlistf = *argv;
		if (*++argv) {
			memf = *argv;
			if (*++argv)
				swapf = *argv;
		}
	}
#endif

	if (nlistf == NULL && memf == NULL && swapf == NULL) {
		kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
		kvm_sysctl_only = 1;
	} else {
		kd = kvm_openfiles(nlistf, memf, swapf, O_RDONLY, errbuf);
	}
	if (kd == NULL)
		errx(1, "%s", errbuf);

	if (unveil(_PATH_DEVDB, "r") == -1 && errno != ENOENT)
		err(1, "unveil");
	if (unveil(_PATH_DEV, "r") == -1 && errno != ENOENT)
		err(1, "unveil");
	if (swapf)
		if (unveil(swapf, "r") == -1)
			err(1, "unveil");
	if (nlistf)
		if (unveil(nlistf, "r") == -1)
			err(1, "unveil");
	if (memf)
		if (unveil(memf, "r") == -1)
			err(1, "unveil");
	if (pledge("stdio rpath getpw ps", NULL) == -1)
		err(1, "pledge");

	if (!fmt) {
		if (showthreads)
			parsefmt(tfmt);
		else
			parsefmt(dfmt);
	}

	/* XXX - should be cleaner */
	if (!all && ttydev == NODEV && pid == -1 && !Uflag) {
		uid = getuid();
		Uflag = 1;
	}

	/*
	 * scan requested variables, noting what structures are needed,
	 * and adjusting header widths as appropriate.
	 */
	scanvars();

	if (neednlist && !nlistread)
		(void) donlist();

	/*
	 * get proc list
	 */
	if (Uflag) {
		what = KERN_PROC_UID;
		flag = uid;
	} else if (ttydev != NODEV) {
		what = KERN_PROC_TTY;
		flag = ttydev;
	} else if (pid != -1) {
		what = KERN_PROC_PID;
		flag = pid;
	} else if (kflag) {
		what = KERN_PROC_KTHREAD;
		flag = 0;
	} else {
		what = KERN_PROC_ALL;
		flag = 0;
	}
	if (showthreads)
		what |= KERN_PROC_SHOW_THREADS;

	/*
	 * select procs
	 */
	kp = kvm_getprocs(kd, what, flag, sizeof(*kp), &nentries);
	if (kp == NULL)
		errx(1, "%s", kvm_geterr(kd));

	/*
	 * print header
	 */
	printheader();
	if (nentries == 0)
		exit(1);
	/*
	 * sort proc list, we convert from an array of structs to an array
	 * of pointers to make the sort cheaper.
	 */
	if ((kinfo = reallocarray(NULL, nentries, sizeof(*kinfo))) == NULL)
		err(1, "failed to allocate memory for proc pointers");
	for (i = 0; i < nentries; i++)
		kinfo[i] = &kp[i];
	qsort(kinfo, nentries, sizeof(*kinfo), pscomp);
	/*
	 * for each proc, call each variable output function.
	 */
	for (i = lineno = 0; i < nentries; i++) {
		if (showthreads == 0 && (kinfo[i]->p_flag & P_THREAD) != 0)
			continue;
		if (xflg == 0 && ((int)kinfo[i]->p_tdev == NODEV ||
		    (kinfo[i]->p_psflags & PS_CONTROLT ) == 0))
			continue;
		if (showthreads && kinfo[i]->p_tid == -1)
			continue;
		for (vent = vhead; vent; vent = vent->next) {
			(vent->var->oproc)(kinfo[i], vent);
			if (vent->next != NULL)
				(void)putchar(' ');
		}
		(void)putchar('\n');
		if (prtheader && lineno++ == prtheader - 4) {
			(void)putchar('\n');
			printheader();
			lineno = 0;
		}
	}
	exit(eval);
}
示例#29
0
文件: 3.c 项目: hemiao3000/code
void show_mode(struct stat* st)
{
	char buf[11];

	if (S_ISREG(st->st_mode))
		buf[0] = '-';
	else if (S_ISDIR(st->st_mode))
		buf[0] = 'd';
	else if (S_ISCHR(st->st_mode))
		buf[0] = 'c';
	else if (S_ISBLK(st->st_mode))
		buf[0] = 'b';
	else if (S_ISFIFO(st->st_mode))
		buf[0] = 'p';
	else if (S_ISLNK(st->st_mode))
		buf[0] = 'l';
	else if (S_ISSOCK(st->st_mode))
		buf[0] = 's';
	else
		buf[0] = '0';
	
	if ((st->st_mode & 00400) != 0)
		buf[1] = 'r';
	else
		buf[1] = '-';

	if ((st->st_mode & 00200) != 0)
		buf[2] = 'w';
	else
		buf[2] = '-';

	if ((st->st_mode & 00100) != 0)
		buf[3] = 'x';
	else
		buf[3] = '-';

	if ((st->st_mode & 00040) != 0)
		buf[4] = 'r';
	else
		buf[4] = '-';

	if ((st->st_mode & 00020) != 0)
		buf[5] = 'w';
	else
		buf[5] = '-';

	if ((st->st_mode & 00010) != 0)
		buf[6] = 'x';
	else
		buf[6] = '-';

	if ((st->st_mode & 00004) != 0)
		buf[7] = 'r';
	else
		buf[7] = '-';

	if ((st->st_mode & 00002) != 0)
		buf[8] = 'w';
	else
		buf[8] = '-';

	if ((st->st_mode & 00001) != 0)
		buf[9] = 'x';
	else
		buf[9] = '-';
	
	buf[10] = '\0';

	printf("%s ", buf);
}
示例#30
0
/*
 * Reads the currect terminal path and initialize cxt->tty_* variables.
 */
static void init_tty(struct login_context *cxt)
{
	struct stat st;
	struct termios tt, ttt;

	cxt->tty_mode = (mode_t) getlogindefs_num("TTYPERM", TTY_MODE);

	get_terminal_name(&cxt->tty_path, &cxt->tty_name, &cxt->tty_number);

	/*
	 * In case login is suid it was possible to use a hardlink as stdin
	 * and exploit races for a local root exploit. (Wojciech Purczynski).
	 *
	 * More precisely, the problem is  ttyn := ttyname(0); ...; chown(ttyn);
	 * here ttyname() might return "/tmp/x", a hardlink to a pseudotty.
	 * All of this is a problem only when login is suid, which it isn't.
	 */
	if (!cxt->tty_path || !*cxt->tty_path ||
	    lstat(cxt->tty_path, &st) != 0 || !S_ISCHR(st.st_mode) ||
	    (st.st_nlink > 1 && strncmp(cxt->tty_path, "/dev/", 5)) ||
	    access(cxt->tty_path, R_OK | W_OK) != 0) {

		syslog(LOG_ERR, _("FATAL: bad tty"));
		sleepexit(EXIT_FAILURE);
	}

#ifdef LOGIN_CHOWN_VCS
	if (cxt->tty_number) {
		/* find names of Virtual Console devices, for later mode change */
		snprintf(cxt->vcsn, sizeof(cxt->vcsn), "/dev/vcs%s", cxt->tty_number);
		snprintf(cxt->vcsan, sizeof(cxt->vcsan), "/dev/vcsa%s", cxt->tty_number);
	}
#endif

	tcgetattr(0, &tt);
	ttt = tt;
	ttt.c_cflag &= ~HUPCL;

	if ((fchown(0, 0, 0) || fchmod(0, cxt->tty_mode)) && errno != EROFS) {

		syslog(LOG_ERR, _("FATAL: %s: change permissions failed: %m"),
				cxt->tty_path);
		sleepexit(EXIT_FAILURE);
	}

	/* Kill processes left on this tty */
	tcsetattr(0, TCSAFLUSH, &ttt);

	/*
	 * Let's close file decriptors before vhangup
	 * https://lkml.org/lkml/2012/6/5/145
	 */
	close(STDIN_FILENO);
	close(STDOUT_FILENO);
	close(STDERR_FILENO);

	signal(SIGHUP, SIG_IGN);	/* so vhangup() wont kill us */
	vhangup();
	signal(SIGHUP, SIG_DFL);

	/* open stdin,stdout,stderr to the tty */
	open_tty(cxt->tty_path);

	/* restore tty modes */
	tcsetattr(0, TCSAFLUSH, &tt);
}