[pacman-dev] [PATCH] Cleanups: libalpm/utils
Johannes Weiner
hannes at saeurebad.de
Wed Jan 24 10:20:26 EST 2007
Hi,
I tried to clean up lib/libalpm/util.[ch]. It's not yet complete, I
would like to have some comments on it first.
Some notes:
There has to be a proper way handling out-of-memory. The lib
can't do anything anymore without memory - am I right?
_alpm_runscriptlet is really long and I'm going to split it.
So, here goes the patch:
Signed-off-by: Johannes Weiner <hannes at saeurebad.de>
-------------- next part --------------
diff -Naur pacman-lib.old/lib/libalpm/util.c pacman-lib/lib/libalpm/util.c
--- pacman-lib.old/lib/libalpm/util.c 2007-01-24 16:09:16.000000000 +0100
+++ pacman-lib/lib/libalpm/util.c 2007-01-24 16:10:13.000000000 +0100
@@ -64,9 +64,49 @@
#include "package.h"
#include "alpm.h"
+/* Memory allocation frontends with return value check.
+ * TODO: Think about an elegant way to die on failure */
+static void *safe_mem(void *r)
+{
+ if (r) {
+ return (r);
+ }
+
+ _alpm_log(PM_LOG_ERROR, "Memory exhausted.\n");
+
+ /* TODO: This is probably the wrong way */
+ alpm_release();
+ exit(2);
+}
+
+void *pmalloc(size_t s)
+{
+ return (safe_mem(malloc(s)));
+}
+
+void *pcalloc(size_t e, size_t s)
+{
+ return (safe_mem(calloc(e, s)));
+}
+
+void *prealloc(void *p, size_t s)
+{
+ return (safe_mem(realloc(p, s)));
+}
+
+char *pstrdup(const char *s)
+{
+ return (safe_mem((char *) strdup(s)));
+}
+
+void *palloca(size_t s)
+{
+ return (safe_mem(alloca(s)));
+}
+
#ifdef __sun__
/* This is a replacement for strsep which is not portable (missing on Solaris).
- * Copyright (c) 2001 by Fran??ois Gouget <fgouget_at_codeweavers.com> */
+ * Copyright (c) 2001 by Fran?ois Gouget <fgouget_at_codeweavers.com> */
char* strsep(char** str, const char* delims)
{
char* token;
@@ -92,13 +132,12 @@
/* Backported from Solaris Express 4/06
* Copyright (c) 2006 Sun Microsystems, Inc. */
-char * mkdtemp(char *template)
+char * mkdtemp(const char *template)
{
- char *t = alloca(strlen(template) + 1);
- char *r;
+ char *r, *t = palloca(strlen(template) + 1);
/* Save template */
- (void) strcpy(t, template);
+ strcpy(t, template);
for (; ; ) {
r = mktemp(template);
@@ -113,7 +152,7 @@
return (NULL);
/* Reset template */
- (void) strcpy(template, t);
+ strcpy(template, t);
}
}
#endif
@@ -121,14 +160,16 @@
/* does the same thing as 'mkdir -p' */
int _alpm_makepath(char *path)
{
- char *orig, *str, *ptr;
- char full[PATH_MAX] = "";
mode_t oldmask;
+ char *orig, *str, *ptr, full[PATH_MAX];
oldmask = umask(0000);
- orig = strdup(path);
+ memset(full, 0, sizeof(full));
+
+ orig = pstrdup(path);
str = orig;
+
while((ptr = strsep(&str, "/"))) {
if(strlen(ptr)) {
struct stat buf;
@@ -149,32 +190,46 @@
return(0);
}
-int _alpm_copyfile(char *src, char *dest)
+int _alpm_copyfile(const char *src, const char *dest)
{
- FILE *in, *out;
- size_t len;
- char buf[4097];
+ FILE *fp;
+ char *buf;
+ struct stat sbuf;
- in = fopen(src, "r");
- if(in == NULL) {
+ if (stat(src, &sbuf)) {
return(1);
}
- out = fopen(dest, "w");
- if(out == NULL) {
- fclose(in);
+
+ if (!(fp = fopen(src, "r"))) {
return(1);
}
- while((len = fread(buf, 1, 4096, in))) {
- fwrite(buf, 1, len, out);
+ buf = pmalloc(sbuf.st_size);
+
+ if (fread(buf, sbuf.st_size, 1, fp) != 1) {
+ FREE(buf);
+ return(1);
+ }
+
+ fclose(fp);
+
+ if (!(fp = fopen(dest, "w"))) {
+ FREE(buf);
+ return(1);
+ }
+
+ if (fwrite(buf, sbuf.st_size, 1, fp) != 1) {
+ FREE(buf);
+ fclose(fp);
+ return(1);
}
- fclose(in);
- fclose(out);
+ FREE(buf);
+ fclose(fp);
return(0);
}
-/* Convert a string to uppercase
+/* Convert a string to uppercase destructively
*/
char *_alpm_strtoupper(char *str)
{
@@ -187,7 +242,7 @@
return str;
}
-/* Trim whitespace and newlines from a string
+/* Trim whitespace and newlines from a string destructively
*/
char *_alpm_strtrim(char *str)
{
@@ -210,8 +265,8 @@
return(str);
}
- pch = (char *)(str + (strlen(str) - 1));
- while(isspace((int)*pch)) {
+ pch = (str + (strlen(str) - 1));
+ while(isspace(*pch)) {
pch--;
}
*++pch = '\0';
@@ -221,35 +276,36 @@
/* Create a lock file
*/
-int _alpm_lckmk(char *file)
+int _alpm_lckmk(const char *file)
{
int fd, count = 0;
char *dir, *ptr;
/* create the dir of the lockfile first */
- dir = strdup(file);
+ dir = pstrdup(file);
ptr = strrchr(dir, '/');
if(ptr) {
*ptr = '\0';
}
_alpm_makepath(dir);
- while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1 && errno == EACCES) {
+ while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000) == -1) &&
+ (errno == EACCES)) {
if(++count < 1) {
sleep(1);
- } else {
+ } else {
return(-1);
}
}
- free(dir);
+ FREE(dir);
return(fd > 0 ? fd : -1);
}
/* Remove a lock file
*/
-int _alpm_lckrm(char *file)
+int _alpm_lckrm(const char *file)
{
if(unlink(file) == -1 && errno != ENOENT) {
return(-1);
@@ -272,8 +328,12 @@
archive_read_support_compression_all(_archive);
archive_read_support_format_all(_archive);
- if(archive_read_open_file(_archive, archive, ARCHIVE_DEFAULT_BYTES_PER_BLOCK) != ARCHIVE_OK) {
- _alpm_log(PM_LOG_ERROR, _("could not open %s: %s\n"), archive, archive_error_string(_archive));
+ if(archive_read_open_file(_archive,
+ archive,
+ ARCHIVE_DEFAULT_BYTES_PER_BLOCK)
+ != ARCHIVE_OK) {
+ _alpm_log(PM_LOG_ERROR, _("could not open %s: %s\n"), archive,
+ archive_error_string(_archive));
RET_ERR(PM_ERR_PKG_OPEN, -1);
}
@@ -283,10 +343,18 @@
return(1);
continue;
}
- snprintf(expath, PATH_MAX, "%s/%s", prefix, archive_entry_pathname(entry));
+
+ snprintf(expath, PATH_MAX, "%s/%s", prefix,
+ archive_entry_pathname(entry));
archive_entry_set_pathname(entry, expath);
- if(archive_read_extract(_archive, entry, ARCHIVE_EXTRACT_FLAGS) != ARCHIVE_OK) {
- _alpm_log(PM_LOG_ERROR, _("could not extract %s: %s\n"), archive_entry_pathname(entry), archive_error_string(_archive));
+
+ if(archive_read_extract(_archive,
+ entry,
+ ARCHIVE_EXTRACT_FLAGS)
+ != ARCHIVE_OK) {
+ _alpm_log(PM_LOG_ERROR, _("could not extract %s: %s\n"),
+ archive_entry_pathname(entry),
+ archive_error_string(_archive));
return(1);
}
@@ -300,49 +368,53 @@
}
/* does the same thing as 'rm -rf' */
-int _alpm_rmrf(char *path)
+int _alpm_rmrf(const char *path)
{
int errflag = 0;
struct dirent *dp;
DIR *dirp;
char name[PATH_MAX];
- struct stat st;
+ struct stat st;
- if(stat(path, &st) == 0) {
- if(S_ISREG(st.st_mode)) {
- if(!unlink(path)) {
- return(0);
- } else {
- if(errno == ENOENT) {
- return(0);
- } else {
- /* not a directory */
- return(1);
- }
- }
- } else if(S_ISDIR(st.st_mode)) {
- 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);
- }
+ if(stat(path, &st)) {
+ return(0);
+ }
+
+ if(S_ISREG(st.st_mode)) {
+ if(!unlink(path)) {
+ return(0);
+ }
+
+ if(errno == ENOENT) {
+ return(0);
+ } else {
+ /* not a directory */
+ return(1);
+ }
+ } else if(S_ISDIR(st.st_mode)) {
+ if(!(dirp = opendir(path))) {
+ 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);
+ closedir(dirp);
+
+ if(rmdir(path)) {
+ errflag++;
+ }
}
- return(0);
+
+ return(errflag);
}
-int _alpm_logaction(unsigned short usesyslog, FILE *f, const char *str)
+int _alpm_logaction(unsigned char usesyslog, FILE *f, const char *str)
{
_alpm_log(PM_LOG_DEBUG, _("logaction called: %s"), str);
@@ -387,37 +459,39 @@
/* A cheap grep for text files, returns 1 if a substring
* was found in the text file fn, 0 if it wasn't
+ *
+ * TODO: Remove hardcoded buffersize
*/
static int grep(const char *fn, const char *needle)
{
FILE *fp;
+ char line[1024];
if((fp = fopen(fn, "r")) == NULL) {
return(0);
}
- while(!feof(fp)) {
- char line[1024];
- fgets(line, 1024, fp);
- if(feof(fp)) {
- continue;
- }
+
+ while(fgets(line, 1024, fp)) {
if(strstr(line, needle)) {
fclose(fp);
return(1);
}
}
+
fclose(fp);
return(0);
}
-int _alpm_runscriptlet(char *root, char *installfn, char *script, char *ver, char *oldver, pmtrans_t *trans)
+/*
+ * TODO: This function is WAY too complex and long!!!
+ */
+int _alpm_runscriptlet(const char *root, const char *installfn,
+ const char *script, const char *ver,
+ const char *oldver, pmtrans_t *trans)
{
- char scriptfn[PATH_MAX];
- char cmdline[PATH_MAX];
- char tmpdir[PATH_MAX] = "";
- char *scriptpath;
+ char scriptfn[PATH_MAX], cmdline[PATH_MAX], tmpdir[PATH_MAX];
+ char *scriptpath, cwd[PATH_MAX] = "";
struct stat buf;
- char cwd[PATH_MAX] = "";
pid_t pid;
int retval = 0;
@@ -433,7 +507,8 @@
}
snprintf(tmpdir, PATH_MAX, "%stmp/alpm_XXXXXX", root);
if(mkdtemp(tmpdir) == NULL) {
- _alpm_log(PM_LOG_ERROR, _("could not create temp directory"));
+ _alpm_log(PM_LOG_ERROR,
+ _("could not create temp directory"));
return(1);
}
_alpm_unpack(installfn, tmpdir, ".INSTALL");
@@ -453,14 +528,18 @@
/* save the cwd so we can restore it later */
if(getcwd(cwd, PATH_MAX) == NULL) {
- _alpm_log(PM_LOG_ERROR, _("could not get current working directory"));
- /* in case of error, cwd content is undefined: so we set it to something */
+ _alpm_log(PM_LOG_ERROR,
+ _("could not get current working directory"));
+ /* in case of error, cwd content is undefined:
+ * so we set it to something */
cwd[0] = 0;
}
/* just in case our cwd was removed in the upgrade operation */
if(chdir(root) != 0) {
- _alpm_log(PM_LOG_ERROR, _("could not change directory to %s (%s)"), root, strerror(errno));
+ _alpm_log(PM_LOG_ERROR,
+ _("could not change directory to %s (%s)"),
+ root, strerror(errno));
}
_alpm_log(PM_LOG_FLOW2, _("executing %s script..."), script);
@@ -476,52 +555,70 @@
pid = fork();
if(pid == -1) {
- _alpm_log(PM_LOG_ERROR, _("could not fork a new process (%s)"), strerror(errno));
+ _alpm_log(PM_LOG_ERROR,
+ _("could not fork a new process (%s)"),
+ strerror(errno));
retval = 1;
goto cleanup;
}
if(pid == 0) {
FILE *pp;
+ char line[1024];
_alpm_log(PM_LOG_DEBUG, _("chrooting in %s"), root);
if(chroot(root) != 0) {
- _alpm_log(PM_LOG_ERROR, _("could not change the root directory (%s)"), strerror(errno));
+ _alpm_log(PM_LOG_ERROR,
+ _("could not change the root directory (%s)"),
+ strerror(errno));
return(1);
}
if(chdir("/") != 0) {
- _alpm_log(PM_LOG_ERROR, _("could not change directory to / (%s)"), strerror(errno));
+ _alpm_log(PM_LOG_ERROR,
+ _("could not change directory to / (%s)"),
+ strerror(errno));
return(1);
}
umask(0022);
_alpm_log(PM_LOG_DEBUG, _("executing \"%s\""), cmdline);
pp = popen(cmdline, "r");
if(!pp) {
- _alpm_log(PM_LOG_ERROR, _("call to popen failed (%s)"), strerror(errno));
+ _alpm_log(PM_LOG_ERROR,
+ _("call to popen failed (%s)"),
+ strerror(errno));
retval = 1;
goto cleanup;
}
- while(!feof(pp)) {
- char line[1024];
- if(fgets(line, 1024, pp) == NULL)
- break;
+ while(fgets(line, 1024, pp)) {
+ size_t slen, dlen;
+ slen = strlen(SCRIPTLET_START);
+ dlen = strlen(SCRIPTLET_DONE);
+
/* "START <event desc>" */
- if((strlen(line) > strlen(SCRIPTLET_START)) && !strncmp(line, SCRIPTLET_START, strlen(SCRIPTLET_START))) {
- EVENT(trans, PM_TRANS_EVT_SCRIPTLET_START, _alpm_strtrim(line + strlen(SCRIPTLET_START)), NULL);
+ if((strlen(line) > slen) &&
+ !strncmp(line, SCRIPTLET_START, slen)) {
+ EVENT(trans, PM_TRANS_EVT_SCRIPTLET_START,
+ _alpm_strtrim(line + slen), NULL);
/* "DONE <ret code>" */
- } else if((strlen(line) > strlen(SCRIPTLET_DONE)) && !strncmp(line, SCRIPTLET_DONE, strlen(SCRIPTLET_DONE))) {
- EVENT(trans, PM_TRANS_EVT_SCRIPTLET_DONE, (void*)atol(_alpm_strtrim(line + strlen(SCRIPTLET_DONE))), NULL);
+ } else if((strlen(line) > dlen) &&
+ !strncmp(line, SCRIPTLET_DONE, dlen)) {
+ EVENT(trans, PM_TRANS_EVT_SCRIPTLET_DONE,
+ (void *)atol(_alpm_strtrim(line + dlen)),
+ NULL);
} else {
_alpm_strtrim(line);
/* log our script output */
alpm_logaction(line);
- EVENT(trans, PM_TRANS_EVT_SCRIPTLET_INFO, line, NULL);
+ EVENT(trans, PM_TRANS_EVT_SCRIPTLET_INFO,
+ line, NULL);
}
}
pclose(pp);
exit(0);
} else {
if(waitpid(pid, 0, 0) == -1) {
- _alpm_log(PM_LOG_ERROR, _("call to waitpid failed (%s)"), strerror(errno));
+ _alpm_log(PM_LOG_ERROR,
+ _("call to waitpid failed (%s)"),
+ strerror(errno));
retval = 1;
goto cleanup;
}
@@ -529,14 +626,16 @@
cleanup:
if(strlen(tmpdir) && _alpm_rmrf(tmpdir)) {
- _alpm_log(PM_LOG_WARNING, _("could not remove tmpdir %s"), tmpdir);
+ _alpm_log(PM_LOG_WARNING,
+ _("could not remove tmpdir %s"),
+ tmpdir);
}
if(strlen(cwd)) {
chdir(cwd);
}
return(retval);
-}
+} /* Thank goddess, I'm through. */
#ifndef __sun__
static long long get_freespace()
@@ -584,23 +683,16 @@
}
}
freespace = get_freespace();
- _alpm_log(PM_LOG_DEBUG, _("check_freespace: total pkg size: %lld, disk space: %lld"), pkgsize, freespace);
+ _alpm_log(PM_LOG_DEBUG,
+ _("check_freespace: total pkg size: %lld, disk space: %lld"),
+ pkgsize, freespace);
if(pkgsize > freespace) {
if(data) {
- long long *ptr;
- if((ptr = (long long*)malloc(sizeof(long long)))==NULL) {
- _alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %d bytes"), sizeof(long long));
- pm_errno = PM_ERR_MEMORY;
- return(-1);
- }
+ long long *ptr = pmalloc(sizeof(long long));
*ptr = pkgsize;
*data = alpm_list_add(*data, ptr);
- if((ptr = (long long*)malloc(sizeof(long long)))==NULL) {
- _alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %d bytes"), sizeof(long long));
- FREELIST(*data);
- pm_errno = PM_ERR_MEMORY;
- return(-1);
- }
+
+ ptr = pmalloc(sizeof(long long));
*ptr = freespace;
*data = alpm_list_add(*data, ptr);
}
@@ -621,8 +713,8 @@
struct tm *lt;
lt = localtime(&t);
sprintf(buffer, "%4d%02d%02d%02d%02d%02d",
- lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday,
- lt->tm_hour, lt->tm_min, lt->tm_sec);
+ lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday,
+ lt->tm_hour, lt->tm_min, lt->tm_sec);
buffer[14] = '\0';
}
}
diff -Naur pacman-lib.old/lib/libalpm/util.h pacman-lib/lib/libalpm/util.h
--- pacman-lib.old/lib/libalpm/util.h 2007-01-24 16:09:16.000000000 +0100
+++ pacman-lib/lib/libalpm/util.h 2007-01-24 16:10:13.000000000 +0100
@@ -43,7 +43,9 @@
s1[(len)-1] = 0; \
} while(0)
-#define ARCHIVE_EXTRACT_FLAGS ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME
+#define ARCHIVE_EXTRACT_FLAGS (ARCHIVE_EXTRACT_OWNER \
+ | ARCHIVE_EXTRACT_PERM \
+ | ARCHIVE_EXTRACT_TIME)
#ifdef ENABLE_NLS
#define _(str) dgettext ("libalpm", str)
@@ -54,18 +56,25 @@
#define SCRIPTLET_START "START "
#define SCRIPTLET_DONE "DONE "
+void *pmalloc(size_t s);
+void *pcalloc(size_t e, size_t s);
+void *prealloc(void *p, size_t s);
+char *pstrdup(const char *s);
+void *palloca(size_t s);
int _alpm_makepath(char *path);
-int _alpm_copyfile(char *src, char *dest);
+int _alpm_copyfile(const char *src, const char *dest);
char *_alpm_strtoupper(char *str);
char *_alpm_strtrim(char *str);
-int _alpm_lckmk(char *file);
-int _alpm_lckrm(char *file);
+int _alpm_lckmk(const char *file);
+int _alpm_lckrm(const char *file);
int _alpm_unpack(const char *archive, const char *prefix, const char *fn);
-int _alpm_rmrf(char *path);
-int _alpm_logaction(unsigned short usesyslog, FILE *f, const char *str);
+int _alpm_rmrf(const char *path);
+int _alpm_logaction(unsigned char usesyslog, FILE *f, const char *str);
int _alpm_ldconfig(char *root);
#ifdef _ALPM_TRANS_H
-int _alpm_runscriptlet(char *util, char *installfn, char *script, char *ver, char *oldver, pmtrans_t *trans);
+int _alpm_runscriptlet(const char *util, const char *installfn,
+ const char *script, const char *ver,
+ const char *oldver, pmtrans_t *trans);
#ifndef __sun__
int _alpm_check_freespace(pmtrans_t *trans, alpm_list_t **data);
#endif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://archlinux.org/pipermail/pacman-dev/attachments/20070124/e62c443e/attachment.pgp>
More information about the pacman-dev
mailing list