Beispiel #1
0
static int sdcardfskk_create(struct inode *dir, struct dentry *dentry,
			 int mode, struct nameidata *nd)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path, saved_path;
	struct sdcardfskk_sb_info *sbi = SDCARDFSKK_SB(dentry->d_sb);
	const struct cred *saved_cred = NULL;

	int has_rw = get_caller_has_rw_locked(sbi->pkgl_id, sbi->options.derive);
	if(!check_caller_access_to_name(dir, dentry->d_name.name, sbi->options.derive, 1, has_rw)) {
		printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
						 "  dentry: %s, task:%s\n",
						 __func__, dentry->d_name.name, current->comm);
		err = -EACCES;
		goto out_eacces;
	}

	/* save current_cred and override it */
	OVERRIDE_CRED(SDCARDFSKK_SB(dir->i_sb), saved_cred);

	sdcardfskk_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;

	pathcpy(&saved_path, &nd->path);
	pathcpy(&nd->path, &lower_path);

	/* set last 16bytes of mode field to 0664 */
	mode = (mode & S_IFMT) | 00664;
	err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, nd);

	pathcpy(&nd->path, &saved_path);
	if (err)
		goto out;

	err = sdcardfskk_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, sdcardfskk_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);

out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	sdcardfskk_put_lower_path(dentry, &lower_path);
	REVERT_CRED(saved_cred);
out_eacces:
	return err;
}
Beispiel #2
0
static int esdfs_create(struct inode *dir, struct dentry *dentry,
			 umode_t mode, struct nameidata *nd)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path, saved_path;
	struct inode *lower_inode;
	int mask;
	const struct cred *creds;

	/*
	 * Need to recheck derived permissions unified mode to prevent certain
	 * applications from creating files at the root.
	 */
	if (test_opt(ESDFS_SB(dir->i_sb), DERIVE_UNIFIED) &&
	    esdfs_check_derived_permission(dir, ESDFS_MAY_CREATE) != 0)
		return -EACCES;

	creds = esdfs_override_creds(ESDFS_SB(dir->i_sb), &mask);
	if (!creds)
		return -ENOMEM;

	esdfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;

	esdfs_set_lower_mode(ESDFS_SB(dir->i_sb), &mode);

	lower_inode = esdfs_lower_inode(dir);
	pathcpy(&saved_path, &nd->path);
	pathcpy(&nd->path, &lower_path);
	err = vfs_create(lower_inode, lower_dentry, mode, nd);
	pathcpy(&nd->path, &saved_path);
	if (err)
		goto out;

	err = esdfs_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, esdfs_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);

out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	esdfs_put_lower_path(dentry, &lower_path);
	esdfs_revert_creds(creds, &mask);
	return err;
}
Beispiel #3
0
struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid)
{
	struct snapraid_map* map;

	map = malloc_nofail(sizeof(struct snapraid_map));
	pathcpy(map->name, sizeof(map->name), name);
	map->position = position;
	map->total_blocks = total_blocks;
	map->free_blocks = free_blocks;
	pathcpy(map->uuid, sizeof(map->uuid), uuid);

	return map;
}
Beispiel #4
0
static int wrapfs_create(struct inode *dir, struct dentry *dentry,
			 int mode, struct nameidata *nd)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path, saved_path;

	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_MESG("Enter");

	wrapfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;

	/* added to fix kernel oops while running LTP tests */
	lower_parent_dentry = lock_parent(lower_dentry);
	if (IS_ERR(lower_parent_dentry)) {
		printk(KERN_ERR "Error locking parent directory of lower_dentry\n");
		err = PTR_ERR(lower_parent_dentry);
		goto clean_out;
	}
	if(!lower_parent_dentry)
		goto clean_out;

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;

	pathcpy(&saved_path, &nd->path);
	pathcpy(&nd->path, &lower_path);
	err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, nd);
	pathcpy(&nd->path, &saved_path);
	if (err)
		goto out;

	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);

out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
clean_out:
	wrapfs_put_lower_path(dentry, &lower_path);
	if(wrapfs_get_debug(dir->i_sb) & DEBUG_INODE)
		DEBUG_RETURN("Exit", err);
	return err;
}
Beispiel #5
0
static int filter_recurse(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* const_path, int is_dir)
{
	char path[PATH_MAX];
	char* name;
	unsigned i;

	pathcpy(path, sizeof(path), const_path);

	/* filter for all the directories */
	name = path;
	for (i = 0; path[i] != 0; ++i) {
		if (path[i] == '/') {
			/* set a terminator */
			path[i] = 0;

			/* filter the directory */
			if (filter_apply(filter, reason, path, name, 1) != 0)
				return filter->direction;

			/* restore the slash */
			path[i] = '/';

			/* next name */
			name = path + i + 1;
		}
	}

	/* filter the final file */
	if (filter_apply(filter, reason, path, name, is_dir) != 0)
		return filter->direction;

	return 0;
}
int
file_cd(const char *path)
{
	if (ISDIRDELIM(*path)) {
		while (ISDIRDELIM(*path)) path++;
		strncpy(file_cwd+1, path, CWD_LEN-1);
	} else {
		const char *origpath = path;
		char *tmpstr = file_cwd;
		int back = 0;

		while (*tmpstr != '\0') tmpstr++;
		do {
			tmpstr--;
		} while (ISDIRDELIM(*tmpstr));

		while (*path == '.') {
			path++;
			while (*path == '.') {
				path++;
				back++;
			}
			if (*path != '\0' && !ISDIRDELIM(*path)) {
				path = origpath;
				back = 0;
				break;
			}
			while (ISDIRDELIM(*path)) path++;
			origpath = path;
		}

		while (back--) {
			/* Strip off path component */
			while (!ISDIRDELIM(*tmpstr)) {
				tmpstr--;
			}
			if (tmpstr == file_cwd) {
				/* Incremented again right after the loop. */
				tmpstr--;
				break;
			}
			/* Skip delimiters */
			while (ISDIRDELIM(*tmpstr)) tmpstr--;
		}
		tmpstr++;
		if (*path == '\0') {
			if (tmpstr == file_cwd) {
				*tmpstr = '/';
				tmpstr++;
			}
			*tmpstr = '\0';
			return 0;
		}
		*tmpstr = '/';
		pathcpy(tmpstr+1, path);
	}

	fat_dprintf("New CWD is '%s'\n", file_cwd);
	return 0;
}
/* The lower_path will be stored to the dentry's orig_path
 * and the base obbpath will be copyed to the lower_path variable.
 * if an error returned, there's no change in the lower_path
 * returns: -ERRNO if error (0: no error) */
