95660dc43a5ef1c21637850954f668bb3f030427
[reactos.git] / reactos / drivers / fs / minix / minix.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: services/fs/minix/minix.c
5 * PURPOSE: Minix FSD
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ddk/ntddk.h>
13 #include <internal/string.h>
14 #include <wstring.h>
15
16 //#define NDEBUG
17 #include <internal/debug.h>
18
19 #include "minix_fs.h"
20
21 /* GLOBALS ******************************************************************/
22
23 static PDRIVER_OBJECT DriverObject;
24
25 typedef struct
26 {
27 PDEVICE_OBJECT AttachedDevice;
28 struct minix_inode root_inode;
29 char superblock_buf[BLOCKSIZE];
30 struct minix_super_block* sb;
31 } MINIX_DEVICE_EXTENSION;
32
33 /* FUNCTIONS ****************************************************************/
34
35
36 static unsigned int MinixGetIndirectBlock(struct minix_inode* inode,
37 unsigned char* buffer, int blk)
38 {
39 unsigned short int* buf = (unsigned short int *)buffer;
40 return(buf[blk]);
41 }
42
43 static unsigned int MinixGetBlock(PDEVICE_OBJECT DeviceObject,
44 struct minix_inode* inode,
45 int blk)
46 {
47 int block;
48 char* buffer;
49
50
51 DPRINT("MinixGetBlock(inode %x, blk %d)\n",inode,blk);
52
53 if (blk < 7)
54 {
55 block = inode->i_zone[blk];
56 return(block);
57 }
58 blk = blk - 7;
59
60 buffer = ExAllocatePool(NonPagedPool,1024);
61
62 if (blk < 512)
63 {
64 block = inode->i_zone[7];
65 MinixReadSector(DeviceObject,block,buffer);
66 block = MinixGetIndirectBlock(inode,buffer,blk);
67 ExFreePool(buffer);
68 return(block);
69 }
70 blk = blk - 512;
71 block = inode->i_zone[8];
72 MinixReadSector(DeviceObject,block,buffer);
73 block = MinixGetIndirectBlock(inode,buffer,(blk>>9)&511);
74 MinixReadSector(DeviceObject,block,buffer);
75 block = MinixGetIndirectBlock(inode,buffer,blk&511);
76 ExFreePool(buffer);
77 return(block);
78 }
79
80 NTSTATUS MinixReadBlock(PDEVICE_OBJECT DeviceObject,
81 struct minix_inode* inode,
82 int blk,
83 PVOID buffer)
84 {
85 unsigned int block;
86
87 DPRINT("MinixReadBlock(inode %x, blk %d, buffer %x)\n",inode,blk,buffer);
88 block = MinixGetBlock(DeviceObject,inode,blk);
89 DPRINT("block %d\n",block);
90 return(MinixReadSector(DeviceObject,block,buffer));
91 }
92
93 VOID MinixMount(PDEVICE_OBJECT DeviceToMount)
94 {
95 PDEVICE_OBJECT DeviceObject;
96 MINIX_DEVICE_EXTENSION* DeviceExt;
97
98 IoCreateDevice(DriverObject,
99 sizeof(MINIX_DEVICE_EXTENSION),
100 NULL,
101 FILE_DEVICE_FILE_SYSTEM,
102 0,
103 FALSE,
104 &DeviceObject);
105 DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
106 DeviceExt = DeviceObject->DeviceExtension;
107
108 MinixReadSector(DeviceToMount,1,DeviceExt->superblock_buf);
109 DeviceExt->sb = (struct minix_super_block *)(DeviceExt->superblock_buf);
110
111 DeviceExt->AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
112 DeviceToMount);
113 }
114
115 NTSTATUS MinixFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
116 {
117 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
118 PVPB vpb = Stack->Parameters.Mount.Vpb;
119 PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject;
120 NTSTATUS Status;
121 char* superblock_buf;
122 struct minix_super_block* sb;
123
124 DbgPrint("MinixFileSystemControl(DeviceObject %x, Irp %x)\n",DeviceObject,
125 Irp);
126 DPRINT("DeviceToMount %x\n",DeviceToMount);
127
128 superblock_buf = ExAllocatePool(NonPagedPool,BLOCKSIZE);
129
130 DPRINT("MinixReadSector %x\n",MinixReadSector);
131 MinixReadSector(DeviceToMount,1,superblock_buf);
132 sb = (struct minix_super_block *)superblock_buf;
133 DPRINT("Magic %x\n",sb->s_magic);
134 DPRINT("Imap blocks %x\n",sb->s_imap_blocks);
135 DPRINT("Zmap blocks %x\n",sb->s_zmap_blocks);
136 if (sb->s_magic==MINIX_SUPER_MAGIC2)
137 {
138 DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
139 MinixMount(DeviceToMount);
140 Status = STATUS_SUCCESS;
141 }
142 else
143 {
144 DPRINT("%s() = STATUS_UNRECOGNIZED_VOLUME\n",__FUNCTION__);
145 Status = STATUS_UNRECOGNIZED_VOLUME;
146 }
147
148 Irp->IoStatus.Status = Status;
149 Irp->IoStatus.Information = 0;
150
151 IoCompleteRequest(Irp, IO_NO_INCREMENT);
152 return(Status);
153 }
154
155
156 NTSTATUS MinixReadInode(PDEVICE_OBJECT DeviceObject,
157 MINIX_DEVICE_EXTENSION* DeviceExt,
158 ULONG ino,
159 struct minix_inode* result)
160 {
161 int block;
162 char* buffer;
163 struct minix_inode* inodes;
164
165 DPRINT("MinixReadInode(ino %x, result %x)\n",ino,result);
166
167 buffer = ExAllocatePool(NonPagedPool,1024);
168 inodes = (struct minix_inode *)buffer;
169
170 block = 2 + DeviceExt->sb->s_imap_blocks + DeviceExt->sb->s_zmap_blocks
171 + ((ino-1) / MINIX_INODES_PER_BLOCK);
172 DPRINT("Reading block %x offset %x\n",block,block*BLOCKSIZE);
173 DPRINT("Index %x\n",(ino-1)%MINIX_INODES_PER_BLOCK);
174 MinixReadSector(DeviceObject,block,buffer);
175 memcpy(result,&inodes[(ino-1)%MINIX_INODES_PER_BLOCK],
176 sizeof(struct minix_inode));
177 DPRINT("result->i_uid %x\n",result->i_uid);
178 DPRINT("result->i_size %x\n",result->i_size);
179 return(STATUS_SUCCESS);
180 }
181
182 BOOLEAN MinixCompareUnicodeStringToAnsi(PCH AnsiStr, PWCHAR UnicodeStr,
183 ULONG MaxLen)
184 {
185 unsigned int i = 0;
186
187 while (i<MaxLen)
188 {
189 if ((*AnsiStr)!=(*UnicodeStr))
190 {
191 return(FALSE);
192 }
193 if ((*AnsiStr)==0 && (*UnicodeStr)==0)
194 {
195 return(TRUE);
196 }
197 AnsiStr++;
198 UnicodeStr++;
199 i++;
200 }
201 return(TRUE);
202 }
203
204 ULONG MinixDirLookup(PDEVICE_OBJECT DeviceObject,
205 struct minix_inode* dir,
206 PWCHAR Name)
207 {
208 char* buffer;
209 struct minix_dir_entry* entry;
210 unsigned int offset;
211 unsigned int i;
212 unsigned int inode;
213
214 buffer=ExAllocatePool(NonPagedPool,BLOCKSIZE);
215
216 for (i=0;i<(dir->i_size/MINIX_DIR_ENTRY_SIZE);i++)
217 {
218 offset = i*MINIX_DIR_ENTRY_SIZE;
219 if ((offset%BLOCKSIZE)==0)
220 {
221 MinixReadBlock(DeviceObject,
222 dir,
223 offset/BLOCKSIZE,
224 buffer);
225 }
226 entry = (struct minix_dir_entry *)&buffer[offset%BLOCKSIZE];
227 DPRINT("Inode %x Name %.30s\n",entry->inode,entry->name);
228 if (MinixCompareUnicodeStringToAnsi(entry->name,Name,30))
229 {
230 inode = entry->inode;
231 ExFreePool(buffer);
232 DPRINT("MinixDirLookup() = %d\n",inode);
233 return(inode);
234 }
235 }
236 ExFreePool(buffer);
237 DPRINT("MinixDirLookup() = %d\n",0);
238 return(0);
239 }
240
241 NTSTATUS MinixOpen(PDEVICE_OBJECT DeviceObject,
242 MINIX_DEVICE_EXTENSION* DeviceExt,
243 PWSTR DeviceName,
244 struct minix_inode* result)
245 {
246 PWSTR current;
247 PWSTR next;
248 PWSTR string = DeviceName;
249 struct minix_inode current_dir;
250 unsigned int current_ino;
251
252 DbgPrint("MinixOpen(DeviceObject %x, DeviceName %S, result %x)\n",
253 DeviceObject,DeviceName,result);
254 DPRINT("DeviceName %x\n",DeviceName);
255
256 next = &string[0];
257 current = next+1;
258
259 current_ino = MINIX_ROOT_INO;
260
261 while (next!=NULL && current_ino!=0)
262 {
263 MinixReadInode(DeviceObject,DeviceExt,current_ino,&current_dir);
264
265 DPRINT("current %S next %x\n",current,next);
266
267 *next = '\\';
268 current = next+1;
269 next = wcschr(next+1,'\\');
270 if (next!=NULL)
271 {
272 *next=0;
273 }
274
275 current_ino = MinixDirLookup(DeviceObject,&current_dir,current);
276 }
277 if (next==NULL && current_ino!=0)
278 {
279 MinixReadInode(DeviceObject,DeviceExt,current_ino,&current_dir);
280 }
281 memcpy(result,&current_dir,sizeof(struct minix_inode));
282 DPRINT("MinxOpen() = STATUS_SUCCESS\n",0);
283 return(STATUS_SUCCESS);
284 }
285
286 NTSTATUS MinixWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
287 {
288 DPRINT("MinixWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
289
290 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
291 Irp->IoStatus.Information = 0;
292 return(STATUS_UNSUCCESSFUL);
293 }
294
295 NTSTATUS MinixRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
296 {
297 ULONG Length;
298 PVOID Buffer;
299 ULONG Offset;
300 ULONG CurrentOffset;
301 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
302 PFILE_OBJECT FileObject = Stack->FileObject;
303 MINIX_DEVICE_EXTENSION* DeviceExt = DeviceObject->DeviceExtension;
304 struct minix_inode* inode = (struct minix_inode *)FileObject->FsContext;
305 PVOID TempBuffer;
306 unsigned int i;
307
308 DPRINT("MinixRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
309
310 Length = Stack->Parameters.Read.Length;
311 Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
312 Offset = Stack->Parameters.Read.ByteOffset.LowPart;
313
314 TempBuffer = ExAllocatePool(NonPagedPool,BLOCKSIZE);
315
316 DPRINT("Length %x Buffer %x Offset %x\n",Length,Buffer,Offset);
317
318 CurrentOffset=Offset;
319
320 if ((Offset%BLOCKSIZE)!=0)
321 {
322 CHECKPOINT;
323
324 CurrentOffset = Offset - (Offset%BLOCKSIZE);
325
326 MinixReadBlock(DeviceExt->AttachedDevice,inode,
327 CurrentOffset/BLOCKSIZE,
328 TempBuffer);
329 memcpy(Buffer,TempBuffer+(Offset%BLOCKSIZE),
330 min(BLOCKSIZE - (Offset%BLOCKSIZE),Length));
331 DPRINT("(BLOCKSIZE - (Offset%BLOCKSIZE)) %d\n",
332 (BLOCKSIZE - (Offset%BLOCKSIZE)));
333 DPRINT("Length %d\n",Length);
334 CurrentOffset = CurrentOffset + BLOCKSIZE;
335 Buffer = Buffer + BLOCKSIZE - (Offset%BLOCKSIZE);
336 Length = Length - min(BLOCKSIZE - (Offset%BLOCKSIZE),Length);
337 DPRINT("CurrentOffset %d Buffer %x Length %d\n",CurrentOffset,Buffer,
338 Length);
339 }
340 for (i=0;i<(Length/BLOCKSIZE);i++)
341 {
342 CHECKPOINT;
343
344 MinixReadBlock(DeviceExt->AttachedDevice,inode,
345 CurrentOffset/BLOCKSIZE,Buffer);
346 CurrentOffset = CurrentOffset + BLOCKSIZE;
347 Buffer = Buffer + BLOCKSIZE;
348 Length = Length - BLOCKSIZE;
349 }
350 if (Length > 0)
351 {
352 CHECKPOINT;
353
354 MinixReadBlock(DeviceExt->AttachedDevice,inode,
355 CurrentOffset/BLOCKSIZE,
356 TempBuffer);
357 memcpy(Buffer,TempBuffer,Length);
358 }
359
360 Irp->IoStatus.Status = STATUS_SUCCESS;
361 Irp->IoStatus.Information = Length;
362 return(STATUS_SUCCESS);
363 }
364
365 NTSTATUS MinixClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
366 {
367 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
368 PFILE_OBJECT FileObject = Stack->FileObject;
369
370 DPRINT("MinixClose(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
371
372 ExFreePool(FileObject->FsContext);
373
374 Irp->IoStatus.Status = STATUS_SUCCESS;
375 Irp->IoStatus.Information = 0;
376
377 IoCompleteRequest(Irp, IO_NO_INCREMENT);
378 return(STATUS_SUCCESS);
379 }
380
381 NTSTATUS MinixCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
382 {
383 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
384 PFILE_OBJECT FileObject = Stack->FileObject;
385 NTSTATUS Status;
386 struct minix_inode* result;
387 MINIX_DEVICE_EXTENSION* DeviceExt;
388
389 DPRINT("MinixCreate(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
390 DPRINT("Opening file %x %S\n",FileObject->FileName.Buffer,
391 FileObject->FileName.Buffer);
392 DPRINT("FileObject->FileName.Buffer %x\n",
393 FileObject->FileName.Buffer);
394
395 DeviceExt = (MINIX_DEVICE_EXTENSION *)DeviceObject->DeviceExtension;
396 result = ExAllocatePool(NonPagedPool,sizeof(struct minix_inode));
397 DPRINT("result %x\n",result);
398 Status = MinixOpen(DeviceExt->AttachedDevice,DeviceExt,
399 FileObject->FileName.Buffer,result);
400
401 if (Status==STATUS_SUCCESS)
402 {
403 FileObject->FsContext=result;
404 }
405
406 Irp->IoStatus.Status = Status;
407 Irp->IoStatus.Information = 0;
408
409 IoCompleteRequest(Irp, IO_NO_INCREMENT);
410 return(Status);
411 }
412
413 NTSTATUS DriverEntry(PDRIVER_OBJECT _DriverObject,
414 PUNICODE_STRING RegistryPath)
415 /*
416 * FUNCTION: Called by the system to initalize the driver
417 * ARGUMENTS:
418 * DriverObject = object describing this driver
419 * RegistryPath = path to our configuration entries
420 * RETURNS: Success or failure
421 */
422 {
423 PDEVICE_OBJECT DeviceObject;
424 NTSTATUS ret;
425 UNICODE_STRING ustr;
426 ANSI_STRING astr;
427
428 DbgPrint("Minix FSD 0.0.1\n");
429
430 DriverObject = _DriverObject;
431
432 RtlInitAnsiString(&astr,"\\Device\\Minix");
433 RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE);
434 ret = IoCreateDevice(DriverObject,0,&ustr,
435 FILE_DEVICE_PARALLEL_PORT,0,FALSE,&DeviceObject);
436 if (ret!=STATUS_SUCCESS)
437 {
438 return(ret);
439 }
440
441 DeviceObject->Flags=0;
442 DriverObject->MajorFunction[IRP_MJ_CLOSE] = MinixClose;
443 DriverObject->MajorFunction[IRP_MJ_CREATE] = MinixCreate;
444 DriverObject->MajorFunction[IRP_MJ_READ] = MinixRead;
445 DriverObject->MajorFunction[IRP_MJ_WRITE] = MinixWrite;
446 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
447 MinixFileSystemControl;
448 DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
449 MinixDirectoryControl;
450 DriverObject->DriverUnload = NULL;
451
452 IoRegisterFileSystem(DeviceObject);
453
454 return(STATUS_SUCCESS);
455 }
456