PERFORCE change 178990 for review
Garrett Cooper
gcooper at FreeBSD.org
Mon May 31 00:59:55 UTC 2010
http://p4web.freebsd.org/@@178990?ac=10
Change 178990 by gcooper at gcooper-bayonetta on 2010/05/31 00:59:14
1. Properly check for result from new_plist_entry instead of assuming
it will always pass.
2. Use for-loops instead of while-loops wherever easily acceptable.
3. Use explicit branch test values.
4. Avoid a NULL pointer deref in new_plist_entry if the malloc(3) fails.
5. delete_hierarchy:
i. Unify return code mechanism.
ii. Avoid some NULL pointer derefs in the nukedirs loop.
iii. Don't leak memory between each time that dir is strdup(3)'ed.
5. style(9)-ize code.
Affected files ...
.. //depot/projects/soc2007/gcooper-pkg_install-enhancements-simplified/lib/libpkg/plist.c#8 edit
Differences ...
==== //depot/projects/soc2007/gcooper-pkg_install-enhancements-simplified/lib/libpkg/plist.c#8 (text+ko) ====
@@ -38,96 +38,102 @@
void
add_plist(Package *p, plist_t type, const char *arg)
{
- PackingList tmp;
+ PackingList tmp;
+
+ tmp = new_plist_entry();
+
+ if (tmp != NULL) {
+
+ tmp->name = copy_string(arg);
+ tmp->type = type;
+
+ if (!p->head)
+ p->head = p->tail = tmp;
+ else {
+ tmp->prev = p->tail;
+ p->tail->next = tmp;
+ p->tail = tmp;
+ }
+ switch (type) {
+ case PLIST_NAME:
+ p->name = tmp->name;
+ break;
- tmp = new_plist_entry();
- tmp->name = copy_string(arg);
- tmp->type = type;
+ case PLIST_ORIGIN:
+ p->origin = tmp->name;
+ break;
- if (!p->head)
- p->head = p->tail = tmp;
- else {
- tmp->prev = p->tail;
- p->tail->next = tmp;
- p->tail = tmp;
- }
- switch (type) {
- case PLIST_NAME:
- p->name = tmp->name;
- break;
+ default:
+ break;
+ }
- case PLIST_ORIGIN:
- p->origin = tmp->name;
- break;
+ }
- default:
- break;
- }
}
void
add_plist_top(Package *p, plist_t type, const char *arg)
{
- PackingList tmp;
+ PackingList tmp;
+
+ tmp = new_plist_entry();
+
+ if (tmp != NULL) {
+
+ tmp->name = copy_string(arg);
+ tmp->type = type;
+
+ if (!p->head)
+ p->head = p->tail = tmp;
+ else {
+ tmp->next = p->head;
+ p->head->prev = tmp;
+ p->head = tmp;
+ }
- tmp = new_plist_entry();
- tmp->name = copy_string(arg);
- tmp->type = type;
+ }
- if (!p->head)
- p->head = p->tail = tmp;
- else {
- tmp->next = p->head;
- p->head->prev = tmp;
- p->head = tmp;
- }
}
/* Return the last (most recent) entry in a packing list */
PackingList
last_plist(Package *p)
{
- return p->tail;
+ return (p->tail);
}
/* Mark all items in a packing list to prevent iteration over them */
void
mark_plist(Package *pkg)
{
- PackingList p = pkg->head;
+ PackingList p;
- while (p) {
- p->marked = TRUE;
- p = p->next;
- }
+ for (p = pkg->head; p != NULL; p = p->next)
+ p->marked = TRUE;
}
/* Find a given item in a packing list and, if so, return it (else NULL) */
PackingList
find_plist(Package *pkg, plist_t type)
{
- PackingList p = pkg->head;
+ PackingList p;
- while (p) {
- if (p->type == type)
- return p;
- p = p->next;
- }
- return NULL;
+ for (p = pkg->head; p != NULL; p = p->next)
+ if (p->type == type)
+ return (p);
+ return (NULL);
}
/* Look for a specific boolean option argument in the list */
char *
find_plist_option(Package *pkg, const char *name)
{
- PackingList p = pkg->head;
+ PackingList p;
- while (p) {
- if (p->type == PLIST_OPTION && !strcmp(p->name, name))
- return p->name;
- p = p->next;
- }
- return NULL;
+ for (p = pkg->head; p != NULL; p = p->next)
+ if (p->type == PLIST_OPTION && !strcmp(p->name, name))
+ return (p->name);
+ return (NULL);
}
/*
@@ -137,56 +143,66 @@
void
delete_plist(Package *pkg, Boolean all, plist_t type, const char *name)
{
- PackingList p = pkg->head;
+ PackingList p = pkg->head;
+
+ while (p != NULL) {
+
+ PackingList pnext = p->next;
+
+ if (p->type == type && (!name || !strcmp(name, p->name))) {
+
+ free(p->name);
+
+ if (p->prev)
+ p->prev->next = pnext;
+ else
+ pkg->head = pnext;
+ if (pnext != NULL)
+ pnext->prev = p->prev;
+ else
+ pkg->tail = p->prev;
+ free(p);
+
+ if (all == FALSE)
+ return;
+ p = pnext;
- while (p) {
- PackingList pnext = p->next;
+ } else
+ p = p->next;
- if (p->type == type && (!name || !strcmp(name, p->name))) {
- free(p->name);
- if (p->prev)
- p->prev->next = pnext;
- else
- pkg->head = pnext;
- if (pnext)
- pnext->prev = p->prev;
- else
- pkg->tail = p->prev;
- free(p);
- if (!all)
- return;
- p = pnext;
}
- else
- p = p->next;
- }
+
}
/* Allocate a new packing list entry */
PackingList
new_plist_entry(void)
{
- PackingList ret;
+ PackingList ret;
- ret = (PackingList)malloc(sizeof(struct _plist));
- bzero(ret, sizeof(struct _plist));
- return ret;
+ ret = (PackingList)malloc(sizeof(struct _plist));
+ if (ret != NULL)
+ bzero(ret, sizeof(struct _plist));
+ return (ret);
}
/* Free an entire packing list */
void
free_plist(Package *pkg)
{
- PackingList p = pkg->head;
+ PackingList p;
+
+ for (p = pkg->head; p != NULL; ) {
+
+ PackingList p1 = p->next;
+
+ free(p->name);
+ free(p);
+ p = p1;
+ }
- while (p) {
- PackingList p1 = p->next;
+ pkg->head = pkg->tail = NULL;
- free(p->name);
- free(p);
- p = p1;
- }
- pkg->head = pkg->tail = NULL;
}
/*
@@ -196,82 +212,86 @@
int
plist_cmd(const char *s, char **arg)
{
- /* XXX (gcooper): this can blow up really quickly with the recent
- * modifications made to read_plist, provided a sufficiently large list. */
- char cmd[FILENAME_MAX + 20]; /* 20 == fudge for max cmd len */
- char *cp;
- const char *sp;
+ /*
+ * XXX (gcooper): this can blow up really quickly with the recent
+ * modifications made to read_plist, provided a sufficiently large
+ * list.
+ */
+ char cmd[FILENAME_MAX + 20]; /* 20 == fudge for max cmd len */
+ char *cp;
+ const char *sp;
- /*
- * FIXME (gcooper): this should be dynamic according to whatever's passed
- * in.
- */
- if (strlcpy(cmd, s, sizeof(cmd)) >= sizeof(cmd)) {
- warnx("%s: line '%s' exceeds set limits", __func__, s);
- errno = EINVAL;
- return -1;
- }
- str_lowercase(cmd);
- cp = cmd;
- sp = s;
- while (*cp) {
- if (isspace(*cp)) {
- *cp = '\0';
- while (isspace(*sp)) /* Never sure if macro, increment later */
- ++sp;
- break;
+ /*
+ * FIXME (gcooper): this should be dynamic according to whatever's
+ * passed in.
+ */
+ if (strlcpy(cmd, s, sizeof(cmd)) >= sizeof(cmd)) {
+ warnx("%s: line '%s' exceeds set limits", __func__, s);
+ errno = EINVAL;
+ return (-1);
}
- ++cp, ++sp;
- }
- if (arg)
- *arg = (char *)sp;
- if (!strcmp(cmd, "cwd"))
- return PLIST_CWD;
- else if (!strcmp(cmd, "srcdir"))
- return PLIST_SRC;
- else if (!strcmp(cmd, "cd"))
- return PLIST_CWD;
- else if (!strcmp(cmd, "exec"))
- return PLIST_CMD;
- else if (!strcmp(cmd, "unexec"))
- return PLIST_UNEXEC;
- else if (!strcmp(cmd, "mode"))
- return PLIST_CHMOD;
- else if (!strcmp(cmd, "owner"))
- return PLIST_CHOWN;
- else if (!strcmp(cmd, "group"))
- return PLIST_CHGRP;
- else if (!strcmp(cmd, "noinst"))
- return PLIST_NOINST;
- else if (!strcmp(cmd, "comment")) {
- if (!strncmp(*arg, "ORIGIN:", 7)) {
- *arg += 7;
- return PLIST_ORIGIN;
- } else if (!strncmp(*arg, "DEPORIGIN:", 10)) {
- *arg += 10;
- return PLIST_DEPORIGIN;
+ str_lowercase(cmd);
+ cp = cmd;
+ sp = s;
+ while (*cp != '\0') {
+ if (isspace(*cp)) {
+ *cp = '\0';
+ /* Never sure if macro, increment later */
+ while (isspace(*sp++)) ;
+ break;
+ }
+ cp++;
+ sp++;
}
- return PLIST_COMMENT;
- } else if (!strcmp(cmd, "ignore"))
- return PLIST_IGNORE;
- else if (!strcmp(cmd, "ignore_inst"))
- return PLIST_IGNORE_INST;
- else if (!strcmp(cmd, "name"))
- return PLIST_NAME;
- else if (!strcmp(cmd, "display"))
- return PLIST_DISPLAY;
- else if (!strcmp(cmd, "pkgdep"))
- return PLIST_PKGDEP;
- else if (!strcmp(cmd, "conflicts"))
- return PLIST_CONFLICTS;
- else if (!strcmp(cmd, "mtree"))
- return PLIST_MTREE;
- else if (!strcmp(cmd, "dirrm"))
- return PLIST_DIR_RM;
- else if (!strcmp(cmd, "option"))
- return PLIST_OPTION;
- else
- return -1;
+ if (arg)
+ *arg = (char *)sp;
+ if (!strcmp(cmd, "cwd"))
+ return (PLIST_CWD);
+ else if (!strcmp(cmd, "srcdir"))
+ return (PLIST_SRC);
+ else if (!strcmp(cmd, "cd"))
+ return (PLIST_CWD);
+ else if (!strcmp(cmd, "exec"))
+ return (PLIST_CMD);
+ else if (!strcmp(cmd, "unexec"))
+ return (PLIST_UNEXEC);
+ else if (!strcmp(cmd, "mode"))
+ return (PLIST_CHMOD);
+ else if (!strcmp(cmd, "owner"))
+ return (PLIST_CHOWN);
+ else if (!strcmp(cmd, "group"))
+ return (PLIST_CHGRP);
+ else if (!strcmp(cmd, "noinst"))
+ return (PLIST_NOINST);
+ else if (!strcmp(cmd, "comment")) {
+ if (!strncmp(*arg, "ORIGIN:", 7)) {
+ *arg += 7;
+ return (PLIST_ORIGIN);
+ } else if (!strncmp(*arg, "DEPORIGIN:", 10)) {
+ *arg += 10;
+ return (PLIST_DEPORIGIN);
+ }
+ return (PLIST_COMMENT);
+ } else if (!strcmp(cmd, "ignore"))
+ return (PLIST_IGNORE);
+ else if (!strcmp(cmd, "ignore_inst"))
+ return (PLIST_IGNORE_INST);
+ else if (!strcmp(cmd, "name"))
+ return (PLIST_NAME);
+ else if (!strcmp(cmd, "display"))
+ return (PLIST_DISPLAY);
+ else if (!strcmp(cmd, "pkgdep"))
+ return (PLIST_PKGDEP);
+ else if (!strcmp(cmd, "conflicts"))
+ return (PLIST_CONFLICTS);
+ else if (!strcmp(cmd, "mtree"))
+ return (PLIST_MTREE);
+ else if (!strcmp(cmd, "dirrm"))
+ return (PLIST_DIR_RM);
+ else if (!strcmp(cmd, "option"))
+ return (PLIST_OPTION);
+ else
+ return (-1);
}
/* Read a packing list from a file */
@@ -288,7 +308,7 @@
int serrno;
int major;
int minor;
- int rc = -1;
+ int retcode = -1;
off_t end_off;
size_t len;
@@ -303,10 +323,10 @@
0)) != NULL) {
end_off = sb.st_size;
- rc = 0;
+ retcode = 0;
start = contents_map;
- while (rc == 0 && 0 < end_off) {
+ while (retcode == 0 && 0 < end_off) {
end = strchr(start, '\n');
/* No trailing newlines -- look for '\0'. */
@@ -324,7 +344,7 @@
cmd_buf = malloc(end-start+1);
if (cmd_buf == NULL)
- rc = -1;
+ retcode = -1;
else {
strlcpy(cmd_buf, start, end-start+1);
@@ -339,14 +359,14 @@
/* Empty line. */
if (len == 0) {
errno = EINVAL;
- rc = -1;
+ retcode = -1;
} else
cp = cmd_buf;
}
/* A plist command directive */
- if (rc == 0 && *start == CMD_CHAR) {
+ if (retcode == 0 && *start == CMD_CHAR) {
cmd = plist_cmd(cmd_buf+1, &cp);
@@ -354,15 +374,16 @@
warnx("%s: unknown command '%s' "
"(package tools out of date?)",
__func__, start);
- rc = -1;
+ retcode = -1;
} else if (*cp == '\0') {
cp = NULL;
if (cmd == PLIST_PKGDEP) {
- warnx("corrupted record (pkgdep line "
- "without argument), ignoring");
+ warnx("corrupted record "
+ "(pkgdep line without "
+ "argument), ignoring");
errno = EINVAL;
- cmd = rc = -1;
+ cmd = retcode = -1;
}
}
@@ -388,7 +409,7 @@
if (pkg->fmtver_maj >
PLIST_FMT_VER_MAJOR) {
errno = EINVAL;
- rc = -1;
+ retcode = -1;
}
}
@@ -397,14 +418,14 @@
}
/* A file manifest item */
- else if (rc == 0)
+ else if (retcode == 0)
cmd = PLIST_FILE;
/*
* Winner, winner, chicken dinner.. we have a working
* command!
*/
- if (rc == 0) {
+ if (retcode == 0) {
add_plist(pkg, cmd, cp);
start = end;
@@ -436,14 +457,14 @@
errno = serrno;
}
- if (rc == -1 && cmd_buf != NULL) {
+ if (retcode == -1 && cmd_buf != NULL) {
serrno = errno;
free(cmd_buf);
if (serrno == 0)
errno = serrno;
}
- return rc;
+ return (retcode);
}
@@ -451,8 +472,9 @@
int
write_plist(Package *pkg, FILE *fp)
{
+
PackingList plist;
- int rc = 0;
+ int retcode = 0;
for (plist = pkg->head; plist != NULL; plist = plist->next) {
@@ -543,19 +565,20 @@
break;
case PLIST_DEPORIGIN:
- fprintf(fp, "%ccomment DEPORIGIN:%s\n", CMD_CHAR, plist->name);
+ fprintf(fp, "%ccomment DEPORIGIN:%s\n", CMD_CHAR,
+ plist->name);
break;
default:
warnx("%s: unknown command type %d (%s)", __func__,
plist->type, plist->name);
- rc = -1;
+ retcode = -1;
break;
}
}
- return rc;
+ return (retcode);
}
@@ -568,121 +591,166 @@
int
delete_package(Boolean ign_err, Boolean nukedirs, Package *pkg)
{
- PackingList p;
- const char *Where = ".", *last_file = "";
- Boolean fail = FALSE;
- Boolean preserve;
- char tmp[FILENAME_MAX], *name = NULL;
- char *prefix = NULL;
+ PackingList p;
+ Boolean fail = FALSE;
+ Boolean preserve;
+ char tmp[FILENAME_MAX];
+ char *name = NULL;
+ char *prefix = NULL;
+ const char *Where = ".";
+ const char *last_file = "";
+
+ preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE;
+
+ for (p = pkg->head; p != NULL; p = p->next) {
+
+ switch (p->type) {
+ case PLIST_NAME:
+ name = p->name;
+ break;
+
+ case PLIST_IGNORE:
+ p = p->next;
+ break;
+
+ case PLIST_CWD:
+ if (prefix == NULL)
+ prefix = p->name;
+ Where = (p->name == NULL) ? prefix : p->name;
+ if (Verbose)
+ printf("Change working directory to %s\n",
+ Where);
+ break;
+
+ case PLIST_UNEXEC:
+ format_cmd(tmp, FILENAME_MAX, p->name, Where,
+ last_file);
+ if (Verbose)
+ printf("Execute '%s'\n", tmp);
+ if (!Fake && system(tmp)) {
+ warnx("unexec command for '%s' failed", tmp);
+ fail = -1;
+ }
+ break;
+
+ /*
+ * TODO: break up this logic into more easily digestable
+ * blocks, if not to improve indentation, at least to improve
+ * modularity and testability via whitebox tests.
+ */
+ case PLIST_FILE:
+ last_file = p->name;
+ sprintf(tmp, "%s/%s", Where, p->name);
+ /* TODO: set EISDIR */
+ if (isdir(tmp) && fexists(tmp) && !issymlink(tmp)) {
+ warnx("cannot delete specified file '%s' - it "
+ "is a directory!\nthis packing list is "
+ "incorrect - ignoring delete request",
+ tmp);
+ } else {
+ if (p->next &&
+ p->next->type == PLIST_COMMENT &&
+ strncmp(p->next->name, "MD5:", 4) == 0) {
+ char *cp = NULL, buf[33];
+
+ /*
+ * For packing lists whose version is
+ * 1.1 or greater, the md5 hash for a
+ * symlink is calculated on the string
+ * returned by readlink().
+ */
+ if (issymlink(tmp) &&
+ verscmp(pkg, 1, 0) > 0) {
+ char linkbuf[PATHNAME_MAX];
+ int len;
+
+ if ((len = readlink(tmp,
+ linkbuf, sizeof(linkbuf))) > 0)
+ cp = MD5Data((unsigned char *)linkbuf, len, buf);
+ } else if (isfile(tmp) ||
+ verscmp(pkg, 1, 1) < 0)
+ cp = MD5File(tmp, buf);
+
+ if (cp != NULL) {
+
+ /* Mismatch? */
+ if (strcmp(cp,
+ p->next->name + 4) != 0) {
+ warnx("'%s' fails "
+ "original MD5 "
+ "checksum - %s",
+ tmp,
+ (Force ?
+ "deleted anyway." :
+ "not deleted."));
+ if (!Force) {
+ fail = -1;
+ continue;
+ }
+
+ }
- preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE;
- for (p = pkg->head; p; p = p->next) {
- switch (p->type) {
- case PLIST_NAME:
- name = p->name;
- break;
+ }
- case PLIST_IGNORE:
- p = p->next;
- break;
+ }
- case PLIST_CWD:
- if (prefix == NULL)
- prefix = p->name;
- Where = (p->name == NULL) ? prefix : p->name;
- if (Verbose)
- printf("Change working directory to %s\n", Where);
- break;
+ if (Verbose)
+ printf("Delete file %s\n", tmp);
+ if (!Fake) {
+ if (delete_hierarchy(tmp, ign_err,
+ nukedirs))
+ fail = -1;
+ if (preserve && name) {
+ char tmp2[FILENAME_MAX];
+
+ if (make_preserve_name(tmp2,
+ sizeof(tmp2), name, tmp)) {
- case PLIST_UNEXEC:
- format_cmd(tmp, FILENAME_MAX, p->name, Where, last_file);
- if (Verbose)
- printf("Execute '%s'\n", tmp);
- if (!Fake && system(tmp)) {
- warnx("unexec command for '%s' failed", tmp);
- fail = -1;
- }
- break;
+ if (fexists(tmp2)) {
+ if (rename(tmp2, tmp))
+ warn("preserve: unable to restore %s as %s", tmp2, tmp);
+ }
- case PLIST_FILE:
- last_file = p->name;
- sprintf(tmp, "%s/%s", Where, p->name);
- if (isdir(tmp) && fexists(tmp) && !issymlink(tmp)) {
- warnx("cannot delete specified file '%s' - it is a directory!\n"
- "this packing list is incorrect - ignoring delete request", tmp);
- }
- else {
- if (p->next && p->next->type == PLIST_COMMENT && !strncmp(p->next->name, "MD5:", 4)) {
- char *cp = NULL, buf[33];
+ }
- /*
- * For packing lists whose version is 1.1 or greater, the
- * md5 hash for a symlink is calculated on the string
- * returned by readlink().
- */
- if (issymlink(tmp) && verscmp(pkg, 1, 0) > 0) {
- int len;
- char linkbuf[FILENAME_MAX];
+ }
- if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0)
- cp = MD5Data((unsigned char *)linkbuf, len, buf);
- } else if (isfile(tmp) || verscmp(pkg, 1, 1) < 0)
- cp = MD5File(tmp, buf);
+ }
- if (cp != NULL) {
- /* Mismatch? */
- if (strcmp(cp, p->next->name + 4)) {
- warnx("'%s' fails original MD5 checksum - %s",
- tmp, Force ? "deleted anyway." : "not deleted.");
- if (!Force) {
- fail = -1;
- continue;
- }
}
- }
- }
- if (Verbose)
- printf("Delete file %s\n", tmp);
- if (!Fake) {
- if (delete_hierarchy(tmp, ign_err, nukedirs))
- fail = -1;
- if (preserve && name) {
- char tmp2[FILENAME_MAX];
-
- if (make_preserve_name(tmp2, FILENAME_MAX, name, tmp)) {
- if (fexists(tmp2)) {
- if (rename(tmp2, tmp))
- warn("preserve: unable to restore %s as %s",
- tmp2, tmp);
- }
+
+ break;
+
+ case PLIST_DIR_RM:
+ sprintf(tmp, "%s/%s", Where, p->name);
+
+ if (!isdir(tmp) && fexists(tmp)) {
+ warnx("cannot delete specified directory '%s' "
+ "- it is a file!\nthis packing list is "
+ "incorrect - ignoring delete request",
+ tmp);
+ } else {
+ if (Verbose)
+ printf("Deleting directory %s\n", tmp);
+ if (Fake == FALSE &&
+ delete_hierarchy(tmp, ign_err, FALSE)) {
+ warnx("unable to completely remove "
+ "directory '%s'", tmp);
+ fail = -1;
+ }
}
- }
- }
- }
- break;
+
+ last_file = p->name;
+ break;
- case PLIST_DIR_RM:
- sprintf(tmp, "%s/%s", Where, p->name);
- if (!isdir(tmp) && fexists(tmp)) {
- warnx("cannot delete specified directory '%s' - it is a file!\n"
- "this packing list is incorrect - ignoring delete request", tmp);
- }
- else {
- if (Verbose)
- printf("Delete directory %s\n", tmp);
- if (!Fake && delete_hierarchy(tmp, ign_err, FALSE)) {
- warnx("unable to completely remove directory '%s'", tmp);
- fail = -1;
+ default:
+ break;
}
- }
- last_file = p->name;
- break;
- default:
- break;
}
- }
- return fail;
+
+ return (fail);
+
}
#ifdef DEBUG
@@ -697,45 +765,73 @@
int
delete_hierarchy(const char *dir, Boolean ign_err, Boolean nukedirs)
{
- char *cp1, *cp2;
+
+ char *cp1, *cp2;
+ int retcode = 1; /* 1 -> retcode not touched. */
+
+ if (!fexists(dir) && !issymlink(dir)) {
+ if (ign_err == FALSE) {
+ warnx("%s '%s' doesn't exist",
+ isdir(dir) ? "directory" : "file", dir);
+ retcode = -1;
+ }
+ } else if (nukedirs) {
+ if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""),
+ dir))
+ retcode = -1;
+ } else if (isdir(dir) && !issymlink(dir))
+ if (RMDIR(dir) && !ign_err)
+ retcode = -1;
+ else
+ if (REMOVE(dir, ign_err))
+ retcode = -1;
+
+ /*
+ * If we got this far, strdup the paths as is required directly
+ * below.
+ */
+ if (retcode == 1) {
- cp1 = cp2 = strdup(dir);
- if (!fexists(dir) && !issymlink(dir)) {
- if (!ign_err)
- warnx("%s '%s' doesn't exist",
- isdir(dir) ? "directory" : "file", dir);
- return !ign_err;
- }
- else if (nukedirs) {
- if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""), dir))
- return 1;
- }
- else if (isdir(dir) && !issymlink(dir)) {
- if (RMDIR(dir) && !ign_err)
- return 1;
- }
- else {
- if (REMOVE(dir, ign_err))
- return 1;
- }
+ cp1 = cp2 = strdup(dir);
+ if (cp1 == NULL || cp2 == NULL)
+ retcode = -1;
- if (!nukedirs)
- return 0;
- while (cp2) {
- if ((cp2 = strrchr(cp1, '/')) != NULL)
- *cp2 = '\0';
- if (!isemptydir(dir))
- return 0;
- if (RMDIR(dir) && !ign_err) {
- if (!fexists(dir))
- warnx("directory '%s' doesn't exist", dir);
- else
- return 1;
}
- /* back up the pathname one component */
- if (cp2) {
- cp1 = strdup(dir);
+
+ if (retcode == 1) {
+
+ retcode = 0;
+
+ if (nukedirs == TRUE) {
+
+ while (cp2 != NULL && retcode == 0) {
+
+ if ((cp2 = strrchr(cp1, '/')) != NULL)
+ *cp2 = '\0';
+ if (!isemptydir(dir))
+ retcode == 0;
+ if (RMDIR(dir) && !ign_err) {
+
+ if (!fexists(dir))
+ warnx("directory '%s' doesn't "
+ "exist", dir);
+ else
+ retcode = -1;
+
+ }
+
+ /* back up the pathname one component */
+ if (cp2 != NULL) {
+ free(cp1);
+ cp1 = strdup(dir);
+ if (cp1 == NULL)
+ retcode = -1;
+ }
+
+ }
+
}
- }
- return 0;
+
+ return (retcode);
+
}
More information about the p4-projects
mailing list