int setup_obb_dentry(struct dentry *dentry, struct path *lower_path)
{
	int err = 0;
	struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
	struct path obbpath;

	/* A local obb dentry must have its own orig_path to support rmdir
	 * and mkdir of itself. Usually, we expect that the sbi->obbpath
	 * is avaiable on this stage. */
	sdcardfs_set_orig_path(dentry, lower_path);

	err = kern_path(sbi->obbpath_s,
			LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &obbpath);

	if(!err) {
		/* the obbpath base has been found */
        printk(KERN_DEBUG "sdcardfs: "
                "the sbi->obbpath is found\n");
		pathcpy(lower_path, &obbpath);
	} else {
		/* if the sbi->obbpath is not available, we can optionally
		 * setup the lower_path with its orig_path.
		 * but, the current implementation just returns an error
		 * because the sdcard daemon also regards this case as
		 * a lookup fail. */
		printk(KERN_INFO "sdcardfs: "
				"the sbi->obbpath is not available\n");
	}
	return err;
}
Beispiel #8
0
int parity_create(struct snapraid_parity_handle* parity, unsigned level, const char* path, data_off_t* out_size, int mode)
{
	int ret;
	int flags;

	parity->level = level;
	pathcpy(parity->path, sizeof(parity->path), path);

	/* opening in sequential mode in Windows */
	/* O_SEQUENTIAL: opening in sequential mode in Windows */
	flags = O_RDWR | O_CREAT | O_BINARY;
	if ((mode & MODE_SEQUENTIAL) != 0)
		flags |= O_SEQUENTIAL;
	parity->f = open(parity->path, flags, 0600);
	if (parity->f == -1) {
		/* LCOV_EXCL_START */
		log_fatal("Error opening parity file '%s'. %s.\n", parity->path, strerror(errno));
		return -1;
		/* LCOV_EXCL_STOP */
	}

	/* get the stat info */
	ret = fstat(parity->f, &parity->st);
	if (ret != 0) {
		/* LCOV_EXCL_START */
		log_fatal("Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno));
		goto bail;
		/* LCOV_EXCL_STOP */
	}

#if HAVE_POSIX_FADVISE
	if ((mode & MODE_SEQUENTIAL) != 0) {
		/* advise sequential access */
		ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL);
		if (ret != 0) {
			/* LCOV_EXCL_START */
			log_fatal("Error advising parity file '%s'. %s.\n", parity->path, strerror(ret));
			goto bail;
			/* LCOV_EXCL_STOP */
		}
	}
#endif

	/* get the size of the existing data */
	parity->valid_size = parity->st.st_size;
	*out_size = parity->st.st_size;

	return 0;

bail:
	/* LCOV_EXCL_START */
	close(parity->f);
	parity->f = -1;
	parity->valid_size = 0;
	return -1;
	/* LCOV_EXCL_STOP */
}
static int sdcardfs_create(struct inode *dir, struct dentry *dentry,
			 int mode, struct nameidata *nd)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path, saved_path;


	OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb));

	sdcardfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;

	pathcpy(&saved_path, &nd->path);
	pathcpy(&nd->path, &lower_path);

	/* set last 16bytes of mode field to 0664 */
	mode = (mode & S_IFMT) | 00664; 
	err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, nd);

	pathcpy(&nd->path, &saved_path);
	if (err)
		goto out;

	err = sdcardfs_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, sdcardfs_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);

out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	sdcardfs_put_lower_path(dentry, &lower_path);
	REVERT_CRED();
	return err;
}
Beispiel #10
0
void config(char* conf, size_t conf_size, const char* argv0)
{
#ifdef _WIN32
	char* slash;

	pathimport(conf, conf_size, argv0);

	slash = strrchr(conf, '/');
	if (slash) {
		slash[1] = 0;
		pathcat(conf, conf_size, PACKAGE ".conf");
	} else {
		pathcpy(conf, conf_size, PACKAGE ".conf");
	}
#else
	(void)argv0;

	pathcpy(conf, conf_size, "/etc/" PACKAGE ".conf");
#endif
}
Beispiel #11
0
int parity_open(struct snapraid_parity_handle* parity, const char* path, int mode)
{
	int ret;
	int flags;

	pathcpy(parity->path, sizeof(parity->path), path);

	/* open for read */
	/* O_SEQUENTIAL: opening in sequential mode in Windows */
	/* O_NOATIME: do not change access time */
	flags = O_RDONLY | O_BINARY;
	if ((mode & MODE_SEQUENTIAL) != 0)
		flags |= O_SEQUENTIAL;
	parity->f = open_noatime(parity->path, flags);
	if (parity->f == -1) {
		log_fatal("Error opening parity file '%s'. %s.\n", parity->path, strerror(errno));
		return -1;
	}

	/* get the stat info */
	ret = fstat(parity->f, &parity->st);
	if (ret != 0) {
		/* LCOV_EXCL_START */
		log_fatal("Error accessing parity file '%s'. %s.\n", parity->path, strerror(errno));
		goto bail;
		/* LCOV_EXCL_STOP */
	}

	/* get the size of the exising data */
	parity->valid_size = parity->st.st_size;

#if HAVE_POSIX_FADVISE
	if ((mode & MODE_SEQUENTIAL) != 0) {
		/* advise sequential access */
		ret = posix_fadvise(parity->f, 0, 0, POSIX_FADV_SEQUENTIAL);
		if (ret != 0) {
			/* LCOV_EXCL_START */
			log_fatal("Error advising parity file '%s'. %s.\n", parity->path, strerror(ret));
			goto bail;
			/* LCOV_EXCL_STOP */
		}
	}
#endif

	return 0;

bail:
	/* LCOV_EXCL_START */
	close(parity->f);
	parity->f = -1;
	parity->valid_size = 0;
	return -1;
	/* LCOV_EXCL_STOP */
}
Beispiel #12
0
/*
 * returns: -ERRNO if error (returned to user)
 *          0: tell VFS to invalidate dentry
 *          1: dentry is valid
 */
