| 1 | //============================================================================ | 
| 2 | // | 
| 3 | //   SSSS    tt          lll  lll | 
| 4 | //  SS  SS   tt           ll   ll | 
| 5 | //  SS     tttttt  eeee   ll   ll   aaaa | 
| 6 | //   SSSS    tt   ee  ee  ll   ll      aa | 
| 7 | //      SS   tt   eeeeee  ll   ll   aaaaa  --  "An Atari 2600 VCS Emulator" | 
| 8 | //  SS  SS   tt   ee      ll   ll  aa  aa | 
| 9 | //   SSSS     ttt  eeeee llll llll  aaaaa | 
| 10 | // | 
| 11 | // Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony | 
| 12 | // and the Stella Team | 
| 13 | // | 
| 14 | // See the file "License.txt" for information on usage and redistribution of | 
| 15 | // this file, and for a DISCLAIMER OF ALL WARRANTIES. | 
| 16 | //============================================================================ | 
| 17 |  | 
| 18 | #ifndef FS_NODE_POSIX_HXX | 
| 19 | #define FS_NODE_POSIX_HXX | 
| 20 |  | 
| 21 | #include "FSNode.hxx" | 
| 22 |  | 
| 23 | #ifdef BSPF_MACOS | 
| 24 |   #include <sys/types.h> | 
| 25 | #endif | 
| 26 |  | 
| 27 | #include <sys/param.h> | 
| 28 | #include <sys/stat.h> | 
| 29 | #include <dirent.h> | 
| 30 |  | 
| 31 | #include <cassert> | 
| 32 | #include <cstdio> | 
| 33 | #include <cstring> | 
| 34 | #include <cstdlib> | 
| 35 | #include <unistd.h> | 
| 36 |  | 
| 37 | #ifndef MAXPATHLEN // No MAXPATHLEN, as happens on Hurd | 
| 38 |   #define MAXPATHLEN 1024 | 
| 39 | #endif | 
| 40 |  | 
| 41 | /* | 
| 42 |  * Implementation of the Stella file system API based on POSIX (for Linux and macOS) | 
| 43 |  * | 
| 44 |  * Parts of this class are documented in the base interface class, AbstractFSNode. | 
| 45 |  */ | 
| 46 | class FilesystemNodePOSIX : public AbstractFSNode | 
| 47 | { | 
| 48 |   public: | 
| 49 |     /** | 
| 50 |      * Creates a FilesystemNodePOSIX with the root node as path. | 
| 51 |      */ | 
| 52 |     FilesystemNodePOSIX(); | 
| 53 |  | 
| 54 |     /** | 
| 55 |      * Creates a FilesystemNodePOSIX for a given path. | 
| 56 |      * | 
| 57 |      * @param path    String with the path the new node should point to. | 
| 58 |      * @param verify  true if the isValid and isDirectory/isFile flags should | 
| 59 |      *                be verified during the construction. | 
| 60 |      */ | 
| 61 |     FilesystemNodePOSIX(const string& path, bool verify = true); | 
| 62 |  | 
| 63 |     bool exists() const override { return access(_path.c_str(), F_OK) == 0; } | 
| 64 |     const string& getName() const override    { return _displayName; } | 
| 65 |     void setName(const string& name) override { _displayName = name; } | 
| 66 |     const string& getPath() const override { return _path; } | 
| 67 |     string getShortPath() const override; | 
| 68 |     bool hasParent() const override; | 
| 69 |     bool isDirectory() const override { return _isDirectory; } | 
| 70 |     bool isFile() const override      { return _isFile;      } | 
| 71 |     bool isReadable() const override  { return access(_path.c_str(), R_OK) == 0; } | 
| 72 |     bool isWritable() const override  { return access(_path.c_str(), W_OK) == 0; } | 
| 73 |     bool makeDir() override; | 
| 74 |     bool rename(const string& newfile) override; | 
| 75 |  | 
| 76 |     bool getChildren(AbstractFSList& list, ListMode mode) const override; | 
| 77 |     AbstractFSNodePtr getParent() const override; | 
| 78 |  | 
| 79 |   protected: | 
| 80 |     string _path; | 
| 81 |     string _displayName; | 
| 82 |     bool _isValid; | 
| 83 |     bool _isFile; | 
| 84 |     bool _isDirectory; | 
| 85 |  | 
| 86 |   private: | 
| 87 |     /** | 
| 88 |      * Tests and sets the _isValid and _isDirectory/_isFile flags, | 
| 89 |      * using the stat() function. | 
| 90 |      */ | 
| 91 |     virtual void setFlags(); | 
| 92 |  | 
| 93 |     /** | 
| 94 |      * Returns the last component of a given path. | 
| 95 |      * | 
| 96 |      * Examples: | 
| 97 |      *			/foo/bar.txt would return /bar.txt | 
| 98 |      *			/foo/bar/    would return /bar/ | 
| 99 |      * | 
| 100 |      * @param str String containing the path. | 
| 101 |      * @return Pointer to the first char of the last component inside str. | 
| 102 |      */ | 
| 103 |     static const char* lastPathComponent(const string& str) | 
| 104 |     { | 
| 105 |       if(str.empty()) | 
| 106 |         return "" ; | 
| 107 |  | 
| 108 |       const char* start = str.c_str(); | 
| 109 |       const char* cur = start + str.size() - 2; | 
| 110 |  | 
| 111 |       while (cur >= start && *cur != '/') | 
| 112 |         --cur; | 
| 113 |  | 
| 114 |       return cur + 1; | 
| 115 |     } | 
| 116 | }; | 
| 117 |  | 
| 118 | #endif | 
| 119 |  |