1 /*****************************************************************************
2  * Author:   Valient Gough <vgough@pobox.com>
3  *
4  *****************************************************************************
5  * Copyright (c) 2003, Valient Gough
6  *
7  * This program is free software: you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation, either version 3 of the License, or (at your
10  * option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #ifndef _DirNode_incl_
22 #define _DirNode_incl_
23 
24 #include <dirent.h>
25 #include <inttypes.h>
26 #include <list>
27 #include <map>
28 #include <memory>
29 #include <pthread.h>
30 #include <stdint.h>
31 #include <string>
32 #include <sys/types.h>
33 #include <vector>
34 
35 #include "CipherKey.h"
36 #include "FSConfig.h"
37 #include "FileNode.h"
38 #include "NameIO.h"
39 
40 namespace encfs {
41 
42 class Cipher;
43 class EncFS_Context;
44 class FileNode;
45 class NameIO;
46 class RenameOp;
47 struct RenameEl;
48 
49 class DirTraverse {
50  public:
51   DirTraverse(std::shared_ptr<DIR> dirPtr, uint64_t iv,
52               std::shared_ptr<NameIO> naming, bool root);
53   ~DirTraverse();
54 
55   DirTraverse &operator=(const DirTraverse &src);
56 
57   // returns FALSE to indicate an invalid DirTraverse (such as when
58   // an invalid directory is requested for traversal)
59   bool valid() const;
60 
61   // return next plaintext filename
62   // If fileType is not 0, then it is used to return the filetype (or 0 if
63   // unknown)
64   std::string nextPlaintextName(int *fileType = 0, ino_t *inode = 0);
65 
66   /* Return cipher name of next undecodable filename..
67      The opposite of nextPlaintextName(), as that skips undecodable names..
68   */
69   std::string nextInvalid();
70 
71  private:
72   std::shared_ptr<DIR> dir;  // struct DIR
73   // initialization vector to use.  Not very general purpose, but makes it
74   // more efficient to support filename IV chaining..
75   uint64_t iv;
76   std::shared_ptr<NameIO> naming;
77   bool root;
78 };
valid()79 inline bool DirTraverse::valid() const { return dir.get() != 0; }
80 
81 class DirNode {
82  public:
83   // sourceDir points to where raw files are stored
84   DirNode(EncFS_Context *ctx, const std::string &sourceDir,
85           const FSConfigPtr &config);
86   ~DirNode();
87 
88   // return the path to the root directory
89   std::string rootDirectory();
90 
91   // recursive lookup check
92   bool touchesMountpoint(const char *realPath) const;
93 
94   // find files
95   std::shared_ptr<FileNode> lookupNode(const char *plaintextName,
96                                        const char *requestor);
97 
98   /*
99       Combined lookupNode + node->open() call.  If the open fails, then the
100       node is not retained.  If the open succeeds, then the node is returned.
101   */
102   std::shared_ptr<FileNode> openNode(const char *plaintextName,
103                                      const char *requestor, int flags,
104                                      int *openResult);
105 
106   std::string cipherPath(const char *plaintextPath);
107   std::string cipherPathWithoutRoot(const char *plaintextPath);
108   std::string plainPath(const char *cipherPath);
109 
110   // relative cipherPath is the same as cipherPath except that it doesn't
111   // prepent the mount point.  That it, it doesn't return a fully qualified
112   // name, just a relative path within the encrypted filesystem.
113   std::string relativeCipherPath(const char *plaintextPath);
114 
115   /*
116       Returns true if file names are dependent on the parent directory name.
117       If a directory name is changed, then all the filenames must also be
118       changed.
119   */
120   bool hasDirectoryNameDependency() const;
121 
122   // unlink the specified file
123   int unlink(const char *plaintextName);
124 
125   // traverse directory
126   DirTraverse openDir(const char *plainDirName);
127 
128   // uid and gid are used as the directory owner, only if not zero
129   int mkdir(const char *plaintextPath, mode_t mode, uid_t uid = 0,
130             gid_t gid = 0);
131 
132   int rename(const char *fromPlaintext, const char *toPlaintext);
133 
134   int link(const char *to, const char *from);
135 
136   // returns idle time of filesystem in seconds
137   int idleSeconds();
138 
139  protected:
140   /*
141       notify that a file is being renamed.
142       This renames the internal node, if any.  If the file is not open, then
143       this call has no effect.
144       Returns the FileNode if it was found.
145   */
146   std::shared_ptr<FileNode> renameNode(const char *from, const char *to);
147   std::shared_ptr<FileNode> renameNode(const char *from, const char *to,
148                                        bool forwardMode);
149 
150   /*
151       when directory IV chaining is enabled, a directory can't be renamed
152       without renaming all its contents as well.  recursiveRename should be
153       called after renaming the directory, passing in the plaintext from and
154       to paths.
155   */
156   std::shared_ptr<RenameOp> newRenameOp(const char *from, const char *to);
157 
158  private:
159   friend class RenameOp;
160 
161   bool genRenameList(std::list<RenameEl> &list, const char *fromP,
162                      const char *toP);
163 
164   std::shared_ptr<FileNode> findOrCreate(const char *plainName);
165 
166   pthread_mutex_t mutex;
167 
168   EncFS_Context *ctx;
169 
170   // passed in as configuration
171   std::string rootDir;
172   FSConfigPtr fsConfig;
173 
174   std::shared_ptr<NameIO> naming;
175 };
176 
177 }  // namespace encfs
178 
179 #endif
180