void watchdog_close(var_t *table) { char *id; if (pthread_mutex_lock(&watchdog_mutex)) { log_sys_error("watchdog_remove: pthread_mutex_lock"); goto exit; } id = vtable_get(table, "id"); if (id == NULL) { log_error("watchdog_remove: vtable_get returned no id"); goto exit; } sht_remove(&watchdog_table, id); exit: if (pthread_mutex_unlock(&watchdog_mutex)) { log_sys_error("watchdog_remove: pthread_mutex_unlock"); } return; }
static int _dev_get_size_dev(const struct device *dev, uint64_t *size) { int fd; const char *name = dev_name(dev); if ((fd = open(name, O_RDONLY)) < 0) { log_sys_error("open", name); return 0; } if (ioctl(fd, BLKGETSIZE64, size) < 0) { log_sys_error("ioctl BLKGETSIZE64", name); if (close(fd)) log_sys_error("close", name); return 0; } *size >>= BLKSIZE_SHIFT; /* Convert to sectors */ if (close(fd)) log_sys_error("close", name); log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size); return 1; }
int server_data_cmd(int sock, char *cmd, char **buffer) { char recv[RECV_BUFFER]; int n, size, completed; log_debug("server_data_cmd: command '%s'", cmd); if (server_reply(sock, cmd) == -1) { log_error("server_data_cmd: server_reply failed"); return -1; } n = read(sock, recv, sizeof recv); if (n == -1) { log_sys_error("server_data_cmd: read"); return -1; } size = atoi(recv); if (size < 0 || size > MAX_BUFFER) { log_error("server_data_cmd: bad buffer size"); return -1; } *buffer = (char *) malloc(size + 1); if (*buffer == NULL) { log_sys_error("server_data_cmd: malloc"); return -1; } if (server_ok(sock)) { log_error("server_data_cmd: server_ok failed"); return -1; } for (completed = 0; size > completed; completed += n) { n = read(sock, *buffer + completed, size - completed); if (n == -1) { log_sys_error("server_data_cmd: read"); return -1; } } (*buffer)[completed] = 0; if (server_check(sock)) { log_error("server_data_cmd: server_check failed"); return -1; } return 0; }
/* init_ring */ int init_ring( const int socket_fd, const int type, const int frames_per_block, const int no_blocks, void **ring ) { int ring_access_flags = PROT_READ | PROT_WRITE; tpacket_req_t *p = init_tpacket_req(frames_per_block, no_blocks); int ring_len = ( p->tp_block_size ) * ( p->tp_block_nr ); // 1) export kernel mmap()ed memory if ( setsockopt(socket_fd, SOL_PACKET, type, p, LEN__TPACKET_REQ) < 0 ) { log_sys_error("Setting socket options for this ring"); return(EX_ERR); } #ifdef TPACKET_V2 int val = TPACKET_V1; if ( setsockopt(socket_fd, SOL_PACKET, PACKET_HDRLEN, &val, sizeof(int)) < 0 ) { handle_sys_error("Setting TPACKET_V1 for this ring..."); } #endif // 2) open ring if ( ( (*ring) = mmap( NULL, ring_len, ring_access_flags, MAP_SHARED, socket_fd, 0) ) == NULL ) { log_sys_error("mmap()ing error"); return(EX_ERR); } return(ring_len); }
static int _create_control(const char *control, uint32_t major, uint32_t minor) { int ret; mode_t old_umask; if (!major) return 0; old_umask = umask(DM_DEV_DIR_UMASK); ret = dm_create_dir(dm_dir()); umask(old_umask); if (!ret) return 0; log_verbose("Creating device %s (%u, %u)", control, major, minor); old_umask = umask(0); if (mknod(control, S_IFCHR | DM_CONTROL_DEVICE_MODE, MKDEV(major, minor)) < 0) { umask(old_umask); log_sys_error("mknod", control); return 0; } umask(old_umask); if (chown(control, DM_DEVICE_UID, DM_DEVICE_GID) == -1) { log_sys_error("chown", control); return 0; } return 1; }
static int _process_mapper_dir(struct dm_task *dmt) { struct dirent *dirent; DIR *d; const char *dir; int r = 1; dir = dm_dir(); if (!(d = opendir(dir))) { log_sys_error("opendir", dir); return 0; } while ((dirent = readdir(d))) { if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..") || !strcmp(dirent->d_name, "control")) continue; dm_task_set_name(dmt, dirent->d_name); dm_task_run(dmt); } if (closedir(d)) log_sys_error("closedir", dir); return r; }
static int _reopen_fd_to_null(int fd) { int null_fd; int r = 0; if ((null_fd = open("/dev/null", O_RDWR)) == -1) { log_sys_error("open", "/dev/null"); return 0; } if (close(fd)) { log_sys_error("close", ""); goto out; } if (dup2(null_fd, fd) == -1) { log_sys_error("dup2", ""); goto out; } r = 1; out: if (close(null_fd)) { log_sys_error("dup2", ""); return 0; } return r; }
/* * Returns 1 if exists; 0 if it doesn't; -1 if it's wrong */ static int _control_exists(const char *control, uint32_t major, uint32_t minor) { struct stat buf; if (stat(control, &buf) < 0) { if (errno != ENOENT) log_sys_error("stat", control); return 0; } if (!S_ISCHR(buf.st_mode)) { log_verbose("%s: Wrong inode type", control); if (!unlink(control)) return 0; log_sys_error("unlink", control); return -1; } if (major && buf.st_rdev != MKDEV(major, minor)) { log_verbose("%s: Wrong device number: (%u, %u) instead of " "(%u, %u)", control, MAJOR(buf.st_mode), MINOR(buf.st_mode), major, minor); if (!unlink(control)) return 0; log_sys_error("unlink", control); return -1; } return 1; }
static acl_action_type_t pipe_exec(char *dest, char *message, int size) { FILE *fp; int status; fp = popen(dest, "w"); if (fp == NULL) { log_sys_error("pipe_exec: popen"); return ACL_ERROR; } if (fwrite(message, size, 1, fp) != 1) { log_sys_error("pipe_exec: fwrite"); pclose(fp); return ACL_ERROR; } status = pclose(fp); if (status) { log_error("pipe_exec: command failed"); return ACL_ERROR; } return ACL_NONE; }
static int _create_dir_recursive(const char *dir) { char *orig, *s; int rc, r = 0; log_verbose("Creating directory \"%s\"", dir); /* Create parent directories */ orig = s = dm_strdup(dir); while ((s = strchr(s, '/')) != NULL) { *s = '\0'; if (*orig) { rc = mkdir(orig, 0777); if (rc < 0 && errno != EEXIST) { if (errno != EROFS) log_sys_error("mkdir", orig); goto out; } } *s++ = '/'; } /* Create final directory */ rc = mkdir(dir, 0777); if (rc < 0 && errno != EEXIST) { if (errno != EROFS) log_sys_error("mkdir", orig); goto out; } r = 1; out: dm_free(orig); return r; }
FILE *pipe_open(struct cmd_context *cmd, const char *const argv[], int sync_needed, struct pipe_data *pdata) { int pipefd[2]; char buf[PATH_MAX * 2]; if (sync_needed) if (!sync_local_dev_names(cmd)) /* Flush ops and reset dm cookie */ return_0; if (pipe(pipefd)) { log_sys_error("pipe", ""); return 0; } log_verbose("Piping:%s", _verbose_args(argv, buf, sizeof(buf))); if ((pdata->pid = fork()) == -1) { log_sys_error("pipe", ""); return 0; } if (pdata->pid == 0) { /* Child -> writer, convert pipe[0] to STDOUT */ if (!_reopen_fd_to_null(STDIN_FILENO)) stack; else if (close(pipefd[0 /*read*/])) log_sys_error("close", "pipe[0]"); else if (close(STDOUT_FILENO)) log_sys_error("close", "STDOUT"); else if (dup2(pipefd[1 /*write*/], STDOUT_FILENO) == -1) log_sys_error("dup2", "STDOUT"); else if (close(pipefd[1])) log_sys_error("close", "pipe[1]"); else if (argv[0]) { execvp(argv[0], (char **) argv); log_sys_error("execvp", argv[0]); } _exit(errno); } /* Parent -> reader */ if (close(pipefd[1 /*write*/])) { log_sys_error("close", "STDOUT"); return NULL; } if (!(pdata->fp = fdopen(pipefd[0 /*read*/], "r"))) { log_sys_error("fdopen", "STDIN"); if (close(pipefd[0])) log_sys_error("close", "STDIN"); return NULL; /* FIXME: kill */ } return pdata->fp; }
void watchdog(var_t *table, char *stage) { watchdog_t *wd; char *id; if (pthread_mutex_lock(&watchdog_mutex)) { log_sys_error("watchdog: pthread_mutex_lock"); return; } watchdog_init(); // In init id is not set. No problem. id = vtable_get(table, "id"); if (id == NULL) { goto exit; } // Record does not exist wd = sht_lookup(&watchdog_table, id); if (wd == NULL) { wd = watchdog_create(id, stage); if (wd == NULL) { log_error("watchdog: watchdog_create failed"); goto exit; } if (sht_insert(&watchdog_table, id, wd)) { log_error("watchdog: sht_insert failed"); goto exit; } } else { wd->wd_stage = stage; wd->wd_instage = time(NULL); } exit: if (pthread_mutex_unlock(&watchdog_mutex)) { log_sys_error("watchdog: pthread_mutex_unlock"); } return; }
/* * Support envvar LVM_LOG_FILE_EPOCH and allow to attach * extra keyword (consist of upto 32 alpha chars) to * opened log file. After this 'epoch' word pid and starttime * (in kernel units, read from /proc/self/stat) * is automatically attached. * If command/daemon forks multiple times, it could create multiple * log files ensuring, there are no overwrites. */ void init_log_file(const char *log_file, int append) { static const char statfile[] = "/proc/self/stat"; const char *env; int pid; unsigned long long starttime; FILE *st; int i = 0; _log_file_path[0] = '\0'; if ((env = getenv("LVM_LOG_FILE_EPOCH"))) { while (isalpha(env[i]) && i < 32) /* Up to 32 alphas */ i++; if (env[i]) { if (i) log_warn("WARNING: Ignoring invalid LVM_LOG_FILE_EPOCH envvar \"%s\".", env); goto no_epoch; } if (!(st = fopen(statfile, "r"))) log_sys_error("fopen", statfile); else if (fscanf(st, "%d %*s %*c %*d %*d %*d %*d " /* tty_nr */ "%*d %*u %*u %*u %*u " /* mjflt */ "%*u %*u %*u %*d %*d " /* cstim */ "%*d %*d %*d %*d " /* itrealvalue */ "%llu", &pid, &starttime) != 2) { log_warn("WARNING: Cannot parse content of %s.", statfile); } else { if (dm_snprintf(_log_file_path, sizeof(_log_file_path), "%s_%s_%d_%lld", log_file, env, pid, starttime) < 0) { log_warn("WARNING: Debug log file path is too long for epoch."); _log_file_path[0] = '\0'; } else { log_file = _log_file_path; append = 1; /* force */ } } if (st && fclose(st)) log_sys_debug("fclose", statfile); } no_epoch: if (!(_log_file = fopen(log_file, append ? "a" : "w"))) { log_sys_error("fopen", log_file); return; } _log_to_file = 1; }
int pipe_close(struct pipe_data *pdata) { int status; if (fclose(pdata->fp)) log_sys_error("fclose", "STDIN"); if (waitpid(pdata->pid, &status, 0) != pdata->pid) { log_sys_error("waitpid", ""); return 0; } return (status == 0) ? 1 : 0; }
static int _dev_get_size_dev(const struct device *dev, uint64_t *size) { int fd; const char *name = dev_name(dev); #ifdef __NetBSD__ struct disklabel lab; struct dkwedge_info dkw; struct stat stat; #endif if ((fd = open(name, O_RDONLY)) < 0) { #ifndef __NetBSD__ log_sys_error("open", name); #endif return 0; } #ifdef __NetBSD__ /* Get info about partition/wedge */ if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == -1) { if (ioctl(fd, DIOCGDINFO, &lab) == -1) { log_debug("Please implement DIOCGWEDGEINFO or " "DIOCGDINFO for disk device %s", name); close(fd); return 0; } else { if (fstat(fd, &stat) < 0) log_debug("fstat on device %s failure", name); *size = lab.d_partitions[DISKPART(stat.st_rdev)].p_size; } } else *size = dkw.dkw_size; #else if (ioctl(fd, BLKGETSIZE64, size) < 0) { log_sys_error("ioctl BLKGETSIZE64", name); if (close(fd)) log_sys_error("close", name); return 0; } *size >>= BLKSIZE_SHIFT; /* Convert to sectors */ #endif if (close(fd)) log_sys_error("close", name); log_very_verbose("%s: size is %" PRIu64 " sectors", name, *size); return 1; }
static int _create_dir_recursive(const char *dir) { char *orig, *s; int rc, r = 0; log_verbose("Creating directory \"%s\"", dir); /* Create parent directories */ orig = s = strdup(dir); if (!s) { log_error("Failed to duplicate directory name."); return 0; } while ((s = strchr(s, '/')) != NULL) { *s = '\0'; if (*orig) { rc = mkdir(orig, 0777); if (rc < 0) { if (errno == EEXIST) { if (!_is_dir(orig)) goto_out; } else { if (errno != EROFS) log_sys_error("mkdir", orig); goto out; } } } *s++ = '/'; } /* Create final directory */ rc = mkdir(dir, 0777); if (rc < 0) { if (errno == EEXIST) { if (!_is_dir(dir)) goto_out; } else { if (errno != EROFS) log_sys_error("mkdir", orig); goto out; } } r = 1; out: free(orig); return r; }
static int server_request(int sock) { char cmd_buffer[RECV_BUFFER]; int len; int r; len = read(sock, cmd_buffer, sizeof cmd_buffer); if (len == -1) { log_sys_error("server_request: read"); return -1; } if (len == sizeof cmd_buffer) { log_sys_error("server_request: buffer exhausted"); return -1; } cmd_buffer[len] = 0; /* * Strip trailing newlines */ while (cmd_buffer[len - 1] == '\n') { cmd_buffer[--len] = 0; } /* * No command specified */ if (!len) { return 0; } log_error("server: %s", cmd_buffer); r = server_exec_cmd(sock, cmd_buffer); if (r == -1) { log_error("server_request: server_exec_cmd failed"); } return r; }
/* * Get the sector size from an _open_ device. */ static int _get_block_size(struct device *dev, unsigned int *size) { const char *name = dev_name(dev); #ifdef __NetBSD__ struct disklabel lab; prop_dictionary_t disk_dict, geom_dict; uint32_t secsize; #endif if ((dev->block_size == -1)) { #ifdef __NetBSD__ if (prop_dictionary_recv_ioctl(dev_fd(dev), DIOCGDISKINFO, &disk_dict)) { if (ioctl(dev_fd(dev), DIOCGDINFO, &lab) < 0) { dev->block_size = DEV_BSIZE; } else dev->block_size = lab.d_secsize; } else { geom_dict = prop_dictionary_get(disk_dict, "geometry"); prop_dictionary_get_uint32(geom_dict, "sector-size", &secsize); dev->block_size = secsize; } #else if (ioctl(dev_fd(dev), BLKBSZGET, &dev->block_size) < 0) { log_sys_error("ioctl BLKBSZGET", name); return 0; } #endif log_debug("%s: block size is %u bytes", name, dev->block_size); } *size = (unsigned int) dev->block_size; return 1; }
static int _create_control(const char *control, uint32_t major, uint32_t minor) { int ret; mode_t old_umask; if (!major) return 0; old_umask = umask(DM_DEV_DIR_UMASK); ret = dm_create_dir(dm_dir()); umask(old_umask); if (!ret) return 0; log_verbose("Creating device %s (%u, %u)", control, major, minor); if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR, MKDEV(major, minor)) < 0) { log_sys_error("mknod", control); return 0; } #ifdef HAVE_SELINUX if (!dm_set_selinux_context(control, S_IFCHR)) { stack; return 0; } #endif return 1; }
static void dbt_close(dbt_t *dbt) { if (!dbt->dbt_open) { return; } if ((dbt->dbt_driver->dd_flags & DBT_LOCK)) { if(pthread_mutex_destroy(&dbt->dbt_mutex)) { log_sys_error("dbt_close: ptrhead_mutex_destroy"); } } DBT_DB_CLOSE(dbt); if (dbt->dbt_scheme) { var_delete(dbt->dbt_scheme); } dbt->dbt_open = 0; return; }
/* Open control device if doesn't exist create it. */ static int _open_control(void) { char control[PATH_MAX]; uint32_t major = 0, minor = 0; if (_control_fd != -1) return 1; #ifdef RUMP_ACTION rump_init(); #endif snprintf(control, sizeof(control), "%s/control", dm_dir()); if (!_control_device_number(&major, &minor)) log_error("Is device-mapper driver missing from kernel?"); if (!_control_exists(control, major, minor) && !_create_control(control, major, minor)) goto error; if ((_control_fd = open(control, O_RDWR)) < 0) { log_sys_error("open", control); goto error; } return 1; error: log_error("Failure to communicate with kernel device-mapper driver."); return 0; }
/* get_mac_address */ int get_mac_address (const int socket_fd, const char *if_name, unsigned char *mac) { printf("ini6\n"); int len_if_name = -1; if ( if_name == NULL ) { return(EX_NULL_PARAM); } if ( mac == NULL ) { return(EX_NULL_PARAM); } if ( socket_fd < 0 ) { return(EX_WRONG_PARAM); } len_if_name = strlen(if_name); if ( len_if_name == 0 ) { return(EX_EMPTY_PARAM); } if ( len_if_name > IF_NAMESIZE ) { return(EX_WRONG_PARAM); } ifreq_t *ifr = new_ifreq(); strncpy(ifr->ifr_name, if_name, len_if_name); if ( ioctl(socket_fd, SIOCGIFHWADDR, ifr) < 0 ) { log_sys_error("Could not get interface index"); return(EX_SYS); } memcpy(mac, ifr->ifr_hwaddr.sa_data, ETH_ALEN); return(EX_OK); }
/* * Does the LVM1 driver know of this VG name? */ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname) { struct stat info; char path[PATH_MAX]; /* We'll allow operations on orphans */ if (!is_real_vg(vgname)) return 1; /* LVM1 is only present in 2.4 kernels. */ if (strncmp(cmd->kernel_vsn, "2.4.", 4)) return 1; if (dm_snprintf(path, sizeof(path), "%s/lvm/VGs/%s", cmd->proc_dir, vgname) < 0) { log_error("LVM1 proc VG pathname too long for %s", vgname); return 0; } if (stat(path, &info) == 0) { log_error("%s exists: Is the original LVM driver using " "this volume group?", path); return 0; } else if (errno != ENOENT && errno != ENOTDIR) { log_sys_error("stat", path); return 0; } return 1; }
static int _create_control(const char *control, uint32_t major, uint32_t minor) { int ret; mode_t old_umask; if (!major) return 0; old_umask = umask(0022); ret = dm_create_dir(dm_dir()); umask(old_umask); if (!ret) return 0; log_verbose("Creating device %s (%u, %u)", control, major, minor); if (mknod(control, S_IFCHR | S_IRUSR | S_IWUSR, MKDEV(major, minor)) < 0) { log_sys_error("mknod", control); return 0; } return 1; }
static int server_output(int sock, char *buffer, int size) { int n; if (server_reply(sock, "%d", size) == -1) { log_error("server_output: server_reply failed"); return -1; } if (server_check(sock)) { log_error("server_output: server_check failed"); return -1; } n = write(sock, buffer, size); if (n == -1) { log_sys_error("server_output: write"); return -1; } return n; }
/* send_message */ int send_message( const sockaddr_t* dest_addr, const int socket_fd, const void *buffer, const int len ) { int sent_bytes = 0; if ( ( sent_bytes = sendto(socket_fd, buffer, len , 0, dest_addr, LEN__SOCKADDR_IN) ) < 0 ) { log_sys_error("cb_broadcast_sendto (fd=%d): <sendto> ERROR.\n" , socket_fd); getchar(); return(EX_ERR); } if ( sent_bytes < len ) { log_app_msg("send_message: sent %d bytes, requested %d.\n" , sent_bytes, len); return(EX_ERR); } return(sent_bytes); }
static void _unlock_mem(struct cmd_context *cmd) { size_t unlock_mstats; log_very_verbose("Unlocking memory"); if (!_memlock_maps(cmd, LVM_MUNLOCK, &unlock_mstats)) stack; if (!_use_mlockall) { _restore_mmap(); if (close(_maps_fd)) log_sys_error("close", _procselfmaps); dm_free(_maps_buffer); _maps_buffer = NULL; if (_mstats < unlock_mstats) { if ((_mstats + lvm_getpagesize()) < unlock_mstats) log_error(INTERNAL_ERROR "Reserved memory (%ld) not enough: used %ld. Increase activation/reserved_memory?", (long)_mstats, (long)unlock_mstats); else /* FIXME Believed due to incorrect use of yes_no_prompt while locks held */ log_debug_mem("Suppressed internal error: Maps lock %ld < unlock %ld, a one-page difference.", (long)_mstats, (long)unlock_mstats); } } if (setpriority(PRIO_PROCESS, 0, _priority)) log_error("setpriority %u failed: %s", _priority, strerror(errno)); _release_memory(); }
void server_clear(void) { if (!cf_control_socket) { return; } server_running = 0; if (pthread_kill(server_thread, SIGUSR2)) { log_sys_error("server_clear: pthread_kill"); } util_thread_join(server_thread); /* * Remove SIGUSR2 handler (to avoid an error on reload) */ if (util_signal(SIGUSR2, SIG_DFL)) { log_error("server_main: util_signal failed"); } sht_clear(&server_function_table); return; }
static int _dev_read_ahead_dev(struct device *dev, uint32_t *read_ahead) { long read_ahead_long; if (dev->read_ahead != -1) { *read_ahead = (uint32_t) dev->read_ahead; return 1; } if (!dev_open(dev)) return_0; if (ioctl(dev->fd, BLKRAGET, &read_ahead_long) < 0) { log_sys_error("ioctl BLKRAGET", dev_name(dev)); if (!dev_close(dev)) stack; return 0; } if (!dev_close(dev)) stack; *read_ahead = (uint32_t) read_ahead_long; dev->read_ahead = read_ahead_long; log_very_verbose("%s: read_ahead is %u sectors", dev_name(dev), *read_ahead); return 1; }
int server_reply(int sock, char *message, ...) { int len, n; char buffer[RECV_BUFFER]; va_list ap; va_start(ap, message); len = vsnprintf(buffer, sizeof buffer, message, ap); va_end(ap); if (len >= sizeof buffer - 1) // Need to add \n here { log_error("server_reply: buffer exhausted"); return -1; } // No need for \0 here. buffer[len] = '\n'; n = write(sock, buffer, len + 1); if (n == -1) { log_sys_error("server_reply: write"); return -1; } return n; }