Cleanups - MM_MapTemp to return void*, VFS use Unlink instead of Relink
[tpg/acess2.git] / KernelLand / Kernel / vfs / mount.c
1 /* 
2  * Acess Micro - VFS Server version 1
3  */
4 #include <acess.h>
5 #include <vfs.h>
6 #include <vfs_int.h>
7 #include <fs_sysfs.h>
8
9 // === IMPORTS ===
10 extern int      giVFS_MountFileID;
11 extern char     *gsVFS_MountFile;
12
13 // === PROTOTYPES ===
14 #if 0
15  int    VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem, const char *Options);
16 #endif
17 void    VFS_UpdateMountFile(void);
18
19 // === GLOBALS ===
20 tMutex  glVFS_MountList;
21 tVFS_Mount      *gVFS_Mounts;
22 tVFS_Mount      *gVFS_RootMount = NULL;
23 Uint32  giVFS_NextMountIdent = 1;
24
25 // === CODE ===
26 /**
27  * \brief Mount a device
28  * \param Device        Device string to mount
29  * \param MountPoint    Destination for the mount
30  * \param Filesystem    Filesystem to use for the mount
31  * \param Options               Options to be passed to the filesystem
32  * \return -1 on Invalid FS, -2 on No Mem, 0 on success
33  * 
34  * Mounts the filesystem on \a Device at \a MountPoint using the driver
35  * \a Filesystem. The options in the string \a Options is passed to the
36  * driver's mount.
37  */
38 int VFS_Mount(const char *Device, const char *MountPoint, const char *Filesystem, const char *Options)
39 {
40         tVFS_Mount      *mnt;
41         tVFS_Driver     *fs;
42          int    deviceLen = strlen(Device);
43          int    mountLen = strlen(MountPoint);
44          int    argLen = strlen(Options);
45         
46         // Get the filesystem
47         fs = VFS_GetFSByName(Filesystem);
48         if(!fs) {
49                 Log_Warning("VFS", "VFS_Mount - Unknown FS Type '%s'", Filesystem);
50                 return -1;
51         }
52         
53         // Create mount information
54         mnt = malloc( sizeof(tVFS_Mount)+deviceLen+1+mountLen+1+argLen+1 );
55         if(!mnt) {
56                 return -2;
57         }
58         
59         // HACK: Forces VFS_ParsePath to fall back on root  
60         if(mountLen == 1 && MountPoint[0] == '/')
61                 mnt->MountPointLen = 0;
62         else
63                 mnt->MountPointLen = mountLen;
64         
65         // Fill Structure
66         mnt->Filesystem = fs;
67         
68         mnt->Device = &mnt->StrData[0];
69         memcpy( mnt->Device, Device, deviceLen+1 );
70         
71         mnt->MountPoint = &mnt->StrData[deviceLen+1];
72         memcpy( mnt->MountPoint, MountPoint, mountLen+1 );
73         
74         mnt->Options = &mnt->StrData[deviceLen+1+mountLen+1];
75         memcpy( mnt->Options, Options, argLen+1 );
76         
77         // Parse options string
78         char    *str = mnt->Options;
79          int    nArg = 0;
80         do {
81                 nArg ++;
82         } while( (str = strchr(str, ',')) );
83
84         char    *args[nArg + 1];
85         str = mnt->Options;
86         nArg = 0;
87         do {
88                 args[nArg++] = str;
89                 str = strchr(str, ',');
90                 if(str) *str = '\0';
91         } while( str );
92         args[nArg] = 0; // NULL terminal
93
94         // Initialise Volume
95         mnt->RootNode = fs->InitDevice(Device, (const char **)args);
96         if(!mnt->RootNode) {
97                 free(mnt);
98                 return -2;
99         }
100
101         // Repair the options string
102         while( nArg -- > 1 )
103                 args[nArg][-1] = ',';
104
105         mnt->Identifier = giVFS_NextMountIdent++;
106         #if 0
107         // Ensure identifiers don't repeat
108         // - Only a problem if there have been 4 billion mounts
109         while( giVFS_NextMountIdent == 0 || VFS_GetMountByIdent(giVFS_NextMountIdent) )
110                 giVFS_NextMountIdent ++;
111         #endif
112         
113         // Set root
114         if(!gVFS_RootMount)     gVFS_RootMount = mnt;
115         
116         // Add to mount list
117         Mutex_Acquire( &glVFS_MountList );
118         {
119                 tVFS_Mount      *tmp;
120                 mnt->Next = NULL;
121                 if(gVFS_Mounts) {
122                         for( tmp = gVFS_Mounts; tmp->Next; tmp = tmp->Next );
123                         tmp->Next = mnt;
124                 }
125                 else {
126                         gVFS_Mounts = mnt;
127                 }
128         }
129         Mutex_Release( &glVFS_MountList );
130         
131         Log_Log("VFS", "Mounted '%s' to '%s' ('%s')", Device, MountPoint, Filesystem);
132         
133         VFS_UpdateMountFile();
134         
135         return 0;
136 }
137
138 /**
139  * \brief Gets a mount point given the identifier
140  */
141 tVFS_Mount *VFS_GetMountByIdent(Uint32 MountID)
142 {
143         tVFS_Mount      *mnt;
144         for(mnt = gVFS_Mounts; mnt; mnt = mnt->Next)
145         {
146                 if(mnt->Identifier == MountID)
147                         return mnt;
148         }
149         return NULL;
150 }
151
152 /**
153  * \brief Updates the mount file buffer
154  * 
155  * Updates the ProcFS mounts file buffer to match the current mounts list.
156  */
157 void VFS_UpdateMountFile(void)
158 {
159          int    len = 0;
160         char    *buf;
161         tVFS_Mount      *mnt;
162         
163         // Format:
164         // <device>\t<location>\t<type>\t<options>\n
165         
166         for(mnt = gVFS_Mounts; mnt; mnt = mnt->Next)
167         {
168                 len += 4 + strlen(mnt->Device) + strlen(mnt->MountPoint)
169                         + strlen(mnt->Filesystem->Name) + strlen(mnt->Options);
170         }
171         
172         buf = malloc( len + 1 );
173         len = 0;
174         for(mnt = gVFS_Mounts; mnt; mnt = mnt->Next)
175         {
176                 strcpy( &buf[len], mnt->Device );
177                 len += strlen(mnt->Device);
178                 buf[len++] = '\t';
179                 
180                 strcpy( &buf[len], mnt->MountPoint );
181                 len += strlen(mnt->MountPoint);
182                 buf[len++] = '\t';
183                 
184                 strcpy( &buf[len], mnt->Filesystem->Name );
185                 len += strlen(mnt->Filesystem->Name);
186                 buf[len++] = '\t';
187                 
188                 strcpy( &buf[len], mnt->Options );
189                 len += strlen(mnt->Options);
190                 buf[len++] = '\n';
191         }
192         buf[len] = 0;
193         
194         SysFS_UpdateFile( giVFS_MountFileID, buf, len );
195         if( gsVFS_MountFile )   free( gsVFS_MountFile );
196         gsVFS_MountFile = buf;
197 }

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