#include "../include/util.h" #include "../include/error.h" #include "../include/types.h" #include #include #include #include #include #include #include #include #include void pdebug(const char *func, const char *fmt, ...) { if (LM_DEBUG != 1) return; va_list args; va_start(args, fmt); printf("[libmp debug] %s: ", func); vprintf(fmt, args); printf("\n"); va_end(args); } bool eq(char *s1, char *s2) { if (NULL == s1 || NULL == s2) return false; if (strlen(s1) != strlen(s2)) return false; return strcmp(s1, s2) == 0; } bool is_letter(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } bool is_digit(char c) { return c >= '0' && c <= '9'; } bool contains(char *str, char s) { for (char *c = str; *c != 0; c++) if (*c == s) return true; return false; } bool parse_host(char *addr, char *host, uint16_t *port) { char *save = NULL, *portc = NULL; int portint = 0; if ((host = strtok_r(addr, ":", &save)) == NULL) { lm_error_set(LM_ERR_BadHost); return false; } if ((portc = strtok_r(NULL, ":", &save)) == NULL) { *port = 0; return true; } portint = atoi(portc); if (portint <= 0 || portint > UINT16_MAX) { lm_error_set(LM_ERR_BadPort); return false; } *port = portint; return true; } bool copy_to_buffer(void *buffer, void *src, size_t size, ssize_t *total, ssize_t *used) { if (*used + size > *total) return false; if (*used == 0) bzero(buffer, *total); memcpy(buffer + *used, src, size); *used += size; return true; } bool copy_from_buffer(void *dst, void *buffer, size_t size, ssize_t *total, ssize_t *used) { if (*used + size > *total) return false; if (*used == 0) bzero(dst, size); memcpy(dst, buffer + *used, size); *used += size; return true; } bool copy_blocks(struct archive *w, struct archive *r) { int64_t offset = 0; const void *buffer; size_t size = 0; int rc = 0; while ((rc = archive_read_data_block(r, &buffer, &size, &offset)) == ARCHIVE_OK) { rc = archive_write_data_block(w, buffer, size, offset); if (rc != ARCHIVE_OK) { lm_error_set(LM_ERR_ArcWBlockFail); return false; } } if (rc != ARCHIVE_EOF) { lm_error_set(LM_ERR_ArcRBlockFail); return false; } return true; } bool extract_archive(char *dst, char *src) { struct archive *reader = NULL, *writer = NULL; struct archive_entry *entry = NULL; int flags = 0, rc = 0; char *oldpwd = NULL; bool ret = false; char srcfull[PATH_MAX + 1]; if (NULL == realpath(src, srcfull)) { lm_error_set(LM_ERR_ArcRealpathFail); goto end; } oldpwd = getcwd(NULL, 0); if (NULL == oldpwd) { lm_error_set(LM_ERR_GetCwdFail); goto end; } chdir(dst); flags = ARCHIVE_EXTRACT_PERM; flags |= ARCHIVE_EXTRACT_UNLINK; reader = archive_read_new(); writer = archive_write_disk_new(); if (NULL == reader || NULL == writer) { lm_error_set(LM_ERR_ArcNewFail); goto end; } archive_write_disk_set_options(writer, flags); archive_write_disk_set_standard_lookup(writer); archive_read_support_format_tar(reader); archive_read_support_filter_gzip(reader); if (archive_read_open_filename(reader, srcfull, 1024 * 10) != ARCHIVE_OK) { lm_error_set(LM_ERR_ArcOpenFail); goto end; } while ((rc = archive_read_next_header(reader, &entry)) == ARCHIVE_OK) { rc = archive_write_header(writer, entry); if (rc != ARCHIVE_OK) { lm_error_set(LM_ERR_ArcWHeaderFail); goto end; } if (!copy_blocks(writer, reader)) goto end; rc = archive_write_finish_entry(writer); if (rc != ARCHIVE_OK) { lm_error_set(LM_ERR_ArcWEntryFail); goto end; } } if (rc != ARCHIVE_EOF) { lm_error_set(LM_ERR_ArcNextHeaderFail); goto end; } ret = true; end: if (NULL != reader) { archive_read_close(reader); archive_read_free(reader); } if (NULL != writer) { archive_write_close(writer); archive_write_free(writer); } if (NULL != oldpwd) { chdir(oldpwd); free(oldpwd); } return ret; } bool exists(char *path) { struct stat st; return stat(path, &st) == 0; } bool is_file(char *path) { struct stat st; if (stat(path, &st) < 0) return false; return S_ISREG(st.st_mode); } bool is_dir(char *path) { struct stat st; if (stat(path, &st) < 0) return false; return S_ISDIR(st.st_mode); } bool can_read(char *path) { return access(path, R_OK) == 0; } bool can_write(char *path) { return access(path, W_OK) == 0; } bool mkdir_ifnot(char *path) { return !(mkdir(path, 0700) < 0 && errno != EEXIST); } void sockaddr_to_str(struct sockaddr *addr, char *str) { struct sockaddr_in *ipv4; struct sockaddr_in6 *ipv6; switch (addr->sa_family) { case AF_INET: ipv4 = (struct sockaddr_in *)addr; inet_ntop(AF_INET, &ipv4->sin_addr, str, INET_ADDRSTRLEN); break; case AF_INET6: ipv6 = (struct sockaddr_in6 *)addr; inet_ntop(AF_INET6, &ipv6->sin6_addr, str, INET6_ADDRSTRLEN); break; } } bool package_name_valid(char *name) { for (char *c = name; *c != 0; c++) { if (!is_digit(*c) && !is_letter(*c) && *c != '-' && *c != '.') return false; } return true; } bool package_version_valid(char *version) { for (char *c = version; *c != 0; c++) { if (!is_digit(*c) && !is_letter(*c) && *c != '-' && *c != '+' && *c != '.') return false; } return true; } bool package_parse(char *package, char *name, char *version) { ssize_t ni = 0, vi = -1; for (char *c = package; *c != 0; c++) { if (vi < 0 && *c == '_') { vi = 0; continue; } if (vi < 0) name[ni++] = *c; else version[vi++] = *c; } if (ni > 0 && vi > 0) { name[ni] = 0; version[vi] = 0; return package_name_valid(name) && package_version_valid(version); } return false; } int join(char *res, const char *base, const char *pth) { int blen = strlen(base); if ((base[blen - 1] == '/' && pth[0] != '/') || (base[blen - 1] != '/' && pth[0] == '/')) { return sprintf(res, "%s%s", base, pth); } else if (base[blen - 1] != '/' && pth[0] != '/') { return sprintf(res, "%s/%s", base, pth); } else if (base[blen - 1] == '/' && pth[0] == '/') { char *basedup = strdup(base); basedup[blen - 1] = '\0'; return sprintf(res, "%s%s", basedup, pth); } return -1; } int join_multiple(char *res, const char *base, const char *pth, const char *pth2) { char firstp[strlen(base) + strlen(pth) + 5]; if (join(firstp, base, pth) < 0) return -1; return join(res, firstp, pth2); } char *join_alloc(const char *base, const char *pth) { int pthlen = strlen(base) + strlen(pth); char *path = malloc(pthlen + 5); join(path, base, pth); return path; } bool pkglist_contains(lm_pkg_t *list, lm_pkg_t *pkg) { lm_pkg_t *cur = list; while (cur) { if (eq(pkg->name, cur->name)) return true; cur = cur->next; } return false; } lm_pkg_t *pkglist_del(lm_pkg_t *list, lm_pkg_t *pkg) { if (NULL == pkg) { lm_error_set(LM_ERR_ArgNULL); return list; } if (NULL == list) return list; if (eq(list->name, pkg->name)) { list = NULL; return list; } lm_pkg_t *cur = list; lm_pkg_t *found = NULL; while (NULL != cur->next) { if (eq(cur->next->name, pkg->name)) { found = cur->next; cur->next = cur->next->next; break; } cur = cur->next; } free(found); return list; } lm_pkg_t *pkglist_add_top(lm_pkg_t *list, lm_pkg_t *pkg) { lm_pkg_t *new = malloc(sizeof(lm_pkg_t)); memcpy(new, pkg, sizeof(lm_pkg_t)); new->next = list; list = new; return list; } lm_pkg_t *pkglist_add_end(lm_pkg_t *list, lm_pkg_t *pkg) { lm_pkg_t *new = malloc(sizeof(lm_pkg_t)), *cur = list; memcpy(new, pkg, sizeof(lm_pkg_t)); new->next = NULL; if (NULL == cur) { list = new; return list; } while (cur->next != NULL) cur = cur->next; cur->next = new; return list; } void pkglist_free(lm_pkg_t *list) { lm_pkg_t *cur = list, *old = NULL; while (cur != NULL) { old = cur; cur = cur->next; free(old); } } bool copy_file(char *dst, char *src) { FILE *dstp = NULL, *srcp = NULL; bool ret = false; if ((dstp = fopen(dst, "w")) == NULL) { lm_error_set(LM_ERR_DstOpenFail); goto end; } if ((srcp = fopen(src, "r")) == NULL) { lm_error_set(LM_ERR_SrcOpenFail); goto end; } char buf[255]; size_t bufsize = sizeof(buf), read = 0; while ((read = fread(buf, 1, bufsize, srcp)) > 0) { if (fwrite(buf, 1, read, dstp) <= 0) { lm_error_set(LM_ERR_DstWriteFail); goto end; } } ret = true; end: if (NULL != dstp) fclose(dstp); if (NULL != srcp) fclose(srcp); return ret; } char *get_md5(char *path) { const EVP_MD *alg = NULL; EVP_MD_CTX *ctx = NULL; FILE *file = NULL; char *sum = NULL, buffer[255]; unsigned char digest[16]; unsigned int digest_len; size_t read = 0; alg = EVP_md5(); ctx = EVP_MD_CTX_new(); bzero(buffer, sizeof(buffer)); bzero(digest, sizeof(digest)); if ((file = fopen(path, "r")) == NULL) { lm_error_set(LM_ERR_HashOpenFail); return NULL; } if (EVP_DigestInit_ex(ctx, alg, NULL) <= 0) { lm_error_set(LM_ERR_HashDigestFail); return NULL; } while ((read = fread(buffer, 1, sizeof(buffer), file)) > 0) EVP_DigestUpdate(ctx, buffer, read); EVP_DigestFinal(ctx, digest, &digest_len); EVP_MD_CTX_free(ctx); sum = malloc((digest_len * 2) + 1); for (int i = 0; i < sizeof(digest); i++) sprintf(&sum[i * 2], "%02x", digest[i]); fclose(file); return sum; }