/* $Id: backup.c,v 1.6 2002/06/23 20:28:31 richdawe Exp $ */ /* * backup.c - Backup functions for pakke * Copyright (C) 2002 by Richard Dawe * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "common.h" #include #include #include #include #include #include /* libpakke includes */ #include #include #include static char BACKUP_SUFFIX[] = ".old"; /* ------------------- * - backup_get_path - * ------------------- */ /* * backup_get_path() returns a path for backing up package files. It is * a combination of the 'backup_prefix', the package DSM or manifest name * and 'BACKUP_SUFFIX'. * * On success, a pointer to a static buffer is returned - make a copy of * the string if you need to modify it. On failure, NULL is returned. * * The returned string is guaranteed to have a trailing forward slash. */ const char * backup_get_path (PACKAGE_INFO *package, const char *backup_prefix) { static char buf[PATH_MAX]; char *name = NULL; size_t len = 0; /* Use DSM or manifest name? */ if (strlen(package->dsm_name) != 0) name = package->dsm_name; else if (strlen(package->manifest) != 0) name = package->manifest; else return(NULL); /* Copy prefix for munging */ strcpy(buf, backup_prefix); forwardslashify(buf); /* Calculate length of path */ len = strlen(buf); if (!ends_with_slash(buf)) len++; len += strlen(name); len += strlen(BACKUP_SUFFIX); len++; /* for trailing slash */ /* Too long */ if (len > PATH_MAX) return(NULL); /* Build string. */ if (!ends_with_slash(buf)) strcat(buf, "/"); strcat(buf, name); strcat(buf, BACKUP_SUFFIX); strcat(buf, "/"); forwardslashify(buf); return(buf); } /* --------------- * - backup_file - * --------------- */ /* * backup_package_file() copies the specified 'path' from 'prefix' into * 'backup_path'. 'prefix' is the directory the package was originally * installed in; 'path' is the relative path under 'prefix'; 'backup_path' * is the backup path for that package, as returned by backup_get_path(). * * On success, 0 is returned. On failure, -1 is returned and 'errno' will * be set appropriately. */ int backup_file (const char *path, const char *prefix, const char *backup_path) { char src_path[PATH_MAX]; char dest_path[PATH_MAX]; char dest_dir[PATH_MAX]; mode_t mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; int src_is_dir; int ret = 0; char *p = NULL; /* Make sure the backup prefix exists. */ ret = recursive_mkdir(backup_path, mode); if ((ret != 0) && (errno != EEXIST)) { /* Pass on errno to caller */ return(-1); } /* Build paths */ strcpy(src_path, prefix); forwardslashify(src_path); if (!ends_with_slash(src_path)) strcat(src_path, "/"); strcat(src_path, path); strcpy(dest_path, backup_path); forwardslashify(dest_path); if (!ends_with_slash(dest_path)) strcat(dest_path, "/"); strcat(dest_path, path); /* Make sure source file exists. */ if (access(src_path, R_OK) != 0) { errno = ENOENT; return(-1); } /* If the source is a directory, just create it in backup directory. * Otherwise copy source to dest. */ src_is_dir = isdir(src_path); if (src_is_dir > 0) { /* Directory */ ret = recursive_mkdir(dest_path, mode); if ((ret != 0) && (errno != EEXIST)) { /* Pass on errno to caller */ return(-1); } /* OK */ ret = 0; } else if (src_is_dir == 0) { /* File */ /* Make the directory to store the file. */ strcpy(dest_dir, dest_path); p = strrchr(dest_dir, '/'); if (p != NULL) { *p = '\0'; ret = recursive_mkdir(dest_dir, mode); if ((ret != 0) && (errno != EEXIST)) { /* Pass on errno to caller */ return(-1); } } /* Copy the file */ ret = copy_file(src_path, dest_path); if (!ret) { /* TODO: Error? EIO? Does 'errno' get set? If so, pass errno through. */ ret = -1; } else { /* OK */ ret = 0; } } else { /* stat() failed - pass on errno to caller */ ret = -1; } return(ret); }