/* * "$Id$" * * "Secure" file removal function for the Common UNIX Printing System (CUPS). * * Copyright 2007 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright * law. Distribution and use rights are outlined in the file "LICENSE.txt" * "LICENSE" which should have been included with this file. If this * file is missing or damaged, see the license at "http://www.cups.org/". * * Contents: * * cupsdRemoveFile() - Remove a file using the 7-pass US DoD method. * overwrite_data() - Overwrite the data in a file. */ /* * Include necessary headers... */ #include "cupsd.h" #ifdef HAVE_REMOVEFILE # include #else static int overwrite_data(int fd, const char *buffer, int bufsize, int filesize); #endif /* HAVE_REMOVEFILE */ /* * 'cupsdRemoveFile()' - Remove a file using the 7-pass US DoD method. */ int /* O - 0 on success, -1 on error */ cupsdRemoveFile(const char *filename) /* I - File to remove */ { #ifdef HAVE_REMOVEFILE int ret; /* Return value */ removefile_state_t s; /* Remove state variable */ s = removefile_state_alloc(); ret = removefile(filename, s, REMOVEFILE_SECURE_7_PASS); removefile_state_free(s); return (ret); #else int fd; /* File descriptor */ struct stat info; /* File information */ char buffer[512]; /* Data buffer */ int i; /* Looping var */ /* * First open the file for writing in exclusive mode. */ if ((fd = open(filename, O_WRONLY | O_EXCL)) < 0) return (-1); /* * Delete the file now - it will still be around as long as the file is * open... */ unlink(filename); /* * Then get the file size... */ if (fstat(fd, &info)) { close(fd); return (-1); } /* * Overwrite the file 7 times with 0xF6, 0x00, 0xFF, random, 0x00, 0xFF, * and more random data. */ memset(buffer, 0xF6, sizeof(buffer)); if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) { close(fd); return (-1); } memset(buffer, 0x00, sizeof(buffer)); if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) { close(fd); return (-1); } memset(buffer, 0xFF, sizeof(buffer)); if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) { close(fd); return (-1); } for (i = 0; i < sizeof(buffer); i ++) buffer[i] = rand(); if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) { close(fd); return (-1); } memset(buffer, 0x00, sizeof(buffer)); if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) { close(fd); return (-1); } memset(buffer, 0xFF, sizeof(buffer)); if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) { close(fd); return (-1); } for (i = 0; i < sizeof(buffer); i ++) buffer[i] = rand(); if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) { close(fd); return (-1); } /* * Whew! Close the file (which will lead to the actual deletion) and * return success... */ close(fd); return (0); #endif /* HAVE_REMOVEFILE */ } #ifndef HAVE_REMOVEFILE /* * 'overwrite_data()' - Overwrite the data in a file. */ static int /* O - 0 on success, -1 on error */ overwrite_data(int fd, /* I - File descriptor */ const char *buffer, /* I - Buffer to write */ int bufsize, /* I - Size of buffer */ int filesize) /* I - Size of file */ { int bytes; /* Bytes to write/written */ /* * Start at the beginning of the file... */ if (lseek(fd, 0, SEEK_SET) < 0) return (-1); /* * Fill the file with the provided data... */ while (filesize > 0) { if (filesize > bufsize) bytes = bufsize; else bytes = filesize; if ((bytes = write(fd, buffer, bytes)) < 0) return (-1); filesize -= bytes; } /* * Force the changes to disk... */ return (fsync(fd)); } #endif /* HAVE_REMOVEFILE */ #ifdef TEST # define testmain main int testmain(void) { FILE *fp; fp = fopen("testfile.secure", "w"); fputs("Hello, World!\n", fp); fputs("Now is the time for all good men to come to the aid of their " "country.\n", fp); fclose(fp); if (cupsdRemoveFile("testfile.secure")) { printf("cupsdRemoveFile: FAIL (%s)\n", strerror(errno)); return (1); } else { puts("cupsdRemoveFile: PASS"); return (0); } } #endif /* TEST */ /* * End of "$Id$". */