summaryrefslogtreecommitdiff
path: root/lib/libalpm/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/util.c')
-rw-r--r--lib/libalpm/util.c134
1 files changed, 98 insertions, 36 deletions
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index e1413a25..65b6372a 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -43,7 +43,6 @@
/* libalpm */
#include "util.h"
#include "log.h"
-#include "error.h"
#include "package.h"
#include "alpm.h"
#include "alpm_list.h"
@@ -186,57 +185,65 @@ int _alpm_makepath(const char *path)
/* does the same thing as 'mkdir -p' */
int _alpm_makepath_mode(const char *path, mode_t mode)
{
- char *orig, *str, *ptr;
- char full[PATH_MAX] = "";
- mode_t oldmask;
-
- oldmask = umask(0000);
+ /* A bit of pointer hell here. Descriptions:
+ * orig - a copy of path so we can safely butcher it with strsep
+ * str - the current position in the path string (after the delimiter)
+ * ptr - the original position of str after calling strsep
+ * incr - incrementally generated path for use in stat/mkdir call
+ */
+ char *orig, *str, *ptr, *incr;
+ mode_t oldmask = umask(0000);
+ int ret = 0;
orig = strdup(path);
+ incr = calloc(strlen(orig) + 1, sizeof(char));
str = orig;
while((ptr = strsep(&str, "/"))) {
if(strlen(ptr)) {
struct stat buf;
-
- strcat(full, "/");
- strcat(full, ptr);
- if(stat(full, &buf)) {
- if(mkdir(full, mode)) {
- FREE(orig);
- umask(oldmask);
- _alpm_log(PM_LOG_ERROR, _("failed to make path '%s' : %s\n"),
- path, strerror(errno));
- return(1);
+ /* we have another path component- append the newest component to
+ * existing string and create one more level of dir structure */
+ strcat(incr, "/");
+ strcat(incr, ptr);
+ if(stat(incr, &buf)) {
+ if(mkdir(incr, mode)) {
+ ret = 1;
+ break;
}
}
}
}
- FREE(orig);
+ free(orig);
+ free(incr);
umask(oldmask);
- return(0);
+ return(ret);
}
+#define CPBUFSIZE 8 * 1024
+
int _alpm_copyfile(const char *src, const char *dest)
{
FILE *in, *out;
size_t len;
- char buf[4097];
+ char *buf;
+ int ret = 0;
- in = fopen(src, "r");
+ in = fopen(src, "rb");
if(in == NULL) {
return(1);
}
- out = fopen(dest, "w");
+ out = fopen(dest, "wb");
if(out == NULL) {
fclose(in);
return(1);
}
+ CALLOC(buf, 1, CPBUFSIZE, ret = 1; goto cleanup;);
+
/* do the actual file copy */
- while((len = fread(buf, 1, 4096, in))) {
+ while((len = fread(buf, 1, CPBUFSIZE, in))) {
fwrite(buf, 1, len, out);
}
- fclose(in);
/* chmod dest to permissions of src, as long as it is not a symlink */
struct stat statbuf;
@@ -246,12 +253,14 @@ int _alpm_copyfile(const char *src, const char *dest)
}
} else {
/* stat was unsuccessful */
- fclose(out);
- return(1);
+ ret = 1;
}
+cleanup:
+ fclose(in);
fclose(out);
- return(0);
+ FREE(buf);
+ return(ret);
}
/* Trim whitespace and newlines from a string
@@ -371,6 +380,13 @@ int _alpm_lckrm()
/* Compression functions */
+/**
+ * @brief Unpack a specific file or all files in an archive.
+ *
+ * @param archive the archive to unpack
+ * @param prefix where to extract the files
+ * @param fn a file within the archive to unpack or NULL for all
+ */
int _alpm_unpack(const char *archive, const char *prefix, const char *fn)
{
int ret = 1;
@@ -382,7 +398,7 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn)
ALPM_LOG_FUNC;
if((_archive = archive_read_new()) == NULL)
- RET_ERR(PM_ERR_LIBARCHIVE_ERROR, -1);
+ RET_ERR(PM_ERR_LIBARCHIVE, -1);
archive_read_support_compression_all(_archive);
archive_read_support_format_all(_archive);
@@ -408,13 +424,17 @@ int _alpm_unpack(const char *archive, const char *prefix, const char *fn)
archive_entry_set_mode(entry, 0755);
}
+ /* If a specific file was requested skip entries that don't match. */
if (fn && strcmp(fn, entryname)) {
+ _alpm_log(PM_LOG_DEBUG, "skipping: %s\n", entryname);
if (archive_read_data_skip(_archive) != ARCHIVE_OK) {
ret = 1;
goto cleanup;
}
continue;
}
+
+ /* Extract the archive entry. */
ret = 0;
snprintf(expath, PATH_MAX, "%s/%s", prefix, entryname);
archive_entry_set_pathname(entry, expath);
@@ -535,8 +555,8 @@ int _alpm_str_cmp(const void *s1, const void *s2)
return(strcmp(s1, s2));
}
-/** Find a package file in an alpm cachedir.
- * @param filename name of package file to find
+/** Find a filename in a registered alpm cachedir.
+ * @param filename name of file to find
* @return malloced path of file, NULL if not found
*/
char *_alpm_filecache_find(const char* filename)
@@ -640,13 +660,7 @@ char SYMEXPORT *alpm_get_md5sum(const char *filename)
ret = md5_file(filename, output);
if (ret > 0) {
- if (ret == 1) {
- _alpm_log(PM_LOG_ERROR, _("md5: %s can't be opened\n"), filename);
- } else if (ret == 2) {
- _alpm_log(PM_LOG_ERROR, _("md5: %s can't be read\n"), filename);
- }
-
- return(NULL);
+ RET_ERR(PM_ERR_NOT_A_FILE, NULL);
}
/* Convert the result to something readable */
@@ -660,4 +674,52 @@ char SYMEXPORT *alpm_get_md5sum(const char *filename)
return(md5sum);
}
+int _alpm_test_md5sum(const char *filepath, const char *md5sum)
+{
+ char *md5sum2;
+ int ret;
+
+ md5sum2 = alpm_get_md5sum(filepath);
+
+ if(md5sum == NULL || md5sum2 == NULL) {
+ ret = -1;
+ } else if(strcmp(md5sum, md5sum2) != 0) {
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+
+ FREE(md5sum2);
+ return(ret);
+}
+
+char *_alpm_archive_fgets(char *line, size_t size, struct archive *a)
+{
+ /* for now, just read one char at a time until we get to a
+ * '\n' char. we can optimize this later with an internal
+ * buffer. */
+ /* leave room for zero terminator */
+ char *last = line + size - 1;
+ char *i;
+
+ for(i = line; i < last; i++) {
+ int ret = archive_read_data(a, i, 1);
+ /* special check for first read- if null, return null,
+ * this indicates EOF */
+ if(i == line && (ret <= 0 || *i == '\0')) {
+ return(NULL);
+ }
+ /* check if read value was null or newline */
+ if(ret <= 0 || *i == '\0' || *i == '\n') {
+ last = i + 1;
+ break;
+ }
+ }
+
+ /* always null terminate the buffer */
+ *last = '\0';
+
+ return(line);
+}
+
/* vim: set ts=2 sw=2 noet: */