Home | History | Annotate | Download | only in posix
      1 /*
      2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14  *     its contributors may be used to endorse or promote products derived
     15  *     from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include "config.h"
     30 #include "FileSystem.h"
     31 
     32 #include "PlatformString.h"
     33 #include <dirent.h>
     34 #include <errno.h>
     35 #include <fcntl.h>
     36 #include <fnmatch.h>
     37 #include <libgen.h>
     38 #include <sys/stat.h>
     39 #include <sys/types.h>
     40 #include <unistd.h>
     41 #include <wtf/text/CString.h>
     42 
     43 namespace WebCore {
     44 
     45 bool fileExists(const String& path)
     46 {
     47     if (path.isNull())
     48         return false;
     49 
     50     CString fsRep = fileSystemRepresentation(path);
     51 
     52     if (!fsRep.data() || fsRep.data()[0] == '\0')
     53         return false;
     54 
     55     struct stat fileInfo;
     56 
     57     // stat(...) returns 0 on successful stat'ing of the file, and non-zero in any case where the file doesn't exist or cannot be accessed
     58     return !stat(fsRep.data(), &fileInfo);
     59 }
     60 
     61 bool deleteFile(const String& path)
     62 {
     63     CString fsRep = fileSystemRepresentation(path);
     64 
     65     if (!fsRep.data() || fsRep.data()[0] == '\0')
     66         return false;
     67 
     68     // unlink(...) returns 0 on successful deletion of the path and non-zero in any other case (including invalid permissions or non-existent file)
     69     return !unlink(fsRep.data());
     70 }
     71 
     72 PlatformFileHandle openFile(const String& path, FileOpenMode mode)
     73 {
     74     CString fsRep = fileSystemRepresentation(path);
     75 
     76     if (fsRep.isNull())
     77         return invalidPlatformFileHandle;
     78 
     79     int platformFlag = 0;
     80     if (mode == OpenForRead)
     81         platformFlag |= O_RDONLY;
     82     else if (mode == OpenForWrite)
     83         platformFlag |= (O_WRONLY | O_CREAT | O_TRUNC);
     84     return open(fsRep.data(), platformFlag, 0666);
     85 }
     86 
     87 void closeFile(PlatformFileHandle& handle)
     88 {
     89     if (isHandleValid(handle)) {
     90         close(handle);
     91         handle = invalidPlatformFileHandle;
     92     }
     93 }
     94 
     95 long long seekFile(PlatformFileHandle handle, long long offset, FileSeekOrigin origin)
     96 {
     97     int whence = SEEK_SET;
     98     switch (origin) {
     99     case SeekFromBeginning:
    100         whence = SEEK_SET;
    101         break;
    102     case SeekFromCurrent:
    103         whence = SEEK_CUR;
    104         break;
    105     case SeekFromEnd:
    106         whence = SEEK_END;
    107         break;
    108     default:
    109         ASSERT_NOT_REACHED();
    110     }
    111     return static_cast<long long>(lseek(handle, offset, whence));
    112 }
    113 
    114 bool truncateFile(PlatformFileHandle handle, long long offset)
    115 {
    116     // ftruncate returns 0 to indicate the success.
    117     return !ftruncate(handle, offset);
    118 }
    119 
    120 int writeToFile(PlatformFileHandle handle, const char* data, int length)
    121 {
    122     do {
    123         int bytesWritten = write(handle, data, static_cast<size_t>(length));
    124         if (bytesWritten >= 0)
    125             return bytesWritten;
    126     } while (errno == EINTR);
    127     return -1;
    128 }
    129 
    130 int readFromFile(PlatformFileHandle handle, char* data, int length)
    131 {
    132     do {
    133         int bytesRead = read(handle, data, static_cast<size_t>(length));
    134         if (bytesRead >= 0)
    135             return bytesRead;
    136     } while (errno == EINTR);
    137     return -1;
    138 }
    139 
    140 bool deleteEmptyDirectory(const String& path)
    141 {
    142     CString fsRep = fileSystemRepresentation(path);
    143 
    144     if (!fsRep.data() || fsRep.data()[0] == '\0')
    145         return false;
    146 
    147     // rmdir(...) returns 0 on successful deletion of the path and non-zero in any other case (including invalid permissions or non-existent file)
    148     return !rmdir(fsRep.data());
    149 }
    150 
    151 bool getFileSize(const String& path, long long& result)
    152 {
    153     CString fsRep = fileSystemRepresentation(path);
    154 
    155     if (!fsRep.data() || fsRep.data()[0] == '\0')
    156         return false;
    157 
    158     struct stat fileInfo;
    159 
    160     if (stat(fsRep.data(), &fileInfo))
    161         return false;
    162 
    163     result = fileInfo.st_size;
    164     return true;
    165 }
    166 
    167 bool getFileModificationTime(const String& path, time_t& result)
    168 {
    169     CString fsRep = fileSystemRepresentation(path);
    170 
    171     if (!fsRep.data() || fsRep.data()[0] == '\0')
    172         return false;
    173 
    174     struct stat fileInfo;
    175 
    176     if (stat(fsRep.data(), &fileInfo))
    177         return false;
    178 
    179     result = fileInfo.st_mtime;
    180     return true;
    181 }
    182 
    183 String pathByAppendingComponent(const String& path, const String& component)
    184 {
    185     if (path.endsWith("/"))
    186         return path + component;
    187     else
    188         return path + "/" + component;
    189 }
    190 
    191 bool makeAllDirectories(const String& path)
    192 {
    193     CString fullPath = fileSystemRepresentation(path);
    194     if (!access(fullPath.data(), F_OK))
    195         return true;
    196 
    197     char* p = fullPath.mutableData() + 1;
    198     int length = fullPath.length();
    199 
    200     if(p[length - 1] == '/')
    201         p[length - 1] = '\0';
    202     for (; *p; ++p)
    203         if (*p == '/') {
    204             *p = '\0';
    205             if (access(fullPath.data(), F_OK))
    206                 if (mkdir(fullPath.data(), S_IRWXU))
    207                     return false;
    208             *p = '/';
    209         }
    210     if (access(fullPath.data(), F_OK))
    211         if (mkdir(fullPath.data(), S_IRWXU))
    212             return false;
    213 
    214     return true;
    215 }
    216 
    217 #if !PLATFORM(ANDROID)
    218 String pathGetFileName(const String& path)
    219 {
    220     return path.substring(path.reverseFind('/') + 1);
    221 }
    222 #endif
    223 
    224 String directoryName(const String& path)
    225 {
    226     CString fsRep = fileSystemRepresentation(path);
    227 
    228     if (!fsRep.data() || fsRep.data()[0] == '\0')
    229         return String();
    230 
    231     return dirname(fsRep.mutableData());
    232 }
    233 
    234 #if !PLATFORM(EFL)
    235 Vector<String> listDirectory(const String& path, const String& filter)
    236 {
    237     Vector<String> entries;
    238     CString cpath = path.utf8();
    239     CString cfilter = filter.utf8();
    240     DIR* dir = opendir(cpath.data());
    241     if (dir) {
    242         struct dirent* dp;
    243         while ((dp = readdir(dir))) {
    244             const char* name = dp->d_name;
    245             if (!strcmp(name, ".") || !strcmp(name, ".."))
    246                 continue;
    247             if (fnmatch(cfilter.data(), name, 0))
    248                 continue;
    249             char filePath[1024];
    250             if (static_cast<int>(sizeof(filePath) - 1) < snprintf(filePath, sizeof(filePath), "%s/%s", cpath.data(), name))
    251                 continue; // buffer overflow
    252             entries.append(filePath);
    253         }
    254         closedir(dir);
    255     }
    256     return entries;
    257 }
    258 #endif
    259 
    260 } // namespace WebCore
    261