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

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