#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <pakfire/constants.h>
#include <pakfire/logging.h>
-#include <pakfire/types.h>
+#include <pakfire/package.h>
#include <pakfire/util.h>
#define NSEC_PER_SEC 1000000000
return pool_rel2id(pool, namespace, id, REL_NAMESPACE, 1);
}
-Id pakfire_parse_dep(Pakfire pakfire, const char* s) {
+Id pakfire_parse_dep(struct pakfire* pakfire, const char* s) {
Id id;
if (!s) {
return 0;
}
+ // Ignore empty strings
+ if (!*s)
+ return 0;
+
Pool* pool = pakfire_get_solv_pool(pakfire);
// Consume any leading space
return id;
}
-void pakfire_parse_deps(Pakfire pakfire, PakfirePackage pkg,
- void (*func)(PakfirePackage pkg, const char* dep), const char* deps) {
+void pakfire_parse_deps(struct pakfire* pakfire, struct pakfire_package* pkg,
+ void (*func)(struct pakfire_package* pkg, const char* dep), const char* deps) {
char* p = strdupa(deps);
while (*p) {
}
int pakfire_string_startswith(const char* s, const char* prefix) {
+ // Validate input
+ if (!s || !prefix) {
+ errno = EINVAL;
+ return 1;
+ }
+
return !strncmp(s, prefix, strlen(prefix));
}
int pakfire_string_endswith(const char* s, const char* suffix) {
+ // Validate input
+ if (!s || !suffix) {
+ errno = EINVAL;
+ return 1;
+ }
+
return !strcmp(s + strlen(s) - strlen(suffix), suffix);
}
+int pakfire_string_matches(const char* s, const char* pattern) {
+ return !!strstr(s, pattern);
+}
+
char* pakfire_unquote_in_place(char* s) {
if (!s || !*s)
return s;
return result;
}
-char** pakfire_split_string(const char* s, char delim) {
- // Copy string to stack and count spaces
- char buffer[strlen(s) + 2];
+static unsigned int pakfire_chrcnt(const char* s, char delim) {
+ size_t length = strlen(s);
- size_t count = 1;
- for (unsigned int i = 0; i < strlen(s) + 1; i++) {
- buffer[i] = s[i];
+ unsigned int count = 0;
- if (s[i] == delim) {
- buffer[i] = '\0';
+ for (unsigned int i = 0; i < length; i++)
+ if (s[i] == delim)
count++;
- }
+
+ return count;
+}
+
+char** pakfire_split_string(const char* s, char delim) {
+ char** array = NULL;
+
+ if (!s) {
+ errno = EINVAL;
+ return NULL;
}
- // Allocate an array of sufficient size
- char** ret = malloc(sizeof(*ret) * (count + 1));
+ // Count how often we need to split
+ unsigned int count = pakfire_chrcnt(s, delim) + 1;
+
+ // Allocate array
+ array = calloc(count + 1, sizeof(*array));
+ if (!array)
+ return NULL;
+
+ // Copy string to stack
+ char* p = strdupa(s);
+ if (!p)
+ return NULL;
- // Copy strings to heap one by one
unsigned int i = 0;
- char* p = buffer;
while (*p) {
- ret[i++] = strdup(p);
+ char* e = strchr(p, delim);
- // Move pointer to the next string
- p += strlen(p) + 1;
- }
+ // Terminate the string
+ if (e)
+ *e = '\0';
- // Terminate array
- ret[count] = NULL;
+ // Add string to the array
+ array[i++] = strdup(p);
- return ret;
+ // End loop when we reached the end
+ if (!e)
+ break;
+
+ // Or continue at the next line
+ p = e + 1;
+ }
+
+ return array;
}
char* pakfire_string_join(char** list, const char* delim) {
return pakfire_strftime("%Y-%m-%d", t);
}
+int __pakfire_strftime_now(char* dest, size_t length, const char* format) {
+ struct tm tm;
+
+ // Fetch the current time
+ const time_t t = time(NULL);
+ if (t < 0)
+ return 1;
+
+ // Convert to struct tm
+ struct tm* now = gmtime_r(&t, &tm);
+ if (!now)
+ return 1;
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+ strftime(dest, length, format, now);
+#pragma GCC diagnostic pop
+
+ return 0;
+}
+
int __pakfire_path_join(char* dest, size_t length,
const char* first, const char* second) {
if (!first)
return ret;
}
-char* pakfire_hexlify(const char* digest, const size_t length) {
+int pakfire_tty_is_noninteractive(void) {
+ const int fds[] = {
+ STDIN_FILENO,
+ STDOUT_FILENO,
+ STDERR_FILENO,
+ -1,
+ };
+
+ for (const int* fd = fds; *fd >= 0; fd++) {
+ if (!isatty(*fd))
+ return 1;
+ }
+
+ return 0;
+}
+
+char* __pakfire_hexlify(const unsigned char* digest, const size_t length) {
const char* hexdigits = "0123456789abcdef";
char* s = malloc((length * 2) + 1);
return s;
}
-static int pakfire_mkparentdir(const char* path, mode_t mode) {
+static int parse_nibble(char nibble) {
+ // Handle digits
+ if (nibble >= '0' && nibble <= '9')
+ return nibble - '0';
+
+ // Handle lowercase letters
+ if (nibble >= 'a' && nibble <= 'f')
+ return 10 + nibble - 'a';
+
+ // Handle uppercase letters
+ if (nibble >= 'A' && nibble <= 'F')
+ return 10 + nibble - 'A';
+
+ // Error
+ return -1;
+}
+
+int __pakfire_unhexlify(unsigned char* dst, const size_t l, const char* src) {
+ if (!src) {
+ errno = EINVAL;
+ return 1;
+ }
+
+ // Determine input length
+ const size_t length = strlen(src);
+
+ for (unsigned int i = 0, j = 0; i < length && j < l; i += 2, j++) {
+ int h = parse_nibble(src[i]);
+ int l = parse_nibble(src[i+1]);
+
+ // Check for invalid input
+ if (h < 0 || l < 0) {
+ errno = EINVAL;
+ return 1;
+ }
+
+ // Store result
+ dst[j] = h << 4 | l;
+ }
+
+ return 0;
+}
+
+int pakfire_mkparentdir(const char* path, mode_t mode) {
int r;
char* dirname = pakfire_dirname(path);
return r;
}
+// Digests
+
+size_t pakfire_digest_length(enum pakfire_digests digest) {
+ switch (digest) {
+ case PAKFIRE_DIGEST_SHA512:
+ return 64;
+
+ case PAKFIRE_DIGEST_SHA256:
+ return 32;
+
+ case PAKFIRE_DIGEST_SHA1:
+ return 20;
+
+ case PAKFIRE_DIGEST_NONE:
+ return 0;
+ }
+
+ return 0;
+}
+
// Archive Stuff
int pakfire_archive_copy_data(struct archive* src, struct archive* dst,
}
}
-int pakfire_archive_copy_data_to_buffer(Pakfire pakfire, struct archive* a,
+int pakfire_archive_copy_data_to_buffer(struct pakfire* pakfire, struct archive* a,
struct archive_entry* entry, char** data, size_t* data_size) {
*data = NULL;
*data_size = 0;
return 0;
// Allocate a block of the required size
- *data = malloc(required_size);
+ *data = calloc(1, required_size + 1);
if (!*data)
return ENOMEM;
// JSON Stuff
-static struct json_object* pakfire_json_parse(Pakfire pakfire, FILE* f) {
+static struct json_object* pakfire_json_parse(struct pakfire* pakfire, FILE* f) {
struct json_tokener* tokener = NULL;
struct json_object* json = NULL;
char* buffer = NULL;
// Create tokener
tokener = json_tokener_new();
if (!tokener) {
- ERROR(pakfire, "Could not allocate JSON tokener: %s\n", strerror(errno));
+ ERROR(pakfire, "Could not allocate JSON tokener: %m\n");
goto ERROR;
}
return json;
}
-struct json_object* pakfire_json_parse_from_file(Pakfire pakfire, const char* path) {
+struct json_object* pakfire_json_parse_from_file(struct pakfire* pakfire, const char* path) {
FILE* f = fopen(path, "r");
if (!f)
return NULL;
(t1->tv_sec == t2->tv_sec && t1->tv_nsec < t2->tv_nsec)
);
}
+
+// Resource Limits
+
+int pakfire_rlimit_set(struct pakfire* pakfire, int limit) {
+ struct rlimit rl;
+
+ // Sanity check
+ if (limit < 3) {
+ errno = EINVAL;
+ return 1;
+ }
+
+ // Fetch current configuration
+ if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
+ ERROR(pakfire, "Could not read RLIMIT_NOFILE: %m\n");
+ return 1;
+ }
+
+ // Do not attempt to set higher than maximum
+ if ((long unsigned int)limit > rl.rlim_max)
+ limit = rl.rlim_max;
+
+ rl.rlim_cur = limit;
+
+ // Set the new limit
+ if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
+ ERROR(pakfire, "Could not set RLIMIT_NOFILE to %lu: %m\n", rl.rlim_cur);
+ return 1;
+ }
+
+ DEBUG(pakfire, "RLIMIT_NOFILE set to %d\n", limit);
+
+ return 0;
+}
+
+/*
+ Resets RLIMIT_NOFILE to FD_SETSIZE (e.g. 1024)
+ for compatibility with software that uses select()
+*/
+int pakfire_rlimit_reset_nofile(struct pakfire* pakfire) {
+ return pakfire_rlimit_set(pakfire, FD_SETSIZE);
+}