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

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