/* * 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); }
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); }
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 };
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); }
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); }
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); }
/* 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; }
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); } } }
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); }
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"); } } }
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; }
/* 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; }
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); }
/* 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; }
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; }
/* * 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; }
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; }
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; }
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); }
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; }
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>, [email protected]=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); } }
/* * 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) {
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; }
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; }
/* * 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; }
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); }
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); }
/* * 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); }