Kernel - Added .Detect method to VFS drivers
[tpg/acess2.git] / KernelLand / Kernel / vfs / fs / devfs.c
1 /*
2  * Acess 2
3  * Device Filesystem (DevFS)
4  * - vfs/fs/devfs.c
5  */
6 #define DEBUG   0
7 #include <acess.h>
8 #include <vfs.h>
9 #include <fs_devfs.h>
10
11 // === PROTOTYPES ===
12 #if 0
13  int    DevFS_AddDevice(tDevFS_Driver *Device);
14 void    DevFS_DelDevice(tDevFS_Driver *Device);
15 #endif
16 tVFS_Node       *DevFS_InitDevice(const char *Device, const char **Options);
17 void    DevFS_Unmount(tVFS_Node *RootNode);
18 char    *DevFS_ReadDir(tVFS_Node *Node, int Pos);
19 tVFS_Node       *DevFS_FindDir(tVFS_Node *Node, const char *Name);
20
21 // === GLOBALS ===
22 tVFS_Driver     gDevFS_Info = {
23         .Name = "devfs",
24         .InitDevice = DevFS_InitDevice,
25         .Unmount = DevFS_Unmount
26         };
27 tVFS_NodeType   gDevFS_DirType = {
28         .TypeName = "DevFS-Dir",
29         .ReadDir = DevFS_ReadDir,
30         .FindDir = DevFS_FindDir
31         };
32 tVFS_Node       gDevFS_RootNode = {
33         .Size = 0,
34         .Flags = VFS_FFLAG_DIRECTORY,
35         .NumACLs = 1,
36         .ACLs = &gVFS_ACL_EveryoneRX,
37         .Type = &gDevFS_DirType
38         };
39 tDevFS_Driver   *gDevFS_Drivers = NULL;
40  int    giDevFS_NextID = 1;
41 tShortSpinlock  glDevFS_ListLock;
42
43 // === CODE ===
44 /**
45  * \fn int DevFS_AddDevice(tDevFS_Driver *Device)
46  */
47 int DevFS_AddDevice(tDevFS_Driver *Device)
48 {
49          int    ret = 0;
50         tDevFS_Driver   *dev;
51
52         ENTER("pDevice", Device);
53         LOG("Device->Name = '%s'", Device->Name);
54         
55         SHORTLOCK( &glDevFS_ListLock );
56         
57         // Check if the device is already registered or the name is taken
58         for( dev = gDevFS_Drivers; dev; dev = dev->Next )
59         {
60                 if(dev == Device)       break;
61                 if(strcmp(dev->Name, Device->Name) == 0)        break;
62         }
63         
64         if(dev) {
65                 if(dev == Device)
66                         Log_Warning("DevFS", "Device %p '%s' attempted to register itself twice",
67                                 dev, dev->Name);
68                 else
69                         Log_Warning("DevFS", "Device %p attempted to register '%s' which was owned by %p",
70                                 Device, dev->Name, dev);
71                 ret = -1;       // Error
72         }
73         else {
74                 Device->Next = gDevFS_Drivers;
75                 gDevFS_Drivers = Device;
76                 gDevFS_RootNode.Size ++;
77                 ret = giDevFS_NextID ++;
78         }
79         SHORTREL( &glDevFS_ListLock );
80         
81         LEAVE('i', ret);
82         return ret;
83 }
84
85 /**
86  * \brief Delete a device from the DevFS folder
87  */
88 void DevFS_DelDevice(tDevFS_Driver *Device)
89 {
90         tDevFS_Driver   *prev = NULL, *dev;
91         
92         SHORTLOCK( &glDevFS_ListLock );
93         // Search list for device
94         for(dev = gDevFS_Drivers;
95                 dev && dev != Device;
96                 prev = dev, dev = dev->Next
97                 );
98         
99         // Check if it was found
100         if(dev)
101         {
102                 if(prev)
103                         prev->Next = Device->Next;
104                 else
105                         gDevFS_Drivers = Device->Next;
106         }
107         else
108                 Log_Warning("DevFS", "Attempted to unregister device %p '%s' which was not registered",
109                         Device, Device->Name);
110         
111         SHORTREL( &glDevFS_ListLock );
112 }
113
114 /**
115  * \brief Initialise the DevFS and detect double-mounting, or just do nothing
116  * \note STUB
117  */
118 tVFS_Node *DevFS_InitDevice(const char *Device, const char **Options)
119 {
120         return &gDevFS_RootNode;
121 }
122
123 void DevFS_Unmount(tVFS_Node *RootNode)
124 {
125         
126 }
127
128 /**
129  * \fn char *DevFS_ReadDir(tVFS_Node *Node, int Pos)
130  */
131 char *DevFS_ReadDir(tVFS_Node *Node, int Pos)
132 {
133         tDevFS_Driver   *dev;
134         
135         if(Pos < 0)     return NULL;
136         
137         for(dev = gDevFS_Drivers;
138                 dev && Pos--;
139                 dev = dev->Next
140                 );
141         
142         if(dev)
143                 return strdup(dev->Name);
144         else
145                 return NULL;
146 }
147
148 /**
149  * \fn tVFS_Node *DevFS_FindDir(tVFS_Node *Node, const char *Name)
150  * \brief Get an entry from the devices directory
151  */
152 tVFS_Node *DevFS_FindDir(tVFS_Node *Node, const char *Name)
153 {
154         tDevFS_Driver   *dev;
155         
156         ENTER("pNode sName", Node, Name);
157         
158         for(dev = gDevFS_Drivers;
159                 dev;
160                 dev = dev->Next
161                 )
162         {
163                 //LOG("dev = %p", dev);
164                 LOG("dev->Name = '%s'", dev->Name);
165                 if(strcmp(dev->Name, Name) == 0) {
166                         LEAVE('p', &dev->RootNode);
167                         return &dev->RootNode;
168                 }
169         }
170         
171         LEAVE('n');
172         return NULL;
173 }
174
175 // --- EXPORTS ---
176 EXPORT(DevFS_AddDevice);
177 EXPORT(DevFS_DelDevice);

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