Ejemplo n.º 1
0
/*
 * correct_ents
 *
 * Correct the entries in the restore list by appending the appropriate
 * path to them
 */
static int
correct_ents(ndmpd_module_params_t *params, int n, char *bkpath)
{
	char *cp, *pathname;
	int i, len, rv;
	ndmp_name *ent;

	if ((pathname = ndmp_malloc(TLM_MAX_PATH_NAME)) == NULL) {
		MOD_LOG(params, "Error: insufficient memory.\n");
		return (-1);
	}

	rv = 0;
	/* Append the backup path to all the "ent[].name"s. */
	for (i = 0; i < n; i++) {
		ent = (ndmp_name *)MOD_GETNAME(params, i);

		NDMP_LOG(LOG_DEBUG,
		    "Old: ent[%d].name: \"%s\"", i, ent->name);
		NDMP_LOG(LOG_DEBUG,
		    "Old: ent[%d].dest: \"%s\"", i, ent->dest);

		/* remove trailing slash */
		len = strlen(ent->name);
		if (ent->name[len - 1] == '/')
			ent->name[len - 1] = '\0';

		if (!tlm_cat_path(pathname, bkpath, ent->name)) {
			MOD_LOG(params, "Error: path too long.\n");
			rv = -1;
			break;
		}

		/* Make a copy of the new string and save it in ent->name. */
		cp = strdup(pathname);
		if (cp == NULL) {
			MOD_LOG(params, "Error: insufficient memory.\n");
			rv = -1;
			break;
		}
		free(ent->name);
		ent->name = cp;

		NDMP_LOG(LOG_DEBUG,
		    "New: ent[%d].name: \"%s\"", i, ent->name);
	}

	free(pathname);
	return (rv);
}
Ejemplo n.º 2
0
/*
 * tlm_new_dir_info
 *
 * Create a new structure, set fh field to what is specified and the path
 * to the concatenation of directory and the component
 */
struct full_dir_info *
tlm_new_dir_info(struct  fs_fhandle *fhp, char *dir, char *nm)
{
	struct full_dir_info *fdip;

	if (!(fdip = ndmp_malloc(sizeof (struct full_dir_info))))
		return (NULL);

	(void) memcpy(&fdip->fd_dir_fh, fhp, sizeof (fs_fhandle_t));
	if (!tlm_cat_path(fdip->fd_dir_name, dir, nm)) {
		free(fdip);
		NDMP_LOG(LOG_DEBUG, "TAPE BACKUP Find> path too long [%s][%s]",
		    dir, nm);
		return (NULL);
	}
	return (fdip);
}
Ejemplo n.º 3
0
/*
 * see if we should exclude this file.
 */
boolean_t
tlm_is_excluded(char *dir, char *name, char **excl_files)
{
    int	i;
    char	full_name[TLM_MAX_PATH_NAME];

    if (!dir || !name || !excl_files)
        return (FALSE);

    if (!tlm_cat_path(full_name, dir, name)) {
        NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]",
                 dir, name);
        return (FALSE);
    }
    for (i = 0; excl_files[i] != 0; i++) {
        if (match(excl_files[i], full_name)) {
            return (TRUE);
        }
    }
    return (FALSE);
}
Ejemplo n.º 4
0
/*
 * tlm_output_file
 *
 * Put this file into the output buffers.
 */