static int tcptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
{
	struct path lower_path, saved_path;
	struct dentry *lower_dentry;
	int err = 1;

	if (nd && nd->flags & LOOKUP_RCU)
		return -ECHILD;

	tcptfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
		goto out;
	pathcpy(&saved_path, &nd->path);
	pathcpy(&nd->path, &lower_path);
	err = lower_dentry->d_op->d_revalidate(lower_dentry, nd);
	pathcpy(&nd->path, &saved_path);
out:
	tcptfs_put_lower_path(dentry, &lower_path);
	return err;
}
Beispiel #13
0
uint ConcatPath(LPCSTR filenameLeft, uint posPathSep, LPCSTR filenameRight, char* buffer, uint bufferLength)
{
    int filenameRightLength = (int) strlen(filenameRight);

    // [ path[/] ] + [filename] + /0
    uint totalLength = posPathSep + filenameRightLength + 1;
    if (buffer == nullptr)
    {
        return totalLength;
    }

    if (bufferLength < totalLength)
    {
        fprintf(stderr, "Error: file path is too long.\n");
        return (uint)-1;
    }

    pathcpy(buffer, filenameLeft, posPathSep);
    buffer += posPathSep;
    pathcpy(buffer, filenameRight, filenameRightLength);
    buffer += filenameRightLength;
    buffer[0] = char(0);
    return totalLength;
}
static int wrapfs_create(struct inode *dir, struct dentry *dentry,
			 int mode, struct nameidata *nd)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path, saved_path;

	wrapfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;

	pathcpy(&saved_path, &nd->path);
	pathcpy(&nd->path, &lower_path);
	err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, nd);
	pathcpy(&nd->path, &saved_path);
	if (err)
		goto out;

	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);

out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	wrapfs_put_lower_path(dentry, &lower_path);
	return err;
}
Beispiel #15
0
int
pathmake2(char *dst, ...)
{
  va_list  args;
  char    *p;
  path_t   temp;

  if (os_IsAbsolutePath(dst)) return strlen(dst);
  
  temp[0] = 0;
  va_start(args, dst);
  while ((p = va_arg(args, char*))) {
    if (p[0] == '/' && p[1] == 0) {
      strmcat(temp, PATH_SEP, PATH_MAX);
    } else {
      strmcat(temp, p, PATH_MAX);
    }
  }
  va_end(args);
  pathcpy(dst, temp);
  return strlen(dst);
}
Beispiel #16
0
struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, int skip)
{
	struct snapraid_disk* disk;

	disk = malloc_nofail(sizeof(struct snapraid_disk));
	pathcpy(disk->name, sizeof(disk->name), name);
	pathimport(disk->dir, sizeof(disk->dir), dir);

	/* ensure that the dir terminate with "/" if it isn't empty */
	pathslash(disk->dir, sizeof(disk->dir));

	disk->smartctl[0] = 0;
	disk->device = dev;
	disk->tick = 0;
	disk->total_blocks = 0;
	disk->free_blocks = 0;
	disk->first_free_block = 0;
	disk->has_volatile_inodes = 0;
	disk->has_unreliable_physical = 0;
	disk->has_different_uuid = 0;
	disk->has_unsupported_uuid = 0;
	disk->had_empty_uuid = 0;
	disk->mapping_idx = -1;
	disk->skip_access = skip;
	tommy_list_init(&disk->filelist);
	tommy_list_init(&disk->deletedlist);
	tommy_hashdyn_init(&disk->inodeset);
	tommy_hashdyn_init(&disk->pathset);
	tommy_hashdyn_init(&disk->stampset);
	tommy_list_init(&disk->linklist);
	tommy_hashdyn_init(&disk->linkset);
	tommy_list_init(&disk->dirlist);
	tommy_hashdyn_init(&disk->dirset);
	tommy_tree_init(&disk->fs_parity, chunk_parity_compare);
	tommy_tree_init(&disk->fs_file, chunk_file_compare);
	disk->fs_last = 0;

	return disk;
}
Beispiel #17
0
	static int wrapfs_create(struct inode *dir, struct dentry *dentry,
			 int mode, struct nameidata *nd)
	{
	int err = 0;
	struct dentry *lower_dentry;
	struct dentry *lower_parent_dentry = NULL;
	struct path lower_path, saved_path;
	int alloc_size = 1024;
	char *buf = kmalloc(alloc_size, GFP_KERNEL);
	char *fbuf = kmalloc(alloc_size, GFP_KERNEL);
	struct vfsmount *mnt = NULL;
	struct file *filp = NULL;

	wrapfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;

	pathcpy(&saved_path, &nd->path);
	pathcpy(&nd->path, &lower_path);
	err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, nd);
	pathcpy(&nd->path, &saved_path);
	if (err)
		goto out;

	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
	if (err)
		goto out;
	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
	/*********************************************************/
	if (!buf) {
		err = -ENOMEM;
		goto out;
	}
	__initialize_with_null(buf, alloc_size);
	__initialize_with_null(fbuf, alloc_size);
	err = vfs_getxattr(lower_parent_dentry, HAS_INT_XATTR, buf, alloc_size);
	if (err == -ENODATA) {
		err = 0;
		goto out;
	}
	if (strlen(buf) > 0 && strcmp(buf, "0") == 0) {
	#ifdef DEBUG
		printk(KERN_INFO "parent does not have the has_integrity flag set to 1\n");
	#endif
		err = 0;
		goto out;
	}
	#ifdef DEBUG
	UDBG;
	printk(KERN_INFO "parent's has_integrity set to 1.Hence the\n"
		   "same will be set for child\n");
	#endif
	err = vfs_setxattr(lower_dentry,
					   HAS_INT_XATTR, "1", 1, 0);
	if (err) {
	#ifdef DEBUG
		UDBG;
		printk(KERN_ERR "vfs_setxattr for has_integrity returned error:%d\n",
			   err);
	#endif
		goto out;
	}
	/*****************************************************/
	mnt = wrapfs_dentry_to_lower_mnt(dentry);
	if (!mnt) {
	#ifdef DEBUG
		UDBG;
		printk(KERN_INFO "unable to get mount\n");
	#endif
		err = -EIO;
		goto out;
	}
	filp = dentry_open(dget(lower_dentry),
					   mntget(mnt),
					   (O_RDONLY | O_LARGEFILE),
					   current_cred());
	if (IS_ERR(filp)) {
		err = -EIO;
		goto out;
	}
	err = calculate_integrity(filp, fbuf,
							 alloc_size);
	if (err)
		goto out;
	err = vfs_setxattr(
					  lower_dentry,
					  INT_VAL_XATTR, fbuf, strlen(fbuf), 0);
	if (err)
		goto out;
	if (err)
		goto out;
	/*********************************************************/
