Merge branch 'master' of git://git.ucc.asn.au/tpg/acess2
[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  int    DevFS_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX]);
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 int DevFS_ReadDir(tVFS_Node *Node, int Pos, char Dest[FILENAME_MAX])
132 {
133         tDevFS_Driver   *dev;
134         
135         if(Pos < 0)     return -EINVAL;
136         
137         for(dev = gDevFS_Drivers;
138                 dev && Pos--;
139                 dev = dev->Next
140                 );
141         
142         if(dev) {
143                 strncpy(Dest, dev->Name, FILENAME_MAX);
144                 return 0;
145         }
146         else {
147                 return -ENOENT;
148         }
149 }
150
151 /**
152  * \fn tVFS_Node *DevFS_FindDir(tVFS_Node *Node, const char *Name)
153  * \brief Get an entry from the devices directory
154  */
155 tVFS_Node *DevFS_FindDir(tVFS_Node *Node, const char *Name)
156 {
157         tDevFS_Driver   *dev;
158         
159         ENTER("pNode sName", Node, Name);
160         
161         for(dev = gDevFS_Drivers;
162                 dev;
163                 dev = dev->Next
164                 )
165         {
166                 //LOG("dev = %p", dev);
167                 LOG("dev->Name = '%s'", dev->Name);
168                 if(strcmp(dev->Name, Name) == 0) {
169                         LEAVE('p', &dev->RootNode);
170                         return &dev->RootNode;
171                 }
172         }
173         
174         LEAVE('n');
175         return NULL;
176 }
177
178 // --- EXPORTS ---
179 EXPORT(DevFS_AddDevice);
180 EXPORT(DevFS_DelDevice);

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