/* * loadermisc.c - miscellaneous loader functions that don't seem to fit * anywhere else (yet) (was misc.c) * JKFIXME: need to break out into reasonable files based on function * * Copyright (C) 1999, 2000, 2001, 2002 Red Hat, Inc. All rights reserved. * * 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, see . * * Author(s): Erik Troan * Matt Wilson * Michael Fulbright * Jeremy Katz */ #include #include #include #include #include #include #include #include #include #include #include "../pyanaconda/isys/log.h" #include "windows.h" int copyFileFd(int infd, char * dest, progressCB pbcb, struct progressCBdata *data, long long total) { int outfd; char buf[4096]; int i; int rc = 0; long long count = 0; outfd = open(dest, O_CREAT | O_RDWR, 0666); if (outfd < 0) { logMessage(ERROR, "failed to open %s: %m", dest); return 1; } while ((i = read(infd, buf, sizeof(buf))) > 0) { if (write(outfd, buf, i) != i) { rc = 1; break; } count += i; if (pbcb && data && total) { pbcb(data, count, total); } } close(outfd); return rc; } int copyFile(char * source, char * dest) { int infd = -1; int rc; infd = open(source, O_RDONLY); if (infd < 0) { logMessage(ERROR, "failed to open %s: %m", source); return 1; } rc = copyFileFd(infd, dest, NULL, NULL, 0); close(infd); return rc; } /** * Do "rm -rf" on the target directory. * * Returns 0 on success, nonzero otherwise (i.e. directory doesn't exist or * some of its contents couldn't be removed. * * This is copied from the util-linux-ng project. */ int recursiveRemove(int fd) { struct stat rb; DIR *dir; int rc = -1; int dfd; if (!(dir = fdopendir(fd))) { goto done; } /* fdopendir() precludes us from continuing to use the input fd */ dfd = dirfd(dir); if (fstat(dfd, &rb)) { goto done; } while(1) { struct dirent *d; errno = 0; if (!(d = readdir(dir))) { if (errno) { goto done; } break; /* end of directory */ } if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; if (d->d_type == DT_DIR) { struct stat sb; if (fstatat(dfd, d->d_name, &sb, AT_SYMLINK_NOFOLLOW)) { continue; } /* remove subdirectories if device is same as dir */ if (sb.st_dev == rb.st_dev) { int cfd; cfd = openat(dfd, d->d_name, O_RDONLY); if (cfd >= 0) { recursiveRemove(cfd); close(cfd); } } else continue; } unlinkat(dfd, d->d_name, d->d_type == DT_DIR ? AT_REMOVEDIR : 0); } rc = 0; /* success */ done: if (dir) closedir(dir); return rc; } int simpleStringCmp(const void * a, const void * b) { const char * first = *((const char **) a); const char * second = *((const char **) b); return strverscmp(first, second); }