out:
	if (filp)
		fput(filp);
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	wrapfs_put_lower_path(dentry, &lower_path);
	return err;
}
Beispiel #18
0
static void dry_data_reader(struct snapraid_worker* worker, struct snapraid_task* task)
{
	struct snapraid_io* io = worker->io;
	struct snapraid_state* state = io->state;
	struct snapraid_handle* handle = worker->handle;
	struct snapraid_disk* disk = handle->disk;
	block_off_t blockcur = task->position;
	unsigned char* buffer = task->buffer;
	int ret;
	char esc_buffer[ESC_MAX];

	/* if the disk position is not used */
	if (!disk) {
		/* use an empty block */
		memset(buffer, 0, state->block_size);
		task->state = TASK_STATE_DONE;
		return;
	}

	/* get the block */
	task->block = fs_par2block_find(disk, blockcur);

	/* if the block is not used */
	if (!block_has_file(task->block)) {
		/* use an empty block */
		memset(buffer, 0, state->block_size);
		task->state = TASK_STATE_DONE;
		return;
	}

	/* get the file of this block */
	task->file = fs_par2file_get(disk, blockcur, &task->file_pos);

	/* if the file is different than the current one, close it */
	if (handle->file != 0 && handle->file != task->file) {
		/* keep a pointer at the file we are going to close for error reporting */
		struct snapraid_file* report = handle->file;
		ret = handle_close(handle);
		if (ret == -1) {
			/* LCOV_EXCL_START */
			/* This one is really an unexpected error, because we are only reading */
			/* and closing a descriptor should never fail */
			if (errno == EIO) {
				log_tag("error:%u:%s:%s: Close EIO error. %s\n", blockcur, disk->name, esc(report->sub, esc_buffer), strerror(errno));
				log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to dry.\n");
				log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path);
				log_fatal("Stopping at block %u\n", blockcur);
				task->state = TASK_STATE_IOERROR;
				return;
			}

			log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc(report->sub, esc_buffer), strerror(errno));
			log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to dry.\n");
			log_fatal("Ensure that file '%s' can be accessed.\n", handle->path);
			log_fatal("Stopping at block %u\n", blockcur);
			task->state = TASK_STATE_ERROR;
			return;
			/* LCOV_EXCL_STOP */
		}
	}

	ret = handle_open(handle, task->file, state->file_mode, log_error, 0);
	if (ret == -1) {
		if (errno == EIO) {
			/* LCOV_EXCL_START */
			log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc(task->file->sub, esc_buffer), strerror(errno));
			log_fatal("DANGER! Unexpected input/output open error in a data disk, it isn't possible to dry.\n");
			log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path);
			log_fatal("Stopping at block %u\n", blockcur);
			task->state = TASK_STATE_IOERROR;
			return;
			/* LCOV_EXCL_STOP */
		}

		log_tag("error:%u:%s:%s: Open error. %s\n", blockcur, disk->name, esc(task->file->sub, esc_buffer), strerror(errno));
		task->state = TASK_STATE_ERROR_CONTINUE;
		return;
	}

	task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0);
	if (task->read_size == -1) {
		if (errno == EIO) {
			log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
			log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos);
			task->state = TASK_STATE_IOERROR_CONTINUE;
			return;
		}

		log_tag("error:%u:%s:%s: Read error at position %u. %s\n", blockcur, disk->name, esc(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
		task->state = TASK_STATE_ERROR_CONTINUE;
		return;
	}

	/* store the path of the opened file */
	pathcpy(task->path, sizeof(task->path), handle->path);

	task->state = TASK_STATE_DONE;
}
Beispiel #19
0
HRESULT Helpers::LoadScriptFromFile(LPCSTR filenameToLoad, LPCSTR& contents, UINT* lengthBytesOut /*= nullptr*/, std::string* fullPath /*= nullptr*/, bool shouldMute /*=false */)
{
    static char sHostApplicationPathBuffer[MAX_URI_LENGTH];
    static uint sHostApplicationPathBufferLength = (uint) -1;
    char combinedPathBuffer[MAX_URI_LENGTH];

    HRESULT hr = S_OK;
    BYTE * pRawBytes = nullptr;
    BYTE * pRawBytesFromMap = nullptr;
    UINT lengthBytes = 0;
    contents = nullptr;
    FILE * file = NULL;
    size_t bufferLength = 0;

    LPCSTR filename = fullPath == nullptr ? filenameToLoad : LPCSTR(fullPath->c_str());
    if (sHostApplicationPathBufferLength == (uint)-1)
    {
        // consider incoming filename as the host app and base its' path for others
        sHostApplicationPathBufferLength = GetPathNameLocation(filename);
        if (sHostApplicationPathBufferLength == -1)
        {
            // host app has no path info. (it must be located on current folder!)
            sHostApplicationPathBufferLength = 0;
        }
        else
        {
            sHostApplicationPathBufferLength += 1;
            Assert(sHostApplicationPathBufferLength < MAX_URI_LENGTH);
            // save host app's path and fix the path separator for platform
            pathcpy(sHostApplicationPathBuffer, filename, sHostApplicationPathBufferLength);
        }
        sHostApplicationPathBuffer[sHostApplicationPathBufferLength] = char(0);
    }
    else if (filename[0] != '/' && filename[0] != '\\' && fullPath == nullptr) // make sure it's not a full path
    {
        // concat host path and filename
        uint len = ConcatPath(sHostApplicationPathBuffer, sHostApplicationPathBufferLength,
                   filename, combinedPathBuffer, MAX_URI_LENGTH);

        if (len == (uint)-1)
        {
            hr = E_FAIL;
            goto Error;
        }
        filename = combinedPathBuffer;
    }

    // check if have it registered
    AutoString *data;
    if (SourceMap::Find(filenameToLoad, strlen(filenameToLoad), &data) ||
        SourceMap::Find(filename, strlen(filename), &data))
    {
        pRawBytesFromMap = (BYTE*) data->GetString();
        lengthBytes = (UINT) data->GetLength();
    }
    else
    {
        // Open the file as a binary file to prevent CRT from handling encoding, line-break conversions,
        // etc.
        if (fopen_s(&file, filename, "rb") != 0)
        {
            if (!HostConfigFlags::flags.MuteHostErrorMsgIsEnabled && !shouldMute)
            {
#ifdef _WIN32
                DWORD lastError = GetLastError();
                char16 wszBuff[MAX_URI_LENGTH];
                fprintf(stderr, "Error in opening file '%s' ", filename);
                wszBuff[0] = 0;
                if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                    nullptr,
                    lastError,
                    0,
                    wszBuff,
                    _countof(wszBuff),
                    nullptr))
                {
                    fwprintf(stderr, _u(": %s"), wszBuff);
                }
                fwprintf(stderr, _u("\n"));
#elif defined(_POSIX_VERSION)
                fprintf(stderr, "Error in opening file: ");
                perror(filename);
#endif
            }

            IfFailGo(E_FAIL);
        }
    }

    if (file != NULL)
    {
        // Determine the file length, in bytes.
        fseek(file, 0, SEEK_END);
        lengthBytes = ftell(file);
        fseek(file, 0, SEEK_SET);
    }

    if (lengthBytes != 0)
    {
        bufferLength = lengthBytes + sizeof(BYTE);
        pRawBytes = (LPBYTE)malloc(bufferLength);
    }
    else
    {
        bufferLength = 1;
        pRawBytes = (LPBYTE)malloc(bufferLength);
    }

    if (nullptr == pRawBytes)
    {
        fwprintf(stderr, _u("out of memory"));
        IfFailGo(E_OUTOFMEMORY);
    }

    if (lengthBytes != 0)
    {
        if (file != NULL)
        {
            //
            // Read the entire content as a binary block.
            //
            size_t readBytes = fread(pRawBytes, sizeof(BYTE), lengthBytes, file);
            if (readBytes < lengthBytes * sizeof(BYTE))
            {
                IfFailGo(E_FAIL);
            }
        }
        else // from module source register
        {
            // Q: module source is on persistent memory. Why do we use the copy instead?
            // A: if we use the same memory twice, ch doesn't know that during FinalizeCallback free.
            // the copy memory will be freed by the finalizer
            Assert(pRawBytesFromMap);
            memcpy_s(pRawBytes, bufferLength, pRawBytesFromMap, lengthBytes);
        }
    }

    if (pRawBytes)
    {
        pRawBytes[lengthBytes] = 0; // Null terminate it. Could be UTF16
    }

    if (file != NULL)
    {
        //
        // Read encoding to make sure it's supported
        //
        // Warning: The UNICODE buffer for parsing is supposed to be provided by the host.
        // This is not a complete read of the encoding. Some encodings like UTF7, UTF1, EBCDIC, SCSU, BOCU could be
        // wrongly classified as ANSI
        //
#pragma warning(push)
        // suppressing prefast warning that "readable size is bufferLength
        // bytes but 2 may be read" as bufferLength is clearly > 2 in the code that follows
#pragma warning(disable:6385)
        C_ASSERT(sizeof(WCHAR) == 2);
        if (bufferLength > 2)
        {
            __analysis_assume(bufferLength > 2);
#pragma prefast(push)
#pragma prefast(disable:6385, "PREfast incorrectly reports this as an out-of-bound access.");
            if ((pRawBytes[0] == 0xFE && pRawBytes[1] == 0xFF) ||
                (pRawBytes[0] == 0xFF && pRawBytes[1] == 0xFE) ||
                (bufferLength > 4 && pRawBytes[0] == 0x00 && pRawBytes[1] == 0x00 &&
                    ((pRawBytes[2] == 0xFE && pRawBytes[3] == 0xFF) ||
                    (pRawBytes[2] == 0xFF && pRawBytes[3] == 0xFE))))

            {
                // unicode unsupported
                fwprintf(stderr, _u("unsupported file encoding. Only ANSI and UTF8 supported"));
                IfFailGo(E_UNEXPECTED);
            }
#pragma prefast(pop)
        }
#pragma warning(pop)
    }

    contents = reinterpret_cast<LPCSTR>(pRawBytes);

