1/* grabbag - Convenience lib for various routines common to several tools 2 * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19#if HAVE_CONFIG_H 20# include <config.h> 21#endif 22 23#if defined _MSC_VER || defined __MINGW32__ 24#include <sys/utime.h> /* for utime() */ 25#include <io.h> /* for chmod(), _setmode(), unlink() */ 26#include <fcntl.h> /* for _O_BINARY */ 27#else 28#include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */ 29#include <utime.h> /* for utime() */ 30#endif 31#if defined __CYGWIN__ || defined __EMX__ 32#include <io.h> /* for setmode(), O_BINARY */ 33#include <fcntl.h> /* for _O_BINARY */ 34#endif 35#include <sys/stat.h> /* for stat(), maybe chmod() */ 36#if defined _WIN32 && !defined __CYGWIN__ 37#else 38#include <unistd.h> /* for unlink() */ 39#endif 40#include <stdio.h> 41#include <stdlib.h> 42#include <string.h> /* for strrchr() */ 43#if defined _WIN32 && !defined __CYGWIN__ 44// for GetFileInformationByHandle() etc 45#include <windows.h> 46#include <winbase.h> 47#endif 48#include "share/grabbag.h" 49 50 51void grabbag__file_copy_metadata(const char *srcpath, const char *destpath) 52{ 53 struct stat srcstat; 54 struct utimbuf srctime; 55 56 if(0 == stat(srcpath, &srcstat)) { 57 srctime.actime = srcstat.st_atime; 58 srctime.modtime = srcstat.st_mtime; 59 (void)chmod(destpath, srcstat.st_mode); 60 (void)utime(destpath, &srctime); 61 } 62} 63 64off_t grabbag__file_get_filesize(const char *srcpath) 65{ 66 struct stat srcstat; 67 68 if(0 == stat(srcpath, &srcstat)) 69 return srcstat.st_size; 70 else 71 return -1; 72} 73 74const char *grabbag__file_get_basename(const char *srcpath) 75{ 76 const char *p; 77 78 p = strrchr(srcpath, '/'); 79 if(0 == p) { 80 p = strrchr(srcpath, '\\'); 81 if(0 == p) 82 return srcpath; 83 } 84 return ++p; 85} 86 87FLAC__bool grabbag__file_change_stats(const char *filename, FLAC__bool read_only) 88{ 89 struct stat stats; 90 91 if(0 == stat(filename, &stats)) { 92#if !defined _MSC_VER && !defined __MINGW32__ 93 if(read_only) { 94 stats.st_mode &= ~S_IWUSR; 95 stats.st_mode &= ~S_IWGRP; 96 stats.st_mode &= ~S_IWOTH; 97 } 98 else { 99 stats.st_mode |= S_IWUSR; 100 } 101#else 102 if(read_only) 103 stats.st_mode &= ~S_IWRITE; 104 else 105 stats.st_mode |= S_IWRITE; 106#endif 107 if(0 != chmod(filename, stats.st_mode)) 108 return false; 109 } 110 else 111 return false; 112 113 return true; 114} 115 116FLAC__bool grabbag__file_are_same(const char *f1, const char *f2) 117{ 118#if defined _MSC_VER || defined __MINGW32__ 119 /* see 120 * http://www.hydrogenaudio.org/forums/index.php?showtopic=49439&pid=444300&st=0 121 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/getfileinformationbyhandle.asp 122 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/by_handle_file_information_str.asp 123 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/createfile.asp 124 * apparently both the files have to be open at the same time for the comparison to work 125 */ 126 FLAC__bool same = false; 127 BY_HANDLE_FILE_INFORMATION info1, info2; 128 HANDLE h1, h2; 129 BOOL ok = 1; 130 h1 = CreateFile(f1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 131 h2 = CreateFile(f2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 132 if(h1 == INVALID_HANDLE_VALUE || h2 == INVALID_HANDLE_VALUE) 133 ok = 0; 134 ok &= GetFileInformationByHandle(h1, &info1); 135 ok &= GetFileInformationByHandle(h2, &info2); 136 if(ok) 137 same = 138 info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber && 139 info1.nFileIndexHigh == info2.nFileIndexHigh && 140 info1.nFileIndexLow == info2.nFileIndexLow 141 ; 142 if(h1 != INVALID_HANDLE_VALUE) 143 CloseHandle(h1); 144 if(h2 != INVALID_HANDLE_VALUE) 145 CloseHandle(h2); 146 return same; 147#else 148 struct stat s1, s2; 149 return f1 && f2 && stat(f1, &s1) == 0 && stat(f2, &s2) == 0 && s1.st_ino == s2.st_ino && s1.st_dev == s2.st_dev; 150#endif 151} 152 153FLAC__bool grabbag__file_remove_file(const char *filename) 154{ 155 return grabbag__file_change_stats(filename, /*read_only=*/false) && 0 == unlink(filename); 156} 157 158FILE *grabbag__file_get_binary_stdin(void) 159{ 160 /* if something breaks here it is probably due to the presence or 161 * absence of an underscore before the identifiers 'setmode', 162 * 'fileno', and/or 'O_BINARY'; check your system header files. 163 */ 164#if defined _MSC_VER || defined __MINGW32__ 165 _setmode(_fileno(stdin), _O_BINARY); 166#elif defined __CYGWIN__ 167 /* almost certainly not needed for any modern Cygwin, but let's be safe... */ 168 setmode(_fileno(stdin), _O_BINARY); 169#elif defined __EMX__ 170 setmode(fileno(stdin), O_BINARY); 171#endif 172 173 return stdin; 174} 175 176FILE *grabbag__file_get_binary_stdout(void) 177{ 178 /* if something breaks here it is probably due to the presence or 179 * absence of an underscore before the identifiers 'setmode', 180 * 'fileno', and/or 'O_BINARY'; check your system header files. 181 */ 182#if defined _MSC_VER || defined __MINGW32__ 183 _setmode(_fileno(stdout), _O_BINARY); 184#elif defined __CYGWIN__ 185 /* almost certainly not needed for any modern Cygwin, but let's be safe... */ 186 setmode(_fileno(stdout), _O_BINARY); 187#elif defined __EMX__ 188 setmode(fileno(stdout), O_BINARY); 189#endif 190 191 return stdout; 192} 193