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 */
46class 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