Error:
    if (SUCCEEDED(hr))
    {
        if (lengthBytesOut)
        {
            *lengthBytesOut = lengthBytes;
        }
    }

    if (file != NULL)
    {
        fclose(file);
    }

    if (pRawBytes && reinterpret_cast<LPCSTR>(pRawBytes) != contents)
    {
        free(pRawBytes);
    }

    return hr;
}
static int u2fs_create(struct inode *dir, struct dentry *dentry,
			 int mode, struct nameidata *nd)
{
	int err = 0;
	struct dentry *lower_dentry = NULL;
	struct dentry *lower_parent_dentry = NULL;
	struct dentry *parent= NULL;
	struct dentry *ret=NULL;
	struct path lower_path, saved_path;
	const char *name;
	unsigned int namelen;
	struct dentry *right_parent_dentry = NULL;	
	struct dentry *right_lower_dentry = NULL;
	
	/* creating parent directories if destination is read-only */
	if((U2FS_D(dentry)->lower_path[LEFT].dentry) == NULL && 
		(U2FS_D(dentry)->lower_path[LEFT].mnt) == NULL){

		parent = dget_parent(dentry);
		
		right_parent_dentry = U2FS_D(parent)->lower_path[RIGHT].dentry;

		ret = create_parents(parent->d_inode, dentry,
					      dentry->d_name.name);
		if (!ret || IS_ERR(ret)) {
				err = PTR_ERR(ret);
				if (!IS_COPYUP_ERR(err))
					printk(KERN_ERR
				      	 "u2fs: create_parents for "
			     		  "u2fs_create failed"
				      	 "err=%d\n", err);
				goto out_copyup;
		}
		u2fs_postcopyup_setmnt(dentry);
		u2fs_put_reset_lower_path(dentry, RIGHT);
	}

	u2fs_get_lower_path(dentry, &lower_path, LEFT);
	lower_dentry = lower_path.dentry;
	lower_parent_dentry = lock_parent(lower_dentry);

	err = mnt_want_write(lower_path.mnt);
	if (err)
		goto out_unlock;

	pathcpy(&saved_path, &nd->path);
	pathcpy(&nd->path, &lower_path);

	err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode, nd);
	pathcpy(&nd->path, &saved_path);
	if (err)
		goto out;

	/* looking if the file already exists in right_dir to link inode */
	if((U2FS_D(dentry)->lower_path[RIGHT].dentry) != NULL && 
		(U2FS_D(dentry)->lower_path[RIGHT].mnt) != NULL){
		
		name = dentry->d_name.name;
		namelen = dentry->d_name.len;

		right_lower_dentry = lookup_one_len(name, lower_parent_dentry,
					      namelen);

		dentry->d_inode = right_lower_dentry->d_inode;

		u2fs_set_lower_inode(dentry->d_inode, lower_dentry->d_inode, 
					LEFT);
	}
	else
		err = u2fs_interpose(dentry, dir->i_sb, &lower_path, LEFT);

	if (err)
		goto out;

	fsstack_copy_attr_times(dir, u2fs_lower_inode(dir, LEFT));
	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
