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

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