Kernel/VFS - Added unmount support
[tpg/acess2.git] / KernelLand / Kernel / vfs / dir.c
1 /*
2  * Acess2 VFS
3  * - Directory Management Functions
4  */
5 #define DEBUG   0
6 #include <acess.h>
7 #include <vfs.h>
8 #include <vfs_int.h>
9
10 // === IMPORTS ===
11 extern tVFS_Mount       *gRootMount;
12
13 // === PROTOTYPES ===
14 #if 0
15  int    VFS_MkDir(const char *Path);
16  int    VFS_MkNod(const char *Path, Uint Flags);
17  int    VFS_Symlink(const char *Name, const char *Link);
18 #endif
19
20 // === CODE ===
21 /**
22  * \fn int VFS_MkDir(char *Path)
23  * \brief Create a new node
24  * \param Path  Path of directory to create
25  */
26 int VFS_MkDir(const char *Path)
27 {
28         return VFS_MkNod(Path, VFS_FFLAG_DIRECTORY);
29 }
30
31 /**
32  * \fn int VFS_MkNod(char *Path, Uint Flags)
33  * \brief Create a new node in a directory
34  * \param Path  Path of new node
35  * \param Flags Flags to apply to the node
36  */
37 int VFS_MkNod(const char *Path, Uint Flags)
38 {
39         tVFS_Mount      *mountpt;
40         char    *absPath, *name;
41          int    pos = 0, oldpos = 0;
42          int    next = 0;
43         tVFS_Node       *parent;
44          int    ret;
45         
46         ENTER("sPath xFlags", Path, Flags);
47         
48         absPath = VFS_GetAbsPath(Path);
49         LOG("absPath = '%s'", absPath);
50         
51         while( (next = strpos(&absPath[pos+1], '/')) != -1 ) {
52                 LOG("next = %i", next);
53                 pos += next+1;
54                 LOG("pos = %i", pos);
55                 oldpos = pos;
56         }
57         absPath[oldpos] = '\0'; // Mutilate path
58         name = &absPath[oldpos+1];
59         
60         LOG("absPath = '%s', name = '%s'", absPath, name);
61         
62         // Check for root
63         if(absPath[0] == '\0')
64                 parent = VFS_ParsePath("/", NULL, &mountpt);
65         else
66                 parent = VFS_ParsePath(absPath, NULL, &mountpt);
67         
68         LOG("parent = %p", parent);
69         
70         if(!parent) {
71                 LEAVE('i', -1);
72                 return -1;      // Error Check
73         }
74
75         // Permissions Check
76         if( !VFS_CheckACL(parent, VFS_PERM_EXECUTE|VFS_PERM_WRITE) ) {
77                 _CloseNode(parent);
78                 mountpt->OpenHandleCount --;
79                 free(absPath);
80                 LEAVE('i', -1);
81                 return -1;
82         }
83         
84         LOG("parent = %p", parent);
85         
86         if(!parent->Type || !parent->Type->MkNod) {
87                 Log_Warning("VFS", "VFS_MkNod - Directory has no MkNod method");
88                 mountpt->OpenHandleCount --;
89                 LEAVE('i', -1);
90                 return -1;
91         }
92         
93         // Create node
94         ret = parent->Type->MkNod(parent, name, Flags);
95         
96         // Free allocated string
97         free(absPath);
98         
99         // Free Parent
100         mountpt->OpenHandleCount --;
101         _CloseNode(parent);
102         
103         // Error Check
104         if(ret != 0) {
105                 LEAVE('i', -1);
106                 return -1;
107         }
108         
109         LEAVE('i', 0);
110         return 0;
111 }
112
113 /**
114  * \fn int VFS_Symlink(const char *Name, const char *Link)
115  * \brief Creates a symlink called \a Name to \a Link
116  * \param Name  Name of symbolic link
117  * \param Link  Destination of symbolic link
118  */
119 int VFS_Symlink(const char *Name, const char *Link)
120 {
121         char    *realLink;
122          int    fp;
123         
124         ENTER("sName sLink", Name, Link);
125         
126         // Get absolue path name
127         realLink = VFS_GetAbsPath( Link );
128         if(!realLink) {
129                 Log_Warning("VFS", "Path '%s' is badly formed", Link);
130                 LEAVE('i', -1);
131                 return -1;
132         }
133
134         LOG("realLink = '%s'", realLink);
135
136         // Make node
137         if( VFS_MkNod(Name, VFS_FFLAG_SYMLINK) != 0 ) {
138                 Log_Warning("VFS", "Unable to create link node '%s'", Name);
139                 free(realLink);
140                 LEAVE('i', -2);
141                 return -2;      // Make link node
142         }
143         
144         // Write link address
145         fp = VFS_Open(Name, VFS_OPENFLAG_WRITE|VFS_OPENFLAG_NOLINK);
146         VFS_Write(fp, strlen(realLink), realLink);
147         VFS_Close(fp);
148         
149         free(realLink);
150         
151         LEAVE('i', 1);
152         return 1;
153 }
154
155 /**
156  * \fn int VFS_ReadDir(int FD, char *Dest)
157  * \brief Read from a directory
158  */
159 int VFS_ReadDir(int FD, char *Dest)
160 {
161         tVFS_Handle     *h = VFS_GetHandle(FD);
162         char    *tmp;
163         
164         //ENTER("ph pDest", h, Dest);
165         
166         if(!h || !h->Node->Type || !h->Node->Type->ReadDir) {
167                 //LEAVE('i', 0);
168                 return 0;
169         }
170         
171         if(h->Node->Size != -1 && h->Position >= h->Node->Size) {
172                 //LEAVE('i', 0);
173                 return 0;
174         }
175         
176         do {
177                 tmp = h->Node->Type->ReadDir(h->Node, h->Position);
178                 if((Uint)tmp < (Uint)VFS_MAXSKIP)
179                         h->Position += (Uint)tmp;
180                 else
181                         h->Position ++;
182         } while(tmp != NULL && (Uint)tmp < (Uint)VFS_MAXSKIP);
183         
184         //LOG("tmp = '%s'", tmp);
185         
186         if(!tmp) {
187                 //LEAVE('i', 0);
188                 return 0;
189         }
190         
191         strcpy(Dest, tmp);
192         free(tmp);
193         
194         //LEAVE('i', 1);
195         return 1;
196 }

UCC git Repository :: git.ucc.asn.au