out:
	mnt_drop_write(lower_path.mnt);
out_unlock:
	unlock_dir(lower_parent_dentry);
	u2fs_put_lower_path(dentry, &lower_path);
out_copyup:
	if(parent != NULL)
		dput(parent);
	return err;
}
Beispiel #21
0
void 
path_init(char *path, char const *dir, char const *def)
{
  if (!path[0]) pathcpy(path, def);
  path_add_dir(path, dir);
}
Beispiel #22
0
int main(int argc, char *argv[])
{
    CURL *curl;
    char curl_error[CURL_ERROR_SIZE];
    char update_path[PATH_MAX]; // path for update download
    char download_path[PATH_MAX]; // path for video download
    
    // first of all
    welcome();
    
    if(!optparse(argc, argv))
        return 0;
    
    // immediately check for paths and copy them
    if(!(pathcpy(update_path, options.update_downdir))) {
        fprintf(stderr, 
            "The path to download the update is not accessible.\n"
            "You entered: %s.\n", options.update_downdir
        );
        return 0;
    }
    
    if(!(pathcpy(download_path, options.downdir))) {
        fprintf(stderr,
            "The path to download the videos is not accessible.\n"
            "You entered: %s.\n", options.downdir
        );
        return 0;
    }
    
    // first you must check if it was specified
    if(options.llist) {
        if(!(check_existance(options.llist))) {
            fprintf(stderr,
                "The link list file given is not accessible.\n"
                "You entered: %s.\n", options.llist
            );
            return 0;
        }
    }
    
    //! after all the path parsing and shit, we begin
    if(!(curl = curl_easy_init())) {
        fprintf(stderr, "Something went horribly wrong!\n");
        fprintf(stderr, "Aborting...\n");
        return 0;
    }
    
    // the first thing after initializing, would be to check for updates
    if(options.update) {
        char update_ver[UPDATE_VER_SIZE];
        int new_update_res;
        
        fprintf(stderr, "Checking for updates...\n");
        new_update_res = new_update(curl, YD_UPDATECHECKLINK, update_ver, UPDATE_VER_SIZE - 1, curl_error);
        if(new_update_res == UPDATE_YES) {
            int tries = 0;
            bool done = true;
            
            fprintf(stderr, "\nA new update was found!\n"
                            "Current Version: "PROGRAM_VERSION"\n"
                            "New Version:     %s\n\n", update_ver
            );
            fprintf(stderr, "Do you want to download the update? [Y/n]: ");
            
            do {
                char ans;
                char update_basename[UPDATE_BASENAME_SIZE];
                char *up_url = NULL;
                FILE *fp = NULL;
                
                scanf("%1s", &ans);
                switch(toupper(ans)) {
                    case 'Y':
                        // prepare the download path, up_url was malloced by update_url
                        if(!(up_url = update_url(curl, YD_UPDATELINK, update_basename, UPDATE_BASENAME_SIZE - 1, curl_error))) { 
                            fprintf(stderr, "Error: %s\n", curl_error);
                            fprintf(stderr, "Update not downloaded successfully.\n");
                            break;
                        }
                        
                        // just cat the base to the path (being careful not to overlap)
                        strncat(update_path, update_basename, PATH_MAX - strlen(update_path) - 1);
                        
                        if(!(fp = fopen(update_path, "wb"))) {
                            fprintf(stderr, "Error Opening file for writing.\n");
                            fprintf(stderr, "Update will not be downloaded.\n");
                        } else {
                            fprintf(stderr, "Downloading update...\n");
                            int perform_update_res = perform_update(curl, up_url, fp, curl_error);
                            if(perform_update_res == UPDATE_OK) {
                                fprintf(stderr, "\n\nUpdate successfully downloaded!\n");
                                fclose(fp);
                            } else {
                                fprintf(stderr, "\n\nError: %s\n", curl_error);
                                fprintf(stderr, "Update not downloaded successfully.\n");
                            }
                            free(up_url);
                        }
                        
                        done = true;
                        break;
                    
                    case 'N':
                        fprintf(stderr, "Not downloading update...\n");
                        done = true;
                        break;
                    
                    default:
                        done = false;
                        if(++tries > 3) // number of tries for a stupid user
                            done = true;
                        else {
                            fprintf(stderr, "That is not a valid option. Enter only [Y/n]: ");
                            tries++;
                        }
                        break;
                }
            } while(!done);
            
        } else if(new_update_res == UPDATE_ERR) {
            fprintf(stderr, "%s\n", curl_error);
        } else if(new_update_res == UPDATE_NO) {
            fprintf(stderr, "No update found.\n");
        }
        fprintf(stderr, "\n");
    }
    
    // ok, that was all the update process
    // all those stupid vars have finally been destroyed
    // next, we start getting links one by one...
    fprintf(stderr, "Ready for downloading. Waiting for input...\n");
    
    char input_buffer[URL_PATH_SIZE]; // buffer for each line of url
    char line_buffer[URL_PATH_SIZE];
    int nread;
    FILE *fp = NULL;
    
    // even though we already checked it, the file might have changed
    // so check it again!
    if(options.llist) {
        if(!(fp = fopen(options.llist, "r"))) {
            fprintf(stderr, "Error opening link list for reading.\n");
            return 0;
        }
    }
    
    // before reading, we might want to flush stdin
    fflush(stdin);
    int i, j = 0;
    do {
        //int i, j = 0; this causes a bug... j can be re-initialized ONLY when the string is capped.
        
        if(options.llist)
            nread = fread(input_buffer, sizeof(char), URL_PATH_SIZE, fp);
        else
            nread = fread(input_buffer, sizeof(char), URL_PATH_SIZE, stdin);
        
        for(i = 0; i < nread; i++) {
            for(; input_buffer[i] != '\n' && i < nread; i++, j++)
                line_buffer[j] = input_buffer[i];
            
            // if we haven't finished reading the line, but the buffer filled up...
            if(i == nread && nread == URL_PATH_SIZE) continue;
            
            // we cap the line, and reinit j
            line_buffer[j] = '\0';
            j = 0;
            
            // until here, we have successfully gotten all the information
            // into line buffer, now entering actual download phase
            {
                FILE *out_file = NULL;
                char video_link[URL_PATH_SIZE];
                char title[URL_PATH_SIZE];
                
                // added in 0.2.0a, found a bug in which the download_path would only be catted
                // oh and make errors continue!
                char out_file_path[PATH_MAX];
                memset(out_file_path, '\0', PATH_MAX);
                strncpy(out_file_path, download_path, PATH_MAX - 1);
                
                fprintf(stderr, "Looking for title...\n");
                if(!(video_title(curl, TITLE_LOOKUP_URL, line_buffer, title, curl_error))) {
                    fprintf(stderr, "\n\nError: %s.\n", curl_error);
                    fprintf(stderr, "Skipping this video..\n\n");
                    continue;
                }
                
                fprintf(stderr, "Title is \"%s\".\n", title);
                fprintf(stderr, "Looking for a direct link to the video...\n");
                
                if(!(generate_link(curl, LINK_LOOKUP_URL, line_buffer, video_link, curl_error))) {
                    fprintf(stderr, "\n\nError: %s.\n", curl_error);
                    fprintf(stderr, "Skipping this video...\n\n");
                    continue;
                }
                
                strncat(out_file_path, title, MAX_PATH - strlen(out_file_path) - 1);
                if(!(out_file = fopen(out_file_path, "wb"))) {
                    fprintf(stderr, "Error opening video file for writing!\n");
                    fprintf(stderr, "Skipping this video...\n\n");
                    continue;
                }
                
                fprintf(stderr, "Downloading...\n");
                if(!(download_vid(curl, video_link, out_file, curl_error)))
                    fprintf(stderr, "\n\nError: %s.\n", curl_error);
                else
                    fprintf(stderr, "\nVideo Sucessfully Downloaded!!!\n\n");
                
                fclose(out_file);
            }
        }
    } while(nread == URL_PATH_SIZE);
    
    return 0;
}
Beispiel #23
0
void state_device(struct snapraid_state* state, int operation, tommy_list* filterlist_disk)
{
	tommy_node* i;
	unsigned j;
	tommy_list high;
	tommy_list low;
	int ret;

	switch (operation) {
	case DEVICE_UP : msg_progress("Spinup...\n"); break;
	case DEVICE_DOWN : msg_progress("Spindown...\n"); break;
	}

	tommy_list_init(&high);
	tommy_list_init(&low);

	/* for all disks */
	for (i = state->disklist; i != 0; i = i->next) {
		struct snapraid_disk* disk = i->data;
		devinfo_t* entry;

		if (filterlist_disk != 0 && filter_path(filterlist_disk, 0, disk->name, 0) != 0)
			continue;

		entry = calloc_nofail(1, sizeof(devinfo_t));

		entry->device = disk->device;
		pathcpy(entry->name, sizeof(entry->name), disk->name);
		pathcpy(entry->mount, sizeof(entry->mount), disk->dir);
		pathcpy(entry->smartctl, sizeof(entry->smartctl), disk->smartctl);

		tommy_list_insert_tail(&high, &entry->node, entry);
	}

	/* for all parities */
	for (j = 0; j < state->level; ++j) {
		devinfo_t* entry;

		if (filterlist_disk != 0 && filter_path(filterlist_disk, 0, lev_config_name(j), 0) != 0)
			continue;

		entry = calloc_nofail(1, sizeof(devinfo_t));

		entry->device = state->parity[j].device;
		pathcpy(entry->name, sizeof(entry->name), lev_config_name(j));
		pathcpy(entry->mount, sizeof(entry->mount), state->parity[j].path);
		pathcpy(entry->smartctl, sizeof(entry->smartctl), state->parity[j].smartctl);
		pathcut(entry->mount); /* remove the parity file */

		tommy_list_insert_tail(&high, &entry->node, entry);
	}

	if (state->opt.fake_device) {
		ret = devtest(&low, operation);
	} else {
		int others = operation == DEVICE_SMART;

		ret = devquery(&high, &low, operation, others);
	}

	/* if the list is empty, it's not supported in this platform */
	if (ret == 0 && tommy_list_empty(&low))
		ret = -1;

	if (ret != 0) {
		const char* ope = 0;
		switch (operation) {
		case DEVICE_UP : ope = "Spinup"; break;
		case DEVICE_DOWN : ope = "Spindown"; break;
		case DEVICE_LIST : ope = "Device listing"; break;
		case DEVICE_SMART : ope = "Smart"; break;
		}
		log_fatal("%s is unsupported in this platform.\n", ope);
	} else {
		if (operation == DEVICE_LIST) {
			for (i = tommy_list_head(&low); i != 0; i = i->next) {
				devinfo_t* devinfo = i->data;
				devinfo_t* parent = devinfo->parent;
#ifdef _WIN32
				printf("%" PRIu64 "\t%s\t%08" PRIx64 "\t%s\t%s\n", devinfo->device, devinfo->wfile, parent->device, parent->wfile, parent->name);
#else
				printf("%u:%u\t%s\t%u:%u\t%s\t%s\n", major(devinfo->device), minor(devinfo->device), devinfo->file, major(parent->device), minor(parent->device), parent->file, parent->name);
#endif
			}
		}

		if (operation == DEVICE_SMART)
			state_smart(state->level + tommy_list_count(&state->disklist), &low);
	}

	tommy_list_foreach(&high, free);
	tommy_list_foreach(&low, free);
}
Beispiel #24
0
/**
 * Fill with fake data the device list.
 */
static int devtest(tommy_list* low, int operation)
{
	unsigned c;

	if (operation != DEVICE_SMART)
		return -1;

	/* add some fake data */
	for (c = 0; c < 16; ++c) {
		devinfo_t* entry;
		int j;

		entry = calloc_nofail(1, sizeof(devinfo_t));

		entry->device = c;

		tommy_list_insert_tail(low, &entry->node, entry);

		for (j = 0; j < 256; ++j) {
			switch (c) {
			case 0 : entry->smart[j] = 0; break;
			case 1 : entry->smart[j] = SMART_UNASSIGNED; break;
			default:
				if (j == 193)
					entry->smart[j] = c - 2;
				else
					entry->smart[j] = 0;
				break;
			}
		}

		if (c == 0) {
			entry->smart_serial[0] = 0;
			entry->file[0] = 0;
			entry->name[0] = 0;
			entry->smart[SMART_SIZE] = SMART_UNASSIGNED;
			entry->smart[SMART_ROTATION_RATE] = 0;
		} else {
			snprintf(entry->smart_serial, sizeof(entry->smart_serial), "%u", c);
			pathcpy(entry->file, sizeof(entry->name), "file");
			pathcpy(entry->name, sizeof(entry->name), "name");
			entry->smart[SMART_SIZE] = c * TERA;
			entry->smart[SMART_ROTATION_RATE] = 7200;
		}

		entry->smart[SMART_ERROR] = 0;
		entry->smart[SMART_FLAGS] = SMART_UNASSIGNED;

		switch (c) {
		case 3 : entry->smart[SMART_ERROR] = 1; break;
		case 4 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_UNSUPPORTED; break;
		case 5 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_COMMAND; break;
		case 6 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_OPEN; break;
		case 7 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_FAIL; break;
		case 8 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL; break;
		case 9 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL_LOGGED; break;
		case 10 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR; break;
		case 11 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR_LOGGED; break;
		}
	}

	return 0;
}
Beispiel #25
0
static void scrub_data_reader(struct snapraid_worker* worker, struct snapraid_task* task)
{
	struct snapraid_io* io = worker->io;
	struct snapraid_state* state = io->state;
	struct snapraid_handle* handle = worker->handle;
	struct snapraid_disk* disk = handle->disk;
	block_off_t blockcur = task->position;
	unsigned char* buffer = task->buffer;
	int ret;
	char esc_buffer[ESC_MAX];

	/* if the disk position is not used */
	if (!disk) {
		/* use an empty block */
		memset(buffer, 0, state->block_size);
		task->state = TASK_STATE_DONE;
		return;
	}

	/* get the block */
	task->block = fs_par2block_find(disk, blockcur);

	/* if the block is not used */
	if (!block_has_file(task->block)) {
		/* use an empty block */
		memset(buffer, 0, state->block_size);
		task->state = TASK_STATE_DONE;
		return;
	}

	/* get the file of this block */
	task->file = fs_par2file_get(disk, blockcur, &task->file_pos);

	/* if the file is different than the current one, close it */
	if (handle->file != 0 && handle->file != task->file) {
		/* keep a pointer at the file we are going to close for error reporting */
		struct snapraid_file* report = handle->file;
		ret = handle_close(handle);
		if (ret == -1) {
			/* LCOV_EXCL_START */
			/* This one is really an unexpected error, because we are only reading */
			/* and closing a descriptor should never fail */
			if (errno == EIO) {
				log_tag("error:%u:%s:%s: Close EIO error. %s\n", blockcur, disk->name, esc(report->sub, esc_buffer), strerror(errno));
				log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to scrub.\n");
				log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path);
				log_fatal("Stopping at block %u\n", blockcur);
				task->state = TASK_STATE_IOERROR;
				return;
			}

			log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc(report->sub, esc_buffer), strerror(errno));
			log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to scrub.\n");
			log_fatal("Ensure that file '%s' can be accessed.\n", handle->path);
			log_fatal("Stopping at block %u\n", blockcur);
			task->state = TASK_STATE_ERROR;
			return;
			/* LCOV_EXCL_STOP */
		}
	}

	ret = handle_open(handle, task->file, state->file_mode, log_error, 0);
	if (ret == -1) {
		if (errno == EIO) {
			/* LCOV_EXCL_START */
			log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc(task->file->sub, esc_buffer), strerror(errno));
			log_fatal("DANGER! Unexpected input/output open error in a data disk, it isn't possible to scrub.\n");
			log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path);
			log_fatal("Stopping at block %u\n", blockcur);
			task->state = TASK_STATE_IOERROR;
			return;
			/* LCOV_EXCL_STOP */
		}

		log_tag("error:%u:%s:%s: Open error. %s\n", blockcur, disk->name, esc(task->file->sub, esc_buffer), strerror(errno));
		task->state = TASK_STATE_ERROR_CONTINUE;
		return;
	}

	/* check if the file is changed */
	if (handle->st.st_size != task->file->size
		|| handle->st.st_mtime != task->file->mtime_sec
		|| STAT_NSEC(&handle->st) != task->file->mtime_nsec
		/* don't check the inode to support filesystem without persistent inodes */
	) {
		/* report that the block and the file are not synced */
		task->is_timestamp_different = 1;
		/* follow */
	}

	/* note that we intentionally don't abort if the file has different attributes */
	/* from the last sync, as we are expected to return errors if running */
	/* in an unsynced array. This is just like the check command. */

	task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0);
	if (task->read_size == -1) {
		if (errno == EIO) {
			log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
			log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos);
			task->state = TASK_STATE_IOERROR_CONTINUE;
			return;
		}

		log_tag("error:%u:%s:%s: Read error at position %u. %s\n", blockcur, disk->name, esc(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
		task->state = TASK_STATE_ERROR_CONTINUE;
		return;
	}

	/* store the path of the opened file */
	pathcpy(task->path, sizeof(task->path), handle->path);

	task->state = TASK_STATE_DONE;
}