/* * ndmpd_worker thread * * Parameters: * argp (input) - structure containing socket and handler function * * Returns: * 0 - successful connection. * -1 - error. */ void * ndmpd_worker(void *ptarg) { int sock; ndmp_connection_t *connection; ndmpd_worker_arg_t *argp = (ndmpd_worker_arg_t *)ptarg; if (!argp) return ((void *)-1); NS_INC(trun); sock = argp->nw_sock; if ((connection = ndmp_create_connection()) == NULL) { (void) close(sock); free(argp); exit(1); } /* initialize auditing session */ if (adt_start_session(&connection->conn_ah, NULL, 0) != 0) { free(argp); return ((void *)-1); } ((ndmp_connection_t *)connection)->conn_sock = sock; (*argp->nw_con_handler_func)(connection); (void) adt_end_session(connection->conn_ah); ndmp_destroy_connection(connection); NS_DEC(trun); free(argp); return (NULL); }
/* * 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); }
/*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); }