longlong_t
tlm_output_file(char *dir, char *name, char *chkdir,
    tlm_acls_t *tlm_acls, tlm_commands_t *commands, tlm_cmd_t *local_commands,
    tlm_job_stats_t *job_stats, struct hardlink_q *hardlink_q)
{
	char	*fullname;		/* directory + name */
	char	*snapname;		/* snapshot name */
	char	*linkname;		/* where this file points */
	int	section = 0;		/* section of a huge file */
	int	fd;
	longlong_t real_size;		/* the origional file size */
	longlong_t file_size;		/* real size of this file */
	longlong_t seek_spot = 0;	/* location in the file */
					/* for Multi Volume record */
	u_longlong_t pos;
	char *fnamep;

	/* Indicate whether a file with the same inode has been backed up. */
	int hardlink_done = 0;

	/*
	 * If a file with the same inode has been backed up, hardlink_pos holds
	 * the tape offset of the data record.
	 */
	u_longlong_t hardlink_pos = 0;

	if (tlm_is_too_long(tlm_acls->acl_checkpointed, dir, name)) {
		syslog(LOG_ERR, "Path too long [%s][%s]", dir, name);
		return (-TLM_NO_SCRATCH_SPACE);
	}

	fullname = ndmp_malloc(TLM_MAX_PATH_NAME);
	linkname = ndmp_malloc(TLM_MAX_PATH_NAME);
	snapname = ndmp_malloc(TLM_MAX_PATH_NAME);
	if (fullname == NULL || linkname == NULL || snapname == NULL) {
		real_size = -TLM_NO_SCRATCH_SPACE;
		goto err_out;
	}
	if (!tlm_cat_path(fullname, dir, name) ||
	    !tlm_cat_path(snapname, chkdir, name)) {
		syslog(LOG_ERR, "Path too long.");
		real_size = -TLM_NO_SCRATCH_SPACE;
		goto err_out;
	}

	pos = tlm_get_data_offset(local_commands);

	if (S_ISPECIAL(tlm_acls->acl_attr.st_mode)) {
		if (S_ISLNK(tlm_acls->acl_attr.st_mode)) {
			file_size = tlm_readlink(fullname, snapname, linkname,
			    TLM_MAX_PATH_NAME-1);
			if (file_size < 0) {
				real_size = -ENOENT;
				goto err_out;
			}
		}

		/*
		 * Since soft links can not be read(2), we should only
		 * backup the file header.
		 */
		(void) output_file_header(fullname,
		    linkname,
		    tlm_acls,
		    section,
		    local_commands);

		(void) tlm_log_fhnode(job_stats, dir, name,
		    &tlm_acls->acl_attr, pos);
		(void) tlm_log_fhpath_name(job_stats, fullname,
		    &tlm_acls->acl_attr, pos);

		free(fullname);
		free(linkname);
		free(snapname);
		return (0);
	}

	fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname;

	/*
	 * For hardlink, only read the data if no other link
	 * belonging to the same inode has been backed up.
	 */
	if (tlm_acls->acl_attr.st_nlink > 1) {
		hardlink_done = !hardlink_q_get(hardlink_q,
		    tlm_acls->acl_attr.st_ino, &hardlink_pos, NULL);
	}

	if (!hardlink_done) {
		/*
		 * Open the file for reading.
		 */
		fd = open(fnamep, O_RDONLY);
		if (fd == -1) {
			syslog(LOG_ERR,
			    "BACKUP> Can't open file [%s][%s] err(%d)",
			    fullname, fnamep, errno);
			real_size = -TLM_NO_SOURCE_FILE;
			goto err_out;
		}
	} else {
		syslog(LOG_DEBUG, "found hardlink, inode = %llu, pos = %llu ",
		    tlm_acls->acl_attr.st_ino, hardlink_pos);

		fd = -1;
	}

	linkname[0] = 0;

	real_size = tlm_acls->acl_attr.st_size;
	(void) output_acl_header(&tlm_acls->acl_info,
	    local_commands);

	/*
	 * section = 0: file is small enough for TAR
	 * section > 0: file goes out in TLM_MAX_TAR_IMAGE sized chunks
	 * 		and the file name gets munged
	 */
	file_size = real_size;
	if (file_size > TLM_MAX_TAR_IMAGE) {
		if (output_humongus_header(fullname, file_size,
		    local_commands) < 0) {
			(void) close(fd);
			real_size = -TLM_NO_SCRATCH_SPACE;
			goto err_out;
		}
		section = 1;
	} else {
		section = 0;
	}

	/*
	 * For hardlink, if other link belonging to the same inode
	 * has been backed up, only backup an empty record.
	 */
	if (hardlink_done)
		file_size = 0;

	/*
	 * work
	 */
	if (file_size == 0) {
		(void) output_file_header(fullname,
		    linkname,
		    tlm_acls,
		    section,
		    local_commands);
		/*
		 * this can fall right through since zero size files
		 * will be skipped by the WHILE loop anyway
		 */
	}

	while (file_size > 0) {
		int section_size = llmin(file_size,
		    (longlong_t)TLM_MAX_TAR_IMAGE);

		tlm_acls->acl_attr.st_size = (longlong_t)section_size;
		(void) output_file_header(fullname,
		    linkname,
		    tlm_acls,
		    section,
		    local_commands);
		while (section_size > 0) {
			char	*buf;
			long	actual_size;
			int	read_size;

			/*
			 * check for Abort commands
			 */
			if (commands->tcs_reader != TLM_BACKUP_RUN) {
				local_commands->tc_writer = TLM_ABORT;
				goto tear_down;
			}

			local_commands->tc_buffers->tbs_buffer[
			    local_commands->tc_buffers->tbs_buffer_in].
			    tb_file_size = section_size;
			local_commands->tc_buffers->tbs_buffer[
			    local_commands->tc_buffers->tbs_buffer_in].
			    tb_seek_spot = seek_spot;

			buf = get_write_buffer(section_size,
			    &actual_size, FALSE, local_commands);
			if (!buf)
				goto tear_down;

			/*
			 * check for Abort commands
			 */
			if (commands->tcs_reader != TLM_BACKUP_RUN) {
				local_commands->tc_writer = TLM_ABORT;
				goto tear_down;
			}

			read_size = min(section_size, actual_size);
			actual_size = read(fd, buf, read_size);
			NS_ADD(rdisk, actual_size);
			NS_INC(rfile);

			if (actual_size == 0)
				break;

			if (actual_size == -1) {
				syslog(LOG_ERR,
				    "problem(%d) reading file [%s][%s]",
				    errno, fullname, snapname);
				goto tear_down;
			}
			seek_spot += actual_size;
			file_size -= actual_size;
			section_size -= actual_size;
		}
		section++;
	}

	/*
	 * If data belonging to this hardlink has been backed up, add the link
	 * to hardlink queue.
	 */
	if (tlm_acls->acl_attr.st_nlink > 1 && !hardlink_done) {
		(void) hardlink_q_add(hardlink_q, tlm_acls->acl_attr.st_ino,
		    pos, NULL, 0);
		syslog(LOG_DEBUG,
		    "backed up hardlink file %s, inode = %llu, pos = %llu ",
		    fullname, tlm_acls->acl_attr.st_ino, pos);
	}

	/*
	 * For hardlink, if other link belonging to the same inode has been
	 * backed up, no add_node entry should be sent for this link.
	 */
	if (hardlink_done) {
		syslog(LOG_DEBUG,
		    "backed up hardlink link %s, inode = %llu, pos = %llu ",
		    fullname, tlm_acls->acl_attr.st_ino, hardlink_pos);
	} else {
		(void) tlm_log_fhnode(job_stats, dir, name,
		    &tlm_acls->acl_attr, pos);
	}

	(void) tlm_log_fhpath_name(job_stats, fullname, &tlm_acls->acl_attr,
	    pos);

tear_down:
	local_commands->tc_buffers->tbs_buffer[
	    local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0;

	(void) close(fd);

err_out:
	free(fullname);
	free(linkname);
	free(snapname);
	return (real_size);
}
Ejemplo n.º 5
0
/*ARGSUSED*/
longlong_t
tlm_output_xattr(char  *dir, char *name, char *chkdir,
    tlm_acls_t *tlm_acls, tlm_commands_t *commands,
    tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats)
{
	char	*fullname;		/* directory + name */
	char	*snapname;		/* snapshot name */
	int	section;		/* section of a huge file */
	int	fd;
	int	afd = 0;
	longlong_t seek_spot = 0;	/* location in the file */
					/* for Multi Volume record */
	DIR *dp;
	struct dirent *dtp;
	char *attrname;
	char *fnamep;
	int rv = 0;

	if (S_ISPECIAL(tlm_acls->acl_attr.st_mode)) {
		return (TLM_NO_SOURCE_FILE);
	}

	fullname = ndmp_malloc(TLM_MAX_PATH_NAME);
	if (fullname == NULL) {
		free(fullname);
		return (-TLM_NO_SCRATCH_SPACE);
	}

	if (!tlm_cat_path(fullname, dir, name)) {
		syslog(LOG_ERR, "Path too long.");
		free(fullname);
		return (-TLM_NO_SCRATCH_SPACE);
	}

	if (pathconf(fullname, _PC_XATTR_EXISTS) != 1 &&
	    sysattr_support(fullname, _PC_SATTR_EXISTS) != 1) {
		free(fullname);
		return (0);
	}

	attrname = ndmp_malloc(TLM_MAX_PATH_NAME);
	snapname = ndmp_malloc(TLM_MAX_PATH_NAME);
	if (attrname == NULL || snapname == NULL) {
		rv = -TLM_NO_SCRATCH_SPACE;
		goto err_out;
	}

	if (!tlm_cat_path(snapname, chkdir, name)) {
		syslog(LOG_ERR, "Path too long.");
		rv = -TLM_NO_SCRATCH_SPACE;
		goto err_out;
	}

	fnamep = (tlm_acls->acl_checkpointed) ? snapname : fullname;

	/*
	 * Open the file for reading.
	 */
	fd = attropen(fnamep, ".", O_RDONLY);
	if (fd == -1) {
		syslog(LOG_ERR, "BACKUP> Can't open file [%s][%s]",
		    fullname, fnamep);
		rv = TLM_NO_SOURCE_FILE;
		goto err_out;
	}

	section = 0;

	dp = (DIR *)fdopendir(fd);
	if (dp == NULL) {
		syslog(LOG_ERR, "BACKUP> Can't open file [%s]", fullname);
		(void) close(fd);
		rv = TLM_NO_SOURCE_FILE;
		goto err_out;
	}

	while ((dtp = readdir(dp)) != NULL) {
		int section_size;

		if (*dtp->d_name == '.')
			continue;

		if (sysattr_rdonly(dtp->d_name))
			continue;

		afd = attropen(fnamep, dtp->d_name, O_RDONLY);
		if (afd == -1) {
			syslog(LOG_ERR,
			    "problem(%d) opening xattr file [%s][%s]", errno,
			    fullname, fnamep);
			goto tear_down;
		}

		(void) output_xattr_header(fullname, dtp->d_name, afd,
		    tlm_acls, section, local_commands);
		(void) snprintf(attrname, TLM_MAX_PATH_NAME, "/dev/null/%s",
		    dtp->d_name);
		(void) output_file_header(attrname, "", tlm_acls, 0,
		    local_commands);

		section_size = (long)llmin(tlm_acls->acl_attr.st_size,
		    (longlong_t)TLM_MAX_TAR_IMAGE);

		/* We only can read upto one section extended attribute */
		while (section_size > 0) {
			char	*buf;
			long	actual_size;
			int	read_size;
			int sysattr_read = 0;
			char *rec;
			int size;

			/*
			 * check for Abort commands
			 */
			if (commands->tcs_reader != TLM_BACKUP_RUN) {
				local_commands->tc_writer = TLM_ABORT;
				goto tear_down;
			}

			local_commands->tc_buffers->tbs_buffer[
			    local_commands->tc_buffers->tbs_buffer_in].
			    tb_file_size = section_size;
			local_commands->tc_buffers->tbs_buffer[
			    local_commands->tc_buffers->tbs_buffer_in].
			    tb_seek_spot = seek_spot;

			buf = get_write_buffer(section_size,
			    &actual_size, FALSE, local_commands);
			if (!buf)
				goto tear_down;

			if ((actual_size < section_size) &&
			    sysattr_rw(dtp->d_name)) {
				rec = buf;
				buf = ndmp_malloc(section_size);
				if (!buf)
					goto tear_down;
				size = actual_size;
				actual_size = section_size;
				sysattr_read = 1;
			}

			/*
			 * check for Abort commands
			 */
			if (commands->tcs_reader != TLM_BACKUP_RUN) {
				local_commands->tc_writer = TLM_ABORT;
				goto tear_down;
			}

			read_size = min(section_size, actual_size);
			if ((actual_size = read(afd, buf, read_size)) < 0)
				break;

			if (sysattr_read) {
				if (get_write_one_buf(buf, rec, read_size,
				    size, local_commands) == 0) {
					free(buf);
					goto tear_down;
				}
				free(buf);
			}


			NS_ADD(rdisk, actual_size);
			NS_INC(rfile);

			if (actual_size == -1) {
				syslog(LOG_ERR,
				    "problem(%d) reading file [%s][%s]",
				    errno, fullname, snapname);
				goto tear_down;
			}
			seek_spot += actual_size;
			section_size -= actual_size;
		}
		(void) close(afd);
		afd = -1;
	}

tear_down:
	local_commands->tc_buffers->tbs_buffer[
	    local_commands->tc_buffers->tbs_buffer_in].tb_seek_spot = 0;

	if (afd > 0)
		(void) close(afd);

	/* closedir closes fd too */
	(void) closedir(dp);

err_out:
	free(fullname);
	free(attrname);
	free(snapname);
	return (rv);
}