summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libalpm/util.c')
-rw-r--r--lib/libalpm/util.c401
1 files changed, 401 insertions, 0 deletions
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
new file mode 100644
index 00000000..9ba3e1ee
--- /dev/null
+++ b/lib/libalpm/util.c
@@ -0,0 +1,401 @@
+/*
+ * util.c
+ *
+ * Copyright (c) 2002-2005 by Judd Vinet <jvinet@zeroflux.org>
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <time.h>
+#include <syslog.h>
+#include <zlib.h>
+#include <libtar.h>
+/* pacman */
+#include "log.h"
+#include "util.h"
+#include "alpm.h"
+
+/* borrowed and modified from Per Liden's pkgutils (http://crux.nu) */
+long _alpm_gzopen_frontend(char *pathname, int oflags, int mode)
+{
+ char* gzoflags;
+ int fd;
+ gzFile gzf;
+
+ switch (oflags & O_ACCMODE) {
+ case O_WRONLY:
+ gzoflags = "w";
+ break;
+ case O_RDONLY:
+ gzoflags = "r";
+ break;
+ case O_RDWR:
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ if((fd = open(pathname, oflags, mode)) == -1) {
+ return -1;
+ }
+ if((oflags & O_CREAT) && fchmod(fd, mode)) {
+ return -1;
+ }
+ if(!(gzf = gzdopen(fd, gzoflags))) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ return (long)gzf;
+}
+
+/* does the same thing as 'mkdir -p' */
+int _alpm_makepath(char *path)
+{
+ char *orig, *str, *ptr;
+ char full[PATH_MAX] = "";
+ mode_t oldmask;
+
+ oldmask = umask(0000);
+
+ orig = strdup(path);
+ str = orig;
+ while((ptr = strsep(&str, "/"))) {
+ if(strlen(ptr)) {
+ struct stat buf;
+
+ strcat(full, "/");
+ strcat(full, ptr);
+ if(stat(full, &buf)) {
+ if(mkdir(full, 0755)) {
+ free(orig);
+ umask(oldmask);
+ return(1);
+ }
+ }
+ }
+ }
+ free(orig);
+ umask(oldmask);
+ return(0);
+}
+
+int _alpm_copyfile(char *src, char *dest)
+{
+ FILE *in, *out;
+ size_t len;
+ char buf[4097];
+
+ in = fopen(src, "r");
+ if(in == NULL) {
+ return(1);
+ }
+ out = fopen(dest, "w");
+ if(out == NULL) {
+ return(1);
+ }
+
+ while((len = fread(buf, 1, 4096, in))) {
+ fwrite(buf, 1, len, out);
+ }
+
+ fclose(in);
+ fclose(out);
+ return(0);
+}
+
+/* Convert a string to uppercase
+ */
+char *_alpm_strtoupper(char *str)
+{
+ char *ptr = str;
+
+ while(*ptr) {
+ (*ptr) = toupper(*ptr);
+ ptr++;
+ }
+ return str;
+}
+
+/* Trim whitespace and newlines from a string
+ */
+char *_alpm_strtrim(char *str)
+{
+ char *pch = str;
+ while(isspace(*pch)) {
+ pch++;
+ }
+ if(pch != str) {
+ memmove(str, pch, (strlen(pch) + 1));
+ }
+
+ pch = (char*)(str + (strlen(str) - 1));
+ while(isspace(*pch)) {
+ pch--;
+ }
+ *++pch = '\0';
+
+ return str;
+}
+
+/* A cheap grep for text files, returns 1 if a substring
+ * was found in the text file fn, 0 if it wasn't
+ */
+int _alpm_grep(const char *fn, const char *needle)
+{
+ FILE *fp;
+
+ if((fp = fopen(fn, "r")) == NULL) {
+ return(0);
+ }
+ while(!feof(fp)) {
+ char line[1024];
+ fgets(line, 1024, fp);
+ if(feof(fp)) {
+ continue;
+ }
+ if(strstr(line, needle)) {
+ fclose(fp);
+ return(1);
+ }
+ }
+ fclose(fp);
+ return(0);
+}
+
+/* Create a lock file
+ */
+int _alpm_lckmk(char *file)
+{
+ int fd, count = 0;
+
+ while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1 && errno == EACCES) {
+ if(++count < 1) {
+ sleep(1);
+ } else {
+ return(-1);
+ }
+ }
+ return(fd > 0 ? 0 : -1);
+
+ return(0);
+}
+
+/* Remove a lock file
+ */
+int _alpm_lckrm(char *file)
+{
+ return(unlink(file) == -1);
+}
+
+int _alpm_unpack(char *archive, const char *prefix, const char *fn)
+{
+ TAR *tar = NULL;
+ char expath[PATH_MAX];
+ tartype_t gztype = {
+ (openfunc_t) _alpm_gzopen_frontend,
+ (closefunc_t)gzclose,
+ (readfunc_t) gzread,
+ (writefunc_t)gzwrite
+ };
+
+ /* open the .tar.gz package */
+ if(tar_open(&tar, archive, &gztype, O_RDONLY, 0, TAR_GNU) == -1) {
+ perror(archive);
+ return(1);
+ }
+ while(!th_read(tar)) {
+ if(fn && strcmp(fn, th_get_pathname(tar))) {
+ if(TH_ISREG(tar) && tar_skip_regfile(tar)) {
+ char errorstr[255];
+ snprintf(errorstr, 255, "bad tar archive: %s", archive);
+ perror(errorstr);
+ tar_close(tar);
+ return(1);
+ }
+ continue;
+ }
+ snprintf(expath, PATH_MAX, "%s/%s", prefix, th_get_pathname(tar));
+ if(tar_extract_file(tar, expath)) {
+ fprintf(stderr, "could not extract %s: %s\n", th_get_pathname(tar), strerror(errno));
+ }
+ if(fn) break;
+ }
+ tar_close(tar);
+
+ return(0);
+}
+
+/* does the same thing as 'rm -rf' */
+int _alpm_rmrf(char *path)
+{
+ int errflag = 0;
+ struct dirent *dp;
+ DIR *dirp;
+ char name[PATH_MAX];
+ extern int errno;
+
+ if(!unlink(path)) {
+ return(0);
+ } else {
+ if(errno == ENOENT) {
+ return(0);
+ } else if(errno == EPERM) {
+ /* fallthrough */
+ } else if(errno == EISDIR) {
+ /* fallthrough */
+ } else if(errno == ENOTDIR) {
+ return(1);
+ } else {
+ /* not a directory */
+ return(1);
+ }
+
+ if((dirp = opendir(path)) == (DIR *)-1) {
+ return(1);
+ }
+ for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+ if(dp->d_ino) {
+ sprintf(name, "%s/%s", path, dp->d_name);
+ if(strcmp(dp->d_name, "..") && strcmp(dp->d_name, ".")) {
+ errflag += _alpm_rmrf(name);
+ }
+ }
+ }
+ closedir(dirp);
+ if(rmdir(path)) {
+ errflag++;
+ }
+ return(errflag);
+ }
+ return(0);
+}
+
+int _alpm_log_action(unsigned char usesyslog, FILE *f, char *fmt, ...)
+{
+ char msg[1024];
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(msg, 1024, fmt, args);
+ va_end(args);
+
+ if(usesyslog) {
+ syslog(LOG_WARNING, "%s", msg);
+ }
+
+ if(f) {
+ time_t t;
+ struct tm *tm;
+
+ t = time(NULL);
+ tm = localtime(&t);
+
+ fprintf(f, "[%02d/%02d/%02d %02d:%02d] %s\n", tm->tm_mon+1, tm->tm_mday,
+ tm->tm_year-100, tm->tm_hour, tm->tm_min, msg);
+ }
+
+ return(0);
+}
+
+int _alpm_ldconfig(char *root)
+{
+ char line[PATH_MAX];
+ struct stat buf;
+
+ snprintf(line, PATH_MAX, "%setc/ld.so.conf", root);
+ if(!stat(line, &buf)) {
+ snprintf(line, PATH_MAX, "%ssbin/ldconfig", root);
+ if(!stat(line, &buf)) {
+ char cmd[PATH_MAX];
+ snprintf(cmd, PATH_MAX, "%s -r %s", line, root);
+ system(cmd);
+ }
+ }
+
+ return(0);
+}
+
+int _alpm_runscriptlet(char *root, char *installfn, char *script, char *ver, char *oldver)
+{
+ char scriptfn[PATH_MAX];
+ char cmdline[PATH_MAX];
+ char tmpdir[PATH_MAX] = "";
+ char *scriptpath;
+ struct stat buf;
+
+ return(0);
+
+ if(stat(installfn, &buf)) {
+ /* not found */
+ return(0);
+ }
+
+ if(!strcmp(script, "pre_upgrade") || !strcmp(script, "pre_install")) {
+ snprintf(tmpdir, PATH_MAX, "%stmp/", root);
+ if(stat(tmpdir, &buf)) {
+ _alpm_makepath(tmpdir);
+ }
+ snprintf(tmpdir, PATH_MAX, "%stmp/pacman-XXXXXX", root);
+ if(mkdtemp(tmpdir) == NULL) {
+ perror("error creating temp directory");
+ return(1);
+ }
+ _alpm_unpack(installfn, tmpdir, ".INSTALL");
+ snprintf(scriptfn, PATH_MAX, "%s/.INSTALL", tmpdir);
+ /* chop off the root so we can find the tmpdir in the chroot */
+ scriptpath = scriptfn + strlen(root) - 1;
+ return(0);
+ } else {
+ strncpy(scriptfn, installfn, PATH_MAX-1);
+ /* chop off the root so we can find the tmpdir in the chroot */
+ scriptpath = scriptfn + strlen(root) - 1;
+ }
+
+ if(!_alpm_grep(scriptfn, script)) {
+ /* script not found in scriptlet file */
+ return(0);
+ }
+
+ /* ORE
+ pm_cblog(PM_LOG_FLOW2, "Executing %s script...\n", script);*/
+ if(oldver) {
+ snprintf(cmdline, PATH_MAX, "echo \"umask 0022; source %s %s %s %s\" | chroot %s /bin/sh",
+ scriptpath, script, ver, oldver, root);
+ } else {
+ snprintf(cmdline, PATH_MAX, "echo \"umask 0022; source %s %s %s\" | chroot %s /bin/sh",
+ scriptpath, script, ver, root);
+ }
+ /* ORE
+ pm_cblog(PM_LOG_FLOW2, "%s\n", cmdline);*/
+ system(cmdline);
+
+ if(strlen(tmpdir) && _alpm_rmrf(tmpdir)) {
+ fprintf(stderr, "warning: could not remove tmpdir %s\n", tmpdir);
+ }
+ return(0);
+}
+
+/* vim: set ts=2 sw=2 noet: */