Planeshift

directory_reader.h

Go to the documentation of this file.
00001 // Copyright (c) 2009, Google Inc.
00002 // All rights reserved.
00003 //
00004 // Redistribution and use in source and binary forms, with or without
00005 // modification, are permitted provided that the following conditions are
00006 // met:
00007 //
00008 //     * Redistributions of source code must retain the above copyright
00009 // notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above
00011 // copyright notice, this list of conditions and the following disclaimer
00012 // in the documentation and/or other materials provided with the
00013 // distribution.
00014 //     * Neither the name of Google Inc. nor the names of its
00015 // contributors may be used to endorse or promote products derived from
00016 // this software without specific prior written permission.
00017 //
00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00021 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00022 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00023 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00024 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00025 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00026 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00028 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 
00030 #ifndef CLIENT_LINUX_MINIDUMP_WRITER_DIRECTORY_READER_H_
00031 #define CLIENT_LINUX_MINIDUMP_WRITER_DIRECTORY_READER_H_
00032 
00033 #include <stdint.h>
00034 #include <unistd.h>
00035 #include <limits.h>
00036 #include <assert.h>
00037 #include <errno.h>
00038 #include <string.h>
00039 
00040 #include "common/linux/linux_libc_support.h"
00041 #include "third_party/lss/linux_syscall_support.h"
00042 
00043 namespace google_breakpad {
00044 
00045 // A class for enumerating a directory without using diropen/readdir or other
00046 // functions which may allocate memory.
00047 class DirectoryReader {
00048  public:
00049   DirectoryReader(int fd)
00050       : fd_(fd),
00051         buf_used_(0) {
00052   }
00053 
00054   // Return the next entry from the directory
00055   //   name: (output) the NUL terminated entry name
00056   //
00057   // Returns true iff successful (false on EOF).
00058   //
00059   // After calling this, one must call |PopEntry| otherwise you'll get the same
00060   // entry over and over.
00061   bool GetNextEntry(const char** name) {
00062     struct kernel_dirent* const dent =
00063       reinterpret_cast<kernel_dirent*>(buf_);
00064 
00065     if (buf_used_ == 0) {
00066       // need to read more entries.
00067       const int n = sys_getdents(fd_, dent, sizeof(buf_));
00068       if (n < 0) {
00069         return false;
00070       } else if (n == 0) {
00071         hit_eof_ = true;
00072       } else {
00073         buf_used_ += n;
00074       }
00075     }
00076 
00077     if (buf_used_ == 0 && hit_eof_)
00078       return false;
00079 
00080     assert(buf_used_ > 0);
00081 
00082     *name = dent->d_name;
00083     return true;
00084   }
00085 
00086   void PopEntry() {
00087     if (!buf_used_)
00088       return;
00089 
00090     const struct kernel_dirent* const dent =
00091       reinterpret_cast<kernel_dirent*>(buf_);
00092 
00093     buf_used_ -= dent->d_reclen;
00094     my_memmove(buf_, buf_ + dent->d_reclen, buf_used_);
00095   }
00096 
00097  private:
00098   const int fd_;
00099   bool hit_eof_;
00100   unsigned buf_used_;
00101   uint8_t buf_[sizeof(struct kernel_dirent) + NAME_MAX + 1];
00102 };
00103 
00104 }  // namespace google_breakpad
00105 
00106 #endif  // CLIENT_LINUX_MINIDUMP_WRITER_DIRECTORY_READER_H_