/* * Utilities * * Copyright (C) 2010 by Multi-Tech Systems * * Author: James Maki * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include "utils.h" #include "log.h" char *basename(const char *path) { const char *cp = strrchr(path, '/'); if(cp) { return (char *) cp + 1; } else { return (char *) path; } } int tokcmp(const char *cmd, const char *pattern) { int len = strlen(cmd); if (len > strlen(pattern)) { return -1; } return memcmp(pattern, cmd, len); } char *strrstrip(char *str) { char *end; char *prev; if (!str || !*str) { return NULL; } prev = end = str + strlen(str); while (end > str && isspace(*(end - 1))) { end--; } *end = '\0'; return prev == end ? NULL : str; } ssize_t safe_read(int fd, void *buf, size_t count) { ssize_t n; do { n = read(fd, buf, count); } while (n < 0 && errno == EINTR); return n; } ssize_t safe_readn(int fd, void *buf, size_t len) { ssize_t cc; ssize_t total; total = 0; while (len) { cc = safe_read(fd, buf, len); if (cc < 0) { if (total) { return total; } return cc; } total += cc; buf = buf + cc; len -= cc; } return total; } ssize_t safe_write(int fd, const void *buf, size_t count) { ssize_t n; do { n = write(fd, buf, count); } while (n < 0 && errno == EINTR); return n; } ssize_t full_write(int fd, const void *buf, size_t len) { ssize_t cc; ssize_t total; total = 0; while (len) { cc = safe_write(fd, buf, len); if (cc < 0) { if (total) { return total; } return cc; } total += cc; buf = ((const char *)buf) + cc; len -= cc; } return total; } int user_yesno(int def, const char *fmt, ...) { char buf[128]; char *line; va_list ap; while (1) { va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); printf("? [%c/%c] ", def == USER_YESNO_YES ? 'Y' : 'y', def == USER_YESNO_NO ? 'N' : 'n'); line = fgets(buf, sizeof(buf), stdin); if (!line) { return -1; } switch (toupper(*line)) { case '\n': return def; case 'Y': return USER_YESNO_YES; case 'N': return USER_YESNO_NO; } } return -1; } int systemf(const char *fmt, ...) { int err; va_list ap; char *buf; va_start(ap, fmt); err = vasprintf(&buf, fmt, ap); va_end(ap); if (err < 0) { log_error("out of memory"); return -1; } err = system(buf); free(buf); return err; } FILE *popenf(const char *mode, const char *fmt, ...) { int err; va_list ap; char *buf; FILE *pipe; va_start(ap, fmt); err = vasprintf(&buf, fmt, ap); va_end(ap); if (err < 0) { log_error("out of memory"); return NULL; } pipe = popen(buf, mode); free(buf); return pipe; } char *shell_path_expand(const char *path) { char buf[PATH_MAX + 1]; FILE *file; char *line; file = popenf("r", "echo -n \"%s\"", path); if (!file) { log_error("popen failed"); return NULL; } line = fgets(buf, sizeof(buf), file); pclose(file); if (!line) { log_error("no line read"); return NULL; } return strdup(line); } #define MAX_TRY 10 int device_lock(const char *path) { char *lock_path; if (asprintf(&lock_path, "/var/lock/LCK..%s", basename(path)) < 0) { log_error("out of memory"); return -1; } int lock_fd = open(lock_path, O_CREAT | O_RDWR, 0644); if (lock_fd >= 0) { unsigned char num_try = 0; while (1) { int lockErr = flock(lock_fd, LOCK_EX | LOCK_NB); if (lockErr == 0) { free(lock_path); return lock_fd; } else if (errno != EWOULDBLOCK) { break; } log_error("%i number of trying to create %s: %m", num_try+1, lock_path); if (num_try++>=MAX_TRY) { break; //something locks device too long } usleep(100000ul);//100ms } } log_error("failed to make lock %s: %m", lock_path); free(lock_path); return device_unlock(lock_fd); } int device_unlock(int lock) { close(lock); return -1; } int indexOfChar(const char *array, int len, char character) { int i; for (i = 0; i < len; i++) { if (array[i] == character) { return i; } } return -1; }