Kernel/vfs - Fixing OpenInode support
[tpg/acess2.git] / 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         // Initialise Volume
78         mnt->RootNode = fs->InitDevice(Device, NULL);   //&ArgString);
79         if(!mnt->RootNode) {
80                 free(mnt);
81                 return -2;
82         }
83
84         mnt->Identifier = giVFS_NextMountIdent++;
85         #if 0
86         // Ensure identifiers don't repeat
87         // - Only a problem if there have been 4 billion mounts
88         while( giVFS_NextMountIdent == 0 || VFS_GetMountByIdent(giVFS_NextMountIdent) )
89                 giVFS_NextMountIdent ++;
90         #endif
91         
92         // Set root
93         if(!gVFS_RootMount)     gVFS_RootMount = mnt;
94         
95         // Add to mount list
96         Mutex_Acquire( &glVFS_MountList );
97         {
98                 tVFS_Mount      *tmp;
99                 mnt->Next = NULL;
100                 if(gVFS_Mounts) {
101                         for( tmp = gVFS_Mounts; tmp->Next; tmp = tmp->Next );
102                         tmp->Next = mnt;
103                 }
104                 else {
105                         gVFS_Mounts = mnt;
106                 }
107         }
108         Mutex_Release( &glVFS_MountList );
109         
110         Log_Log("VFS", "Mounted '%s' to '%s' ('%s')", Device, MountPoint, Filesystem);
111         
112         VFS_UpdateMountFile();
113         
114         return 0;
115 }
116
117 /**
118  * \brief Gets a mount point given the identifier
119  */
120 tVFS_Mount *VFS_GetMountByIdent(Uint32 MountID)
121 {
122         tVFS_Mount      *mnt;
123         for(mnt = gVFS_Mounts; mnt; mnt = mnt->Next)
124         {
125                 if(mnt->Identifier == MountID)
126                         return mnt;
127         }
128         return NULL;
129 }
130
131 /**
132  * \brief Updates the mount file buffer
133  * 
134  * Updates the ProcFS mounts file buffer to match the current mounts list.
135  */
136 void VFS_UpdateMountFile(void)
137 {
138          int    len = 0;
139         char    *buf;
140         tVFS_Mount      *mnt;
141         
142         // Format:
143         // <device>\t<location>\t<type>\t<options>\n
144         
145         for(mnt = gVFS_Mounts; mnt; mnt = mnt->Next)
146         {
147                 len += 4 + strlen(mnt->Device) + strlen(mnt->MountPoint)
148                         + strlen(mnt->Filesystem->Name) + strlen(mnt->Options);
149         }
150         
151         buf = malloc( len + 1 );
152         len = 0;
153         for(mnt = gVFS_Mounts; mnt; mnt = mnt->Next)
154         {
155                 strcpy( &buf[len], mnt->Device );
156                 len += strlen(mnt->Device);
157                 buf[len++] = '\t';
158                 
159                 strcpy( &buf[len], mnt->MountPoint );
160                 len += strlen(mnt->MountPoint);
161                 buf[len++] = '\t';
162                 
163                 strcpy( &buf[len], mnt->Filesystem->Name );
164                 len += strlen(mnt->Filesystem->Name);
165                 buf[len++] = '\t';
166                 
167                 strcpy( &buf[len], mnt->Options );
168                 len += strlen(mnt->Options);
169                 buf[len++] = '\n';
170         }
171         buf[len] = 0;
172         
173         SysFS_UpdateFile( giVFS_MountFileID, buf, len );
174         if( gsVFS_MountFile )   free( gsVFS_MountFile );
175         gsVFS_MountFile = buf;
176 }

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