1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format 2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc. All rights reserved. 3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// http://code.google.com/p/protobuf/ 4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without 6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are 7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met: 8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions of source code must retain the above copyright 10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer. 11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions in binary form must reproduce the above 12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer 13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the 14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution. 15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Neither the name of Google Inc. nor the names of its 16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from 17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission. 18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Author: kenton@google.com (Kenton Varda) 32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// emulates google3/file/base/file.cc 33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/testing/file.h> 35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <stdio.h> 36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/stat.h> 37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/types.h> 38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _MSC_VER 39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define WIN32_LEAN_AND_MEAN // yeah, right 40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <windows.h> // Find*File(). :( 41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <io.h> 42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <direct.h> 43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <dirent.h> 45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <unistd.h> 46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <errno.h> 48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace google { 50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace protobuf { 51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32 53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define mkdir(name, mode) mkdir(name) 54fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Windows doesn't have symbolic links. 55fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define lstat stat 56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifndef F_OK 57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define F_OK 00 // not defined by MSVC for whatever reason 58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool File::Exists(const string& name) { 62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return access(name.c_str(), F_OK) == 0; 63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool File::ReadFileToString(const string& name, string* output) { 66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville char buffer[1024]; 67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FILE* file = fopen(name.c_str(), "rb"); 68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (file == NULL) return false; 69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville while (true) { 71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville size_t n = fread(buffer, 1, sizeof(buffer), file); 72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (n <= 0) break; 73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville output->append(buffer, n); 74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int error = ferror(file); 77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (fclose(file) != 0) return false; 78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return error == 0; 79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid File::ReadFileToStringOrDie(const string& name, string* output) { 82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_CHECK(ReadFileToString(name, output)) << "Could not read: " << name; 83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid File::WriteStringToFileOrDie(const string& contents, const string& name) { 86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FILE* file = fopen(name.c_str(), "wb"); 87d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_CHECK(file != NULL) 88d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << "fopen(" << name << ", \"wb\"): " << strerror(errno); 89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_CHECK_EQ(fwrite(contents.data(), 1, contents.size(), file), 90d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville contents.size()) 91d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << "fwrite(" << name << "): " << strerror(errno); 92d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_CHECK(fclose(file) == 0) 93d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << "fclose(" << name << "): " << strerror(errno); 94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool File::CreateDir(const string& name, int mode) { 97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return mkdir(name.c_str(), mode) == 0; 98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool File::RecursivelyCreateDir(const string& path, int mode) { 101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (CreateDir(path, mode)) return true; 102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 103d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (Exists(path)) return false; 104d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Try creating the parent. 106d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string::size_type slashpos = path.find_last_of('/'); 107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (slashpos == string::npos) { 108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // No parent given. 109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return RecursivelyCreateDir(path.substr(0, slashpos), mode) && 113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville CreateDir(path, mode); 114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid File::DeleteRecursively(const string& name, 117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void* dummy1, void* dummy2) { 118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // We don't care too much about error checking here since this is only used 119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // in tests to delete temporary directories that are under /tmp anyway. 120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _MSC_VER 122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // This interface is so weird. 123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville WIN32_FIND_DATA find_data; 124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville HANDLE find_handle = FindFirstFile((name + "/*").c_str(), &find_data); 125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (find_handle == INVALID_HANDLE_VALUE) { 126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Just delete it, whatever it is. 127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DeleteFile(name.c_str()); 128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville RemoveDirectory(name.c_str()); 129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return; 130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville do { 133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville string entry_name = find_data.cFileName; 134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (entry_name != "." && entry_name != "..") { 135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville string path = name + "/" + entry_name; 136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DeleteRecursively(path, NULL, NULL); 138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville RemoveDirectory(path.c_str()); 139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DeleteFile(path.c_str()); 141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } while(FindNextFile(find_handle, &find_data)); 144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FindClose(find_handle); 145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville RemoveDirectory(name.c_str()); 147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Use opendir()! Yay! 149fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // lstat = Don't follow symbolic links. 150fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville struct stat stats; 151fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (lstat(name.c_str(), &stats) != 0) return; 152fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 153fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (S_ISDIR(stats.st_mode)) { 154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DIR* dir = opendir(name.c_str()); 155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (dir != NULL) { 156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville while (true) { 157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville struct dirent* entry = readdir(dir); 158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (entry == NULL) break; 159fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville string entry_name = entry->d_name; 160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (entry_name != "." && entry_name != "..") { 161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DeleteRecursively(name + "/" + entry_name, NULL, NULL); 162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 164fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 165fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville closedir(dir); 167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville rmdir(name.c_str()); 168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (S_ISREG(stats.st_mode)) { 170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville remove(name.c_str()); 171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace protobuf 176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace google 177