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

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