/* * Copyright (c) 2003, 2004 Roger Seguin <roger_seguin@msn.com> * http://rmlx.dyndns.org * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ static const char *const RCSId = "$Id: wipeswp.C,v 1.4 2004/08/15 02:05:13 RogerSeguin Exp $" "\nCopyright (c) 2003, 2004 Roger Seguin <roger_seguin@msn.com," " http://rmlx.dyndns.org>"; /* Description: Wipe (zero) a swap device (either a partition or a file) Usage: wipeswp <swap device> wipeswp -h Example: Linux system shutdown #!/bin/bash SWAPS=`awk '! /^Filename/ { print $1 }' /proc/swaps` for swp in $SWAPS ; do swapoff $swp wipeswp $swp done */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <memory.h> #include <signal.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> namespace { const size_t SWPHDRLEN = 4 * 1024; // Swap header length const int PATTERN_BYTE = 0; // Swap filled with... const char *m_pcThisPrgName; FILE *m_pFSwapDev = 0; }; /**********************************************************************/ int WipeSwapPartition (char *p_pcSwapDev) /**********************************************************************/ { const size_t BUFFERSIZE = 1024 * 1024; char acBuffer[BUFFERSIZE]; m_pFSwapDev = fopen (p_pcSwapDev, "r+"); if (!m_pFSwapDev) { perror (p_pcSwapDev); return (errno); } if (fseek (m_pFSwapDev, SWPHDRLEN, SEEK_SET) < 0) { perror (p_pcSwapDev); return (errno); } memset (acBuffer, PATTERN_BYTE, BUFFERSIZE); while (fwrite (&acBuffer, 1, BUFFERSIZE, m_pFSwapDev) == BUFFERSIZE); fclose (m_pFSwapDev); sync (); return (0); } // WipeSwapPartition() /**********************************************************************/ int WipeSwapFile (char *p_pcSwapFile, off_t p_FileSize) /**********************************************************************/ /* Actually regenerate the swap file */ { char acCmd[1024]; int status; sprintf (acCmd, "/bin/dd if=/dev/zero of=%s bs=1024 count=%d;" "/sbin/mkswap -c %s", p_pcSwapFile, p_FileSize / 1024, p_pcSwapFile); status = system (acCmd); return (WEXITSTATUS (status)); } // WipeSwapFile() /**********************************************************************/ int Wipe (char *p_pcSwapDev) /**********************************************************************/ { struct stat oDevStatus; int status; status = stat (p_pcSwapDev, &oDevStatus); if (status == -1) { perror (p_pcSwapDev); return (-1); } /* Wipe swap file/partition */ if (S_ISREG (oDevStatus.st_mode) && (oDevStatus.st_size > 0)) return (WipeSwapFile (p_pcSwapDev, oDevStatus.st_size)); if (S_ISBLK (oDevStatus.st_mode)) return (WipeSwapPartition (p_pcSwapDev)); fprintf (stderr, " ** Error: %s is not a swap device\n", p_pcSwapDev); return (-1); } // Wipe() /**********************************************************************/ void Interrupt (int p_iSignal, siginfo_t *, void *) /**********************************************************************/ /* Signal handler */ { fprintf (stderr, "%s terminated by signal %d\n", m_pcThisPrgName, p_iSignal); if (m_pFSwapDev) fclose (m_pFSwapDev); sync (); exit (p_iSignal); } // Interrupt() /**********************************************************************/ const char *BaseName (const char *const p_pcFullName) /* Return the file name, leading directory stripped */ /**********************************************************************/ { const char *const pc = rindex (p_pcFullName, '/'); return (pc ? pc + 1 : p_pcFullName); } // BaseName() /**********************************************************************/ int main (int argc, char *argv[]) /**********************************************************************/ { int fError = 0, // fUsage = 0; struct sigaction oSigaction; int status; m_pcThisPrgName = BaseName (argv[0]); for (char c; (c = getopt (argc, argv, "hV")) != EOF;) switch (c) { case 'V': /* Version */ case 'h': /* Help */ fUsage = 1; break; case '?': default: fError = 1; } fUsage = (fUsage || ((optind + 1) != argc) || fError); if (fUsage) { FILE *pFOut = (fError ? stderr : stdout); fprintf (stdout, "%s\n\tWipe a swap device\n", RCSId + 5); fprintf (pFOut, "Usage:\t%s swap_device\n", m_pcThisPrgName); fprintf (pFOut, "\t%s [-h|-V]\n", m_pcThisPrgName); return (fError ? ~0 : 0); } memset (&oSigaction, 0, sizeof (oSigaction)); oSigaction.sa_sigaction = Interrupt; sigaction (SIGHUP, &oSigaction, 0); sigaction (SIGINT, &oSigaction, 0); sigaction (SIGTERM, &oSigaction, 0); status = Wipe (argv[optind]); return (status); } // main() /* $Log: wipeswp.C,v $ Revision 1.4 2004/08/15 02:05:13 RogerSeguin Revision 1.1 2003/02/05 11:48:30 RogerSeguin Initial revision */