52e9f8075724956d47e5386ddacc71d9729c5018
[tpg/acess2.git] / Kernel / vfs / dir.c
1 /*
2  * Acess2 VFS
3  * - Directory Management Functions
4  */
5 #define DEBUG   0
6 #include <common.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(char *Path);
15  int    VFS_MkNod(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(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(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         if(!parent)     return -1;      // Error Check
65         
66         // Permissions Check
67         if( !VFS_CheckACL(parent, VFS_PERM_EXECUTE|VFS_PERM_WRITE) ) {
68                 if(parent->Close)       parent->Close( parent );
69                 free(absPath);
70                 LEAVE('i', -1);
71                 return -1;
72         }
73         
74         LOG("parent = %p", parent);
75         
76         if(parent->MkNod == NULL) {
77                 Warning("VFS_MkNod - Directory has no MkNod method");
78                 LEAVE('i', -1);
79                 return -1;
80         }
81         
82         // Create node
83         ret = parent->MkNod(parent, name, Flags);
84         
85         // Free allocated string
86         free(absPath);
87         
88         // Free Parent
89         if(parent->Close)       parent->Close( parent );
90         
91         // Error Check
92         if(ret == 0) {
93                 LEAVE('i', -1);
94                 return -1;
95         }
96         
97         LEAVE('i', 0);
98         return 0;
99 }
100
101 /**
102  * \fn int VFS_Symlink(char *Name, char *Link)
103  * \brief Creates a symlink called \a Name to \a Link
104  * \param Name  Name of symbolic link
105  * \param Link  Destination of symbolic link
106  */
107 int VFS_Symlink(char *Name, char *Link)
108 {
109         char    *realLink;
110          int    fp;
111         tVFS_Node       *destNode;
112         
113         //ENTER("sName sLink", Name, Link);
114         
115         // Get absolue path name
116         Link = VFS_GetAbsPath( Link );
117         if(!Link) {
118                 Warning("Path '%s' is badly formed", Link);
119                 return -1;
120         }
121         
122         // Get true path and node
123         destNode = VFS_ParsePath( Link, &realLink );
124         free(Link);
125         
126         // Check if destination exists
127         if(!destNode) {
128                 Warning("File '%s' does not exist, symlink not created", Link);
129                 return -1;
130         }
131         
132         // Derefence the destination
133         if(destNode->Close)     destNode->Close(destNode);
134         
135         // Make node
136         if( VFS_MkNod(Name, VFS_FFLAG_SYMLINK) != 0 ) {
137                 Warning("Unable to create link node '%s'", Name);
138                 return -2;      // Make link node
139         }
140         
141         // Write link address
142         fp = VFS_Open(Name, VFS_OPENFLAG_WRITE|VFS_OPENFLAG_NOLINK);
143         VFS_Write(fp, strlen(realLink), realLink);
144         VFS_Close(fp);
145         
146         free(realLink);
147         
148         return 1;
149 }
150
151 /**
152  * \fn int VFS_ReadDir(int FD, char *Dest)
153  * \brief Read from a directory
154  */
155 int VFS_ReadDir(int FD, char *Dest)
156 {
157         tVFS_Handle     *h = VFS_GetHandle(FD);
158         char    *tmp;
159         
160         //ENTER("ph pDest", h, Dest);
161         
162         if(!h || h->Node->ReadDir == NULL) {
163                 //LEAVE('i', 0);
164                 return 0;
165         }
166         
167         if(h->Node->Size != -1 && h->Position >= h->Node->Size) {
168                 //LEAVE('i', 0);
169                 return 0;
170         }
171         
172         do {
173                 tmp = h->Node->ReadDir(h->Node, h->Position);
174                 if((Uint)tmp < (Uint)VFS_MAXSKIP)
175                         h->Position += (Uint)tmp;
176                 else
177                         h->Position ++;
178         } while(tmp != NULL && (Uint)tmp < (Uint)VFS_MAXSKIP);
179         
180         //LOG("tmp = '%s'", tmp);
181         
182         if(!tmp) {
183                 //LEAVE('i', 0);
184                 return 0;
185         }
186         
187         strcpy(Dest, tmp);
188         free(tmp);
189         
190         //LEAVE('i', 1);
191         return 1;
192 }

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