[NTFS]
[reactos.git] / drivers / filesystems / ext2 / src / create.c
1 /*
2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
4 * FILE: create.c
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
7 * UPDATE HISTORY:
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "ext2fs.h"
13
14 /* GLOBALS *****************************************************************/
15
16 extern PEXT2_GLOBAL Ext2Global;
17
18 /* DEFINITIONS *************************************************************/
19
20 #ifdef ALLOC_PRAGMA
21 #pragma alloc_text(PAGE, Ext2IsNameValid)
22 #pragma alloc_text(PAGE, Ext2FollowLink)
23 #pragma alloc_text(PAGE, Ext2IsSpecialSystemFile)
24 #pragma alloc_text(PAGE, Ext2LookupFile)
25 #pragma alloc_text(PAGE, Ext2ScanDir)
26 #pragma alloc_text(PAGE, Ext2CreateFile)
27 #pragma alloc_text(PAGE, Ext2CreateVolume)
28 #pragma alloc_text(PAGE, Ext2Create)
29 #pragma alloc_text(PAGE, Ext2CreateInode)
30 #pragma alloc_text(PAGE, Ext2SupersedeOrOverWriteFile)
31 #endif
32
33
34 BOOLEAN
35 Ext2IsNameValid(PUNICODE_STRING FileName)
36 {
37 USHORT i = 0;
38 PUSHORT pName = (PUSHORT) FileName->Buffer;
39
40 if (FileName == NULL) {
41 return FALSE;
42 }
43
44 while (i < (FileName->Length / sizeof(WCHAR))) {
45
46 if (pName[i] == 0) {
47 break;
48 }
49
50 if (pName[i] == L'|' || pName[i] == L':' ||
51 pName[i] == L'/' || pName[i] == L'*' ||
52 pName[i] == L'?' || pName[i] == L'\"' ||
53 pName[i] == L'<' || pName[i] == L'>' ) {
54
55 return FALSE;
56 }
57
58 i++;
59 }
60
61 return TRUE;
62 }
63
64
65 NTSTATUS
66 Ext2FollowLink (
67 IN PEXT2_IRP_CONTEXT IrpContext,
68 IN PEXT2_VCB Vcb,
69 IN PEXT2_MCB Parent,
70 IN PEXT2_MCB Mcb,
71 IN ULONG Linkdep
72 )
73 {
74 NTSTATUS Status = STATUS_LINK_FAILED;
75
76 UNICODE_STRING UniName;
77 OEM_STRING OemName;
78 BOOLEAN bOemBuffer = FALSE;
79
80 PEXT2_MCB Target = NULL;
81
82 USHORT i;
83
84 _SEH2_TRY {
85
86 RtlZeroMemory(&UniName, sizeof(UNICODE_STRING));
87 RtlZeroMemory(&OemName, sizeof(OEM_STRING));
88
89 /* exit if we jump into a possible symlink forever loop */
90 if ((Linkdep + 1) > EXT2_MAX_NESTED_LINKS ||
91 IoGetRemainingStackSize() < 1024) {
92 _SEH2_LEAVE;
93 }
94
95 /* read the symlink target path */
96 if (!Mcb->Inode.i_blocks) {
97
98 OemName.Buffer = (PUCHAR) (&Mcb->Inode.i_block[0]);
99 OemName.Length = (USHORT)Mcb->Inode.i_size;
100 OemName.MaximumLength = OemName.Length + 1;
101
102 } else {
103
104 OemName.Length = (USHORT)Mcb->Inode.i_size;
105 OemName.MaximumLength = OemName.Length + 1;
106 OemName.Buffer = Ext2AllocatePool(PagedPool,
107 OemName.MaximumLength,
108 'NL2E');
109 if (OemName.Buffer == NULL) {
110 Status = STATUS_INSUFFICIENT_RESOURCES;
111 _SEH2_LEAVE;
112 }
113 bOemBuffer = TRUE;
114 RtlZeroMemory(OemName.Buffer, OemName.MaximumLength);
115
116 Status = Ext2ReadSymlink(
117 IrpContext,
118 Vcb,
119 Mcb,
120 OemName.Buffer,
121 (ULONG)(Mcb->Inode.i_size),
122 NULL);
123 if (!NT_SUCCESS(Status)) {
124 _SEH2_LEAVE;
125 }
126 }
127
128 /* convert Linux slash to Windows backslash */
129 for (i=0; i < OemName.Length; i++) {
130 if (OemName.Buffer[i] == '/') {
131 OemName.Buffer[i] = '\\';
132 }
133 }
134
135 /* convert oem string to unicode string */
136 UniName.MaximumLength = (USHORT)Ext2OEMToUnicodeSize(Vcb, &OemName);
137 if (UniName.MaximumLength <= 0) {
138 Status = STATUS_INSUFFICIENT_RESOURCES;
139 _SEH2_LEAVE;
140 }
141
142 UniName.MaximumLength += 2;
143 UniName.Buffer = Ext2AllocatePool(PagedPool,
144 UniName.MaximumLength,
145 'NL2E');
146 if (UniName.Buffer == NULL) {
147 Status = STATUS_INSUFFICIENT_RESOURCES;
148 _SEH2_LEAVE;
149 }
150 RtlZeroMemory(UniName.Buffer, UniName.MaximumLength);
151 Status = Ext2OEMToUnicode(Vcb, &UniName, &OemName);
152 if (!NT_SUCCESS(Status)) {
153 Status = STATUS_INSUFFICIENT_RESOURCES;
154 _SEH2_LEAVE;
155 }
156
157 /* search the real target */
158 Status = Ext2LookupFile(
159 IrpContext,
160 Vcb,
161 &UniName,
162 Parent,
163 &Target,
164 Linkdep
165 );
166 if (Target == NULL) {
167 Status = STATUS_LINK_FAILED;
168 }
169
170 if (Target == NULL /* link target doesn't exist */ ||
171 Target == Mcb /* symlink points to itself */ ||
172 IsMcbSpecialFile(Target) /* target not resolved*/ ||
173 IsFileDeleted(Target) /* target deleted */ ) {
174
175 if (Target) {
176 ASSERT(Target->Refercount > 0);
177 Ext2DerefMcb(Target);
178 }
179 ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
180 SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
181 Mcb->Target = NULL;
182
183 } else if (IsMcbSymLink(Target)) {
184
185 ASSERT(Target->Refercount > 0);
186 ASSERT(Target->Target != NULL);
187 Ext2ReferMcb(Target->Target);
188 Mcb->Target = Target->Target;
189 Ext2DerefMcb(Target);
190 ASSERT(!IsMcbSymLink(Target->Target));
191 SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
192 ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
193 ASSERT(Mcb->Target->Refercount > 0);
194
195 } else {
196
197 Mcb->Target = Target;
198 SetLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
199 ClearLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
200 ASSERT(Mcb->Target->Refercount > 0);
201 }
202
203 /* add directory flag to file attribute */
204 if (Mcb->Target && IsMcbDirectory(Mcb->Target)) {
205 Mcb->FileAttr |= FILE_ATTRIBUTE_DIRECTORY;
206 }
207
208 } _SEH2_FINALLY {
209
210 if (bOemBuffer) {
211 Ext2FreePool(OemName.Buffer, 'NL2E');
212 }
213
214 if (UniName.Buffer) {
215 Ext2FreePool(UniName.Buffer, 'NL2E');
216 }
217 } _SEH2_END;
218
219 return Status;
220 }
221
222 BOOLEAN
223 Ext2IsSpecialSystemFile(
224 IN PUNICODE_STRING FileName,
225 IN BOOLEAN bDirectory
226 )
227 {
228 PWSTR SpecialFileList[] = {
229 L"pagefile.sys",
230 L"swapfile.sys",
231 L"hiberfil.sys",
232 NULL
233 };
234
235 PWSTR SpecialDirList[] = {
236 L"Recycled",
237 L"RECYCLER",
238 L"$RECYCLE.BIN",
239 NULL
240 };
241
242 PWSTR entryName;
243 ULONG length;
244 int i;
245
246 for (i = 0; TRUE; i++) {
247
248 if (bDirectory) {
249 entryName = SpecialDirList[i];
250 } else {
251 entryName = SpecialFileList[i];
252 }
253
254 if (NULL == entryName) {
255 break;
256 }
257
258 length = wcslen(entryName) * sizeof(WCHAR);
259 if (FileName->Length == length) {
260 if ( 0 == _wcsnicmp( entryName,
261 FileName->Buffer,
262 length / sizeof(WCHAR) )) {
263 return TRUE;
264 }
265 }
266 }
267
268 return FALSE;
269 }
270
271 NTSTATUS
272 Ext2LookupFile (
273 IN PEXT2_IRP_CONTEXT IrpContext,
274 IN PEXT2_VCB Vcb,
275 IN PUNICODE_STRING FullName,
276 IN PEXT2_MCB Parent,
277 OUT PEXT2_MCB * Ext2Mcb,
278 IN ULONG Linkdep
279 )
280 {
281 NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
282 UNICODE_STRING FileName;
283 PEXT2_MCB Mcb = NULL;
284 struct dentry *de = NULL;
285
286 USHORT i = 0, End;
287 ULONG Inode;
288
289 BOOLEAN bParent = FALSE;
290 BOOLEAN bDirectory = FALSE;
291 BOOLEAN LockAcquired = FALSE;
292 BOOLEAN bNotFollow = FALSE;
293
294 _SEH2_TRY {
295
296 ExAcquireResourceExclusiveLite(&Vcb->McbLock, TRUE);
297 LockAcquired = TRUE;
298
299 bNotFollow = IsFlagOn(Linkdep, EXT2_LOOKUP_NOT_FOLLOW);
300 #ifndef __REACTOS__
301 Linkdep = ClearFlag(Linkdep, EXT2_LOOKUP_FLAG_MASK);
302 #else
303 ClearFlag(Linkdep, EXT2_LOOKUP_FLAG_MASK);
304 #endif
305
306 *Ext2Mcb = NULL;
307
308 DEBUG(DL_RES, ("Ext2LookupFile: %wZ\n", FullName));
309
310 /* check names and parameters */
311 if (FullName->Buffer[0] == L'\\') {
312 Parent = Vcb->McbTree;
313 } else if (Parent) {
314 bParent = TRUE;
315 } else {
316 Parent = Vcb->McbTree;
317 }
318
319 /* make sure the parent is NULL */
320 if (!IsMcbDirectory(Parent)) {
321 Status = STATUS_NOT_A_DIRECTORY;
322 _SEH2_LEAVE;
323 }
324
325 /* use symlink's target as parent directory */
326 if (IsMcbSymLink(Parent)) {
327 Parent = Parent->Target;
328 ASSERT(!IsMcbSymLink(Parent));
329 if (IsFileDeleted(Parent)) {
330 Status = STATUS_NOT_A_DIRECTORY;
331 _SEH2_LEAVE;
332 }
333 }
334
335 if (NULL == Parent) {
336 Status = STATUS_NOT_A_DIRECTORY;
337 _SEH2_LEAVE;
338 }
339
340 /* default is the parent Mcb*/
341 Ext2ReferMcb(Parent);
342 Mcb = Parent;
343
344 /* is empty file name or root node */
345 End = FullName->Length/sizeof(WCHAR);
346 if ( (End == 0) || (End == 1 &&
347 FullName->Buffer[0] == L'\\')) {
348 Status = STATUS_SUCCESS;
349 _SEH2_LEAVE;
350 }
351
352 /* is a directory expected ? */
353 if (FullName->Buffer[End - 1] == L'\\') {
354 bDirectory = TRUE;
355 }
356
357 /* loop with every sub name */
358 while (i < End) {
359
360 USHORT Start = 0;
361
362 /* zero the prefix '\' */
363 while (i < End && FullName->Buffer[i] == L'\\') i++;
364 Start = i;
365
366 /* zero the suffix '\' */
367 while (i < End && (FullName->Buffer[i] != L'\\')) i++;
368
369 if (i > Start) {
370
371 FileName = *FullName;
372 FileName.Buffer += Start;
373 FileName.Length = (USHORT)((i - Start) * 2);
374
375 /* make sure the parent is NULL */
376 if (!IsMcbDirectory(Parent)) {
377 Status = STATUS_NOT_A_DIRECTORY;
378 Ext2DerefMcb(Parent);
379 break;
380 }
381
382 if (IsMcbSymLink(Parent)) {
383 if (IsFileDeleted(Parent->Target)) {
384 Status = STATUS_NOT_A_DIRECTORY;
385 Ext2DerefMcb(Parent);
386 break;
387 } else {
388 Ext2ReferMcb(Parent->Target);
389 Ext2DerefMcb(Parent);
390 Parent = Parent->Target;
391 }
392 }
393
394 /* search cached Mcb nodes */
395 Mcb = Ext2SearchMcbWithoutLock(Parent, &FileName);
396
397 if (Mcb) {
398
399 /* derefer the parent Mcb */
400 Ext2DerefMcb(Parent);
401 Status = STATUS_SUCCESS;
402 Parent = Mcb;
403
404 if (IsMcbSymLink(Mcb) && IsFileDeleted(Mcb->Target) &&
405 Mcb->Refercount == 1) {
406
407 ASSERT(Mcb->Target);
408 ASSERT(Mcb->Target->Refercount > 0);
409 Ext2DerefMcb(Mcb->Target);
410 Mcb->Target = NULL;
411 ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
412 SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
413 Mcb->FileAttr = FILE_ATTRIBUTE_NORMAL;
414 }
415
416 } else {
417
418 /* need create new Mcb node */
419
420 /* is a valid ext2 name */
421 if (!Ext2IsNameValid(&FileName)) {
422 Status = STATUS_OBJECT_NAME_INVALID;
423 Ext2DerefMcb(Parent);
424 break;
425 }
426
427 /* seach the disk */
428 de = NULL;
429 Status = Ext2ScanDir (
430 IrpContext,
431 Vcb,
432 Parent,
433 &FileName,
434 &Inode,
435 &de);
436
437 if (NT_SUCCESS(Status)) {
438
439 /* check it's real parent */
440 ASSERT (!IsMcbSymLink(Parent));
441
442 /* allocate Mcb ... */
443 Mcb = Ext2AllocateMcb(Vcb, &FileName, &Parent->FullName, 0);
444 if (!Mcb) {
445 Status = STATUS_INSUFFICIENT_RESOURCES;
446 Ext2DerefMcb(Parent);
447 break;
448 }
449 Mcb->de = de;
450 Mcb->de->d_inode = &Mcb->Inode;
451 Mcb->Inode.i_ino = Inode;
452 Mcb->Inode.i_sb = &Vcb->sb;
453 de = NULL;
454
455 /* load inode information */
456 if (!Ext2LoadInode(Vcb, &Mcb->Inode)) {
457 Status = STATUS_CANT_WAIT;
458 Ext2DerefMcb(Parent);
459 Ext2FreeMcb(Vcb, Mcb);
460 break;
461 }
462
463 /* set inode attribute */
464 if (!Ext2CheckFileAccess(Vcb, Mcb, Ext2FileCanWrite)) {
465 SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY);
466 }
467
468 if (S_ISDIR(Mcb->Inode.i_mode)) {
469 SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY);
470 } else {
471 if (S_ISREG(Mcb->Inode.i_mode)) {
472 SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_NORMAL);
473 } else if (S_ISLNK(Mcb->Inode.i_mode)) {
474 SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_REPARSE_POINT);
475 } else {
476 SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
477 }
478 }
479
480 /* process special files under root directory */
481 if (IsMcbRoot(Parent)) {
482 /* set hidden and system attributes for
483 Recycled / RECYCLER / pagefile.sys */
484 BOOLEAN IsDirectory = IsMcbDirectory(Mcb);
485 if (Ext2IsSpecialSystemFile(&Mcb->ShortName, IsDirectory)) {
486 SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_HIDDEN);
487 SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_SYSTEM);
488 }
489 }
490
491 Mcb->CreationTime = Ext2NtTime(Mcb->Inode.i_ctime);
492 Mcb->LastAccessTime = Ext2NtTime(Mcb->Inode.i_atime);
493 Mcb->LastWriteTime = Ext2NtTime(Mcb->Inode.i_mtime);
494 Mcb->ChangeTime = Ext2NtTime(Mcb->Inode.i_mtime);
495
496 /* process symlink */
497 if (S_ISLNK(Mcb->Inode.i_mode) && !bNotFollow) {
498 Ext2FollowLink( IrpContext,
499 Vcb,
500 Parent,
501 Mcb,
502 Linkdep+1
503 );
504 }
505
506 /* add reference ... */
507 Ext2ReferMcb(Mcb);
508
509 /* add Mcb to it's parent tree*/
510 Ext2InsertMcb(Vcb, Parent, Mcb);
511
512 /* it's safe to deref Parent Mcb */
513 Ext2DerefMcb(Parent);
514
515 /* linking this Mcb*/
516 Ext2LinkTailMcb(Vcb, Mcb);
517
518 /* set parent to preare re-scan */
519 Parent = Mcb;
520
521 } else {
522
523 /* derefernce it's parent */
524 Ext2DerefMcb(Parent);
525 break;
526 }
527 }
528
529 } else {
530
531 /* there seems too many \ or / */
532 /* Mcb should be already set to Parent */
533 ASSERT(Mcb == Parent);
534 Status = STATUS_SUCCESS;
535 break;
536 }
537 }
538
539 } _SEH2_FINALLY {
540
541 if (de) {
542 Ext2FreeEntry(de);
543 }
544
545 if (NT_SUCCESS(Status)) {
546 if (bDirectory) {
547 if (IsMcbDirectory(Mcb)) {
548 *Ext2Mcb = Mcb;
549 } else {
550 Ext2DerefMcb(Mcb);
551 Status = STATUS_NOT_A_DIRECTORY;
552 }
553 } else {
554 *Ext2Mcb = Mcb;
555 }
556 }
557
558 if (LockAcquired) {
559 ExReleaseResourceLite(&Vcb->McbLock);
560 }
561 } _SEH2_END;
562
563 return Status;
564 }
565
566
567 NTSTATUS
568 Ext2ScanDir (
569 IN PEXT2_IRP_CONTEXT IrpContext,
570 IN PEXT2_VCB Vcb,
571 IN PEXT2_MCB Parent,
572 IN PUNICODE_STRING FileName,
573 OUT PULONG Inode,
574 OUT struct dentry **dentry
575 )
576 {
577 struct ext3_dir_entry_2 *dir_entry = NULL;
578 struct buffer_head *bh = NULL;
579 struct dentry *de = NULL;
580
581 NTSTATUS Status = STATUS_NO_SUCH_FILE;
582
583 DEBUG(DL_RES, ("Ext2ScanDir: %wZ\\%wZ\n", &Parent->FullName, FileName));
584
585 _SEH2_TRY {
586
587 /* grab parent's reference first */
588 Ext2ReferMcb(Parent);
589
590 /* bad request ! Can a man be pregnant ? Maybe:) */
591 if (!IsMcbDirectory(Parent)) {
592 Status = STATUS_NOT_A_DIRECTORY;
593 _SEH2_LEAVE;
594 }
595
596 /* parent is a symlink ? */
597 if IsMcbSymLink(Parent) {
598 if (Parent->Target) {
599 Ext2ReferMcb(Parent->Target);
600 Ext2DerefMcb(Parent);
601 Parent = Parent->Target;
602 ASSERT(!IsMcbSymLink(Parent));
603 } else {
604 DbgBreak();
605 Status = STATUS_NOT_A_DIRECTORY;
606 _SEH2_LEAVE;
607 }
608 }
609
610 de = Ext2BuildEntry(Vcb, Parent, FileName);
611 if (!de) {
612 DEBUG(DL_ERR, ( "Ex2ScanDir: failed to allocate dentry.\n"));
613 Status = STATUS_INSUFFICIENT_RESOURCES;
614 _SEH2_LEAVE;
615 }
616
617 bh = ext3_find_entry(IrpContext, de, &dir_entry);
618 if (dir_entry) {
619 Status = STATUS_SUCCESS;
620 *Inode = dir_entry->inode;
621 *dentry = de;
622 }
623
624 } _SEH2_FINALLY {
625
626 Ext2DerefMcb(Parent);
627
628 if (bh)
629 __brelse(bh);
630
631 if (!NT_SUCCESS(Status)) {
632 if (de)
633 Ext2FreeEntry(de);
634 }
635 } _SEH2_END;
636
637 return Status;
638 }
639
640 NTSTATUS Ext2AddDotEntries(struct ext2_icb *icb, struct inode *dir,
641 struct inode *inode)
642 {
643 struct ext3_dir_entry_2 * de;
644 struct buffer_head * bh;
645 ext3_lblk_t block = 0;
646 int rc = 0;
647
648 bh = ext3_append(icb, inode, &block, &rc);
649 if (!bh) {
650 goto errorout;
651 }
652
653 de = (struct ext3_dir_entry_2 *) bh->b_data;
654 de->inode = cpu_to_le32(inode->i_ino);
655 de->name_len = 1;
656 de->rec_len = cpu_to_le16(EXT3_DIR_REC_LEN(de->name_len));
657 strcpy (de->name, ".");
658 ext3_set_de_type(inode->i_sb, de, S_IFDIR);
659 de = (struct ext3_dir_entry_2 *)
660 ((char *) de + le16_to_cpu(de->rec_len));
661 de->inode = cpu_to_le32(dir->i_ino);
662 de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT3_DIR_REC_LEN(1));
663 de->name_len = 2;
664 strcpy (de->name, "..");
665 ext3_set_de_type(inode->i_sb, de, S_IFDIR);
666 inode->i_nlink = 2;
667 set_buffer_dirty(bh);
668 ext3_mark_inode_dirty(icb, inode);
669
670 errorout:
671 if (bh)
672 __brelse (bh);
673
674 return Ext2WinntError(rc);
675 }
676
677 NTSTATUS
678 Ext2CreateFile(
679 PEXT2_IRP_CONTEXT IrpContext,
680 PEXT2_VCB Vcb,
681 PBOOLEAN OpPostIrp
682 )
683 {
684 NTSTATUS Status = STATUS_UNSUCCESSFUL;
685 PIO_STACK_LOCATION IrpSp;
686 PEXT2_FCB Fcb = NULL;
687 PEXT2_MCB Mcb = NULL;
688 PEXT2_MCB SymLink = NULL;
689 PEXT2_CCB Ccb = NULL;
690
691 PEXT2_FCB ParentFcb = NULL;
692 PEXT2_MCB ParentMcb = NULL;
693
694 UNICODE_STRING FileName;
695 PIRP Irp;
696
697 ULONG Options;
698 ULONG CreateDisposition;
699
700 BOOLEAN bParentFcbCreated = FALSE;
701 #ifndef __REACTOS__
702 BOOLEAN bDir = FALSE;
703 #endif
704 BOOLEAN bFcbAllocated = FALSE;
705 BOOLEAN bCreated = FALSE;
706
707 BOOLEAN bMainResourceAcquired = FALSE;
708 BOOLEAN bFcbLockAcquired = FALSE;
709
710 BOOLEAN OpenDirectory;
711 BOOLEAN OpenTargetDirectory;
712 BOOLEAN CreateDirectory;
713 BOOLEAN SequentialOnly;
714 BOOLEAN NoIntermediateBuffering;
715 BOOLEAN IsPagingFile;
716 BOOLEAN DirectoryFile;
717 BOOLEAN NonDirectoryFile;
718 BOOLEAN NoEaKnowledge;
719 BOOLEAN DeleteOnClose;
720 BOOLEAN TemporaryFile;
721 BOOLEAN CaseSensitive;
722 BOOLEAN OpenReparsePoint;
723
724 ACCESS_MASK DesiredAccess;
725 ULONG ShareAccess;
726 ULONG CcbFlags = 0;
727
728 RtlZeroMemory(&FileName, sizeof(UNICODE_STRING));
729
730 Irp = IrpContext->Irp;
731 IrpSp = IoGetCurrentIrpStackLocation(Irp);
732
733 Options = IrpSp->Parameters.Create.Options;
734
735 DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
736 OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
737
738 NonDirectoryFile = IsFlagOn(Options, FILE_NON_DIRECTORY_FILE);
739 SequentialOnly = IsFlagOn(Options, FILE_SEQUENTIAL_ONLY);
740 NoIntermediateBuffering = IsFlagOn( Options, FILE_NO_INTERMEDIATE_BUFFERING );
741 NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
742 DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE);
743
744 /* Try to open reparse point (symlink) itself ? */
745 OpenReparsePoint = IsFlagOn(Options, FILE_OPEN_REPARSE_POINT);
746
747 CaseSensitive = IsFlagOn(IrpSp->Flags, SL_CASE_SENSITIVE);
748
749 TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes,
750 FILE_ATTRIBUTE_TEMPORARY );
751
752 CreateDisposition = (Options >> 24) & 0x000000ff;
753
754 IsPagingFile = IsFlagOn(IrpSp->Flags, SL_OPEN_PAGING_FILE);
755
756 CreateDirectory = (BOOLEAN)(DirectoryFile &&
757 ((CreateDisposition == FILE_CREATE) ||
758 (CreateDisposition == FILE_OPEN_IF)));
759
760 OpenDirectory = (BOOLEAN)(DirectoryFile &&
761 ((CreateDisposition == FILE_OPEN) ||
762 (CreateDisposition == FILE_OPEN_IF)));
763
764 DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
765 ShareAccess = IrpSp->Parameters.Create.ShareAccess;
766
767 *OpPostIrp = FALSE;
768
769 _SEH2_TRY {
770
771 FileName.MaximumLength = IrpSp->FileObject->FileName.MaximumLength;
772 FileName.Length = IrpSp->FileObject->FileName.Length;
773
774 if (IrpSp->FileObject->RelatedFileObject) {
775 ParentFcb = (PEXT2_FCB)(IrpSp->FileObject->RelatedFileObject->FsContext);
776 }
777
778 if (ParentFcb) {
779 ParentMcb = ParentFcb->Mcb;
780 Ext2ReferMcb(ParentMcb);
781 ParentFcb = NULL;
782 }
783
784 if (FileName.Length == 0) {
785
786 if (ParentMcb) {
787 Mcb = ParentMcb;
788 Ext2ReferMcb(Mcb);
789 Status = STATUS_SUCCESS;
790 goto McbExisting;
791 } else {
792 DbgBreak();
793 Status = STATUS_INVALID_PARAMETER;
794 _SEH2_LEAVE;
795 }
796 }
797
798 FileName.Buffer = Ext2AllocatePool(
799 PagedPool,
800 FileName.MaximumLength,
801 EXT2_FNAME_MAGIC
802 );
803
804 if (!FileName.Buffer) {
805 DEBUG(DL_ERR, ( "Ex2CreateFile: failed to allocate FileName.\n"));
806 Status = STATUS_INSUFFICIENT_RESOURCES;
807 _SEH2_LEAVE;
808 }
809
810 INC_MEM_COUNT(PS_FILE_NAME, FileName.Buffer, FileName.MaximumLength);
811
812 RtlZeroMemory(FileName.Buffer, FileName.MaximumLength);
813 RtlCopyMemory(FileName.Buffer, IrpSp->FileObject->FileName.Buffer, FileName.Length);
814
815 if (IrpSp->FileObject->RelatedFileObject && FileName.Buffer[0] == L'\\') {
816 Status = STATUS_INVALID_PARAMETER;
817 _SEH2_LEAVE;
818 }
819
820 if ((FileName.Length > sizeof(WCHAR)) &&
821 (FileName.Buffer[1] == L'\\') &&
822 (FileName.Buffer[0] == L'\\')) {
823
824 FileName.Length -= sizeof(WCHAR);
825
826 RtlMoveMemory( &FileName.Buffer[0],
827 &FileName.Buffer[1],
828 FileName.Length );
829
830 //
831 // Bad Name if there are still beginning backslashes.
832 //
833
834 if ((FileName.Length > sizeof(WCHAR)) &&
835 (FileName.Buffer[1] == L'\\') &&
836 (FileName.Buffer[0] == L'\\')) {
837
838 Status = STATUS_OBJECT_NAME_INVALID;
839 _SEH2_LEAVE;
840 }
841 }
842
843 if (IsFlagOn(Options, FILE_OPEN_BY_FILE_ID)) {
844 Status = STATUS_NOT_IMPLEMENTED;
845 _SEH2_LEAVE;
846 }
847
848 DEBUG(DL_INF, ( "Ext2CreateFile: %wZ Paging=%d Option: %xh:"
849 "Dir=%d NonDir=%d OpenTarget=%d NC=%d DeleteOnClose=%d\n",
850 &FileName, IsPagingFile, IrpSp->Parameters.Create.Options,
851 DirectoryFile, NonDirectoryFile, OpenTargetDirectory,
852 NoIntermediateBuffering, DeleteOnClose ));
853
854 DEBUG(DL_RES, ("Ext2CreateFile: Lookup 1st: %wZ at %S\n",
855 &FileName, ParentMcb ? ParentMcb->FullName.Buffer : L" "));
856 Status = Ext2LookupFile(
857 IrpContext,
858 Vcb,
859 &FileName,
860 ParentMcb,
861 &Mcb,
862 0 /* always follow link */
863 );
864 McbExisting:
865
866 if (!NT_SUCCESS(Status)) {
867
868 UNICODE_STRING PathName;
869 UNICODE_STRING RealName;
870 UNICODE_STRING RemainName;
871
872 #ifndef __REACTOS__
873 LONG i = 0;
874 #endif
875
876 PathName = FileName;
877 Mcb = NULL;
878
879 if (PathName.Buffer[PathName.Length/2 - 1] == L'\\') {
880 if (DirectoryFile) {
881 PathName.Length -=2;
882 PathName.Buffer[PathName.Length/2] = 0;
883 } else {
884 DirectoryFile = TRUE;
885 }
886 }
887
888 if (!ParentMcb) {
889 if (PathName.Buffer[0] != L'\\') {
890 Status = STATUS_OBJECT_PATH_NOT_FOUND;
891 _SEH2_LEAVE;
892 } else {
893 ParentMcb = Vcb->McbTree;
894 Ext2ReferMcb(ParentMcb);
895 }
896 }
897
898 Dissecting:
899
900 FsRtlDissectName(PathName, &RealName, &RemainName);
901
902 if (((RemainName.Length != 0) && (RemainName.Buffer[0] == L'\\')) ||
903 (RealName.Length >= 256 * sizeof(WCHAR))) {
904 Status = STATUS_OBJECT_NAME_INVALID;
905 _SEH2_LEAVE;
906 }
907
908 if (RemainName.Length != 0) {
909
910 PEXT2_MCB RetMcb = NULL;
911
912 DEBUG(DL_RES, ("Ext2CreateFile: Lookup 2nd: %wZ\\%wZ\n",
913 &ParentMcb->FullName, &RealName));
914
915 Status = Ext2LookupFile (
916 IrpContext,
917 Vcb,
918 &RealName,
919 ParentMcb,
920 &RetMcb,
921 0);
922
923 /* quit name resolving loop */
924 if (!NT_SUCCESS(Status)) {
925 if (Status == STATUS_NO_SUCH_FILE && RemainName.Length != 0) {
926 Status = STATUS_OBJECT_PATH_NOT_FOUND;
927 }
928 _SEH2_LEAVE;
929 }
930
931 /* deref ParentMcb */
932 Ext2DerefMcb(ParentMcb);
933
934 /* RetMcb is already refered */
935 ParentMcb = RetMcb;
936 PathName = RemainName;
937
938 /* symlink must use it's target */
939 if (IsMcbSymLink(ParentMcb)) {
940 Ext2ReferMcb(ParentMcb->Target);
941 Ext2DerefMcb(ParentMcb);
942 ParentMcb = ParentMcb->Target;
943 ASSERT(!IsMcbSymLink(ParentMcb));
944 }
945
946 goto Dissecting;
947 }
948
949 /* is name valid */
950 if ( FsRtlDoesNameContainWildCards(&RealName) ||
951 !Ext2IsNameValid(&RealName)) {
952 Status = STATUS_OBJECT_NAME_INVALID;
953 _SEH2_LEAVE;
954 }
955
956 if (!bFcbLockAcquired) {
957 ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
958 bFcbLockAcquired = TRUE;
959 }
960
961 /* get the ParentFcb, allocate it if needed ... */
962 ParentFcb = ParentMcb->Fcb;
963 if (!ParentFcb) {
964 ParentFcb = Ext2AllocateFcb(Vcb, ParentMcb);
965 if (!ParentFcb) {
966 Status = STATUS_INSUFFICIENT_RESOURCES;
967 _SEH2_LEAVE;
968 }
969 bParentFcbCreated = TRUE;
970 }
971 Ext2ReferXcb(&ParentFcb->ReferenceCount);
972
973 if (bFcbLockAcquired) {
974 ExReleaseResourceLite(&Vcb->FcbLock);
975 bFcbLockAcquired = FALSE;
976 }
977
978 // We need to create a new one ?
979 if ((CreateDisposition == FILE_CREATE ) ||
980 (CreateDisposition == FILE_SUPERSEDE) ||
981 (CreateDisposition == FILE_OPEN_IF) ||
982 (CreateDisposition == FILE_OVERWRITE_IF)) {
983
984 if (IsVcbReadOnly(Vcb)) {
985 Status = STATUS_MEDIA_WRITE_PROTECTED;
986 _SEH2_LEAVE;
987 }
988
989 if (!Ext2CheckFileAccess(Vcb, ParentMcb, Ext2FileCanWrite)) {
990 Status = STATUS_ACCESS_DENIED;
991 _SEH2_LEAVE;
992 }
993
994 if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
995 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
996 Vcb->Vpb->RealDevice );
997 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
998 Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
999 }
1000
1001 if (DirectoryFile) {
1002 if (TemporaryFile) {
1003 DbgBreak();
1004 Status = STATUS_INVALID_PARAMETER;
1005 _SEH2_LEAVE;
1006 }
1007 }
1008
1009 if (!ParentFcb) {
1010 Status = STATUS_OBJECT_PATH_NOT_FOUND;
1011 _SEH2_LEAVE;
1012 }
1013
1014 /* allocate inode and construct entry for this file */
1015 Status = Ext2CreateInode(
1016 IrpContext,
1017 Vcb,
1018 ParentFcb,
1019 DirectoryFile ? EXT2_FT_DIR : EXT2_FT_REG_FILE,
1020 IrpSp->Parameters.Create.FileAttributes,
1021 &RealName
1022 );
1023
1024 if (!NT_SUCCESS(Status)) {
1025 DbgBreak();
1026 _SEH2_LEAVE;
1027 }
1028
1029 bCreated = TRUE;
1030 DEBUG(DL_RES, ("Ext2CreateFile: Confirm creation: %wZ\\%wZ\n",
1031 &ParentMcb->FullName, &RealName));
1032
1033 Irp->IoStatus.Information = FILE_CREATED;
1034 Status = Ext2LookupFile (
1035 IrpContext,
1036 Vcb,
1037 &RealName,
1038 ParentMcb,
1039 &Mcb,
1040 0);
1041 if (!NT_SUCCESS(Status)) {
1042 DbgBreak();
1043 }
1044
1045 } else if (OpenTargetDirectory) {
1046
1047 if (IsVcbReadOnly(Vcb)) {
1048 Status = STATUS_MEDIA_WRITE_PROTECTED;
1049 _SEH2_LEAVE;
1050 }
1051
1052 if (!ParentFcb) {
1053 Status = STATUS_OBJECT_PATH_NOT_FOUND;
1054 _SEH2_LEAVE;
1055 }
1056
1057 RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
1058 IrpSp->FileObject->FileName.MaximumLength);
1059 IrpSp->FileObject->FileName.Length = RealName.Length;
1060
1061 RtlCopyMemory( IrpSp->FileObject->FileName.Buffer,
1062 RealName.Buffer,
1063 RealName.Length );
1064
1065 Fcb = ParentFcb;
1066 Mcb = Fcb->Mcb;
1067 Ext2ReferMcb(Mcb);
1068
1069 Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
1070 Status = STATUS_SUCCESS;
1071
1072 } else {
1073
1074 Status = STATUS_OBJECT_NAME_NOT_FOUND;
1075 _SEH2_LEAVE;
1076 }
1077
1078 } else { // File / Dir already exists.
1079
1080 /* here already get Mcb referred */
1081 if (OpenTargetDirectory) {
1082
1083 UNICODE_STRING RealName = FileName;
1084 USHORT i = 0;
1085
1086 while (RealName.Buffer[RealName.Length/2 - 1] == L'\\') {
1087 RealName.Length -= sizeof(WCHAR);
1088 RealName.Buffer[RealName.Length/2] = 0;
1089 }
1090 i = RealName.Length/2;
1091 while (i > 0 && RealName.Buffer[i - 1] != L'\\')
1092 i--;
1093
1094 if (IsVcbReadOnly(Vcb)) {
1095 Status = STATUS_MEDIA_WRITE_PROTECTED;
1096 Ext2DerefMcb(Mcb);
1097 _SEH2_LEAVE;
1098 }
1099
1100 Irp->IoStatus.Information = FILE_EXISTS;
1101 Status = STATUS_SUCCESS;
1102
1103 RtlZeroMemory( IrpSp->FileObject->FileName.Buffer,
1104 IrpSp->FileObject->FileName.MaximumLength);
1105 IrpSp->FileObject->FileName.Length = RealName.Length - i * sizeof(WCHAR);
1106 RtlCopyMemory( IrpSp->FileObject->FileName.Buffer, &RealName.Buffer[i],
1107 IrpSp->FileObject->FileName.Length );
1108
1109 // use's it's parent since it's open-target operation
1110 Ext2ReferMcb(Mcb->Parent);
1111 Ext2DerefMcb(Mcb);
1112 Mcb = Mcb->Parent;
1113
1114 goto Openit;
1115 }
1116
1117 // We can not create if one exists
1118 if (CreateDisposition == FILE_CREATE) {
1119 Irp->IoStatus.Information = FILE_EXISTS;
1120 Status = STATUS_OBJECT_NAME_COLLISION;
1121 Ext2DerefMcb(Mcb);
1122 _SEH2_LEAVE;
1123 }
1124
1125 /* directory forbits us to do the followings ... */
1126 if (IsMcbDirectory(Mcb)) {
1127
1128 if ((CreateDisposition != FILE_OPEN) &&
1129 (CreateDisposition != FILE_OPEN_IF)) {
1130
1131 Status = STATUS_OBJECT_NAME_COLLISION;
1132 Ext2DerefMcb(Mcb);
1133 _SEH2_LEAVE;
1134 }
1135
1136 if (NonDirectoryFile) {
1137 Status = STATUS_FILE_IS_A_DIRECTORY;
1138 Ext2DerefMcb(Mcb);
1139 _SEH2_LEAVE;
1140 }
1141
1142 if (Mcb->Inode.i_ino == EXT2_ROOT_INO) {
1143
1144 if (OpenTargetDirectory) {
1145 DbgBreak();
1146 Status = STATUS_INVALID_PARAMETER;
1147 Ext2DerefMcb(Mcb);
1148 _SEH2_LEAVE;
1149 }
1150 }
1151
1152 } else {
1153
1154 if (DirectoryFile) {
1155 Status = STATUS_NOT_A_DIRECTORY;;
1156 Ext2DerefMcb(Mcb);
1157 _SEH2_LEAVE;
1158 }
1159 }
1160
1161 Irp->IoStatus.Information = FILE_OPENED;
1162 }
1163
1164 Openit:
1165
1166 if (!bFcbLockAcquired) {
1167 ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE);
1168 bFcbLockAcquired = TRUE;
1169 }
1170
1171 /* Mcb should already be referred and symlink is too */
1172 if (Mcb) {
1173
1174 ASSERT(Mcb->Refercount > 0);
1175
1176 /* refer it's target if it's a symlink, so both refered */
1177 if (IsMcbSymLink(Mcb)) {
1178
1179 if (OpenReparsePoint) {
1180 /* set Ccb flag */
1181 CcbFlags = CCB_OPEN_REPARSE_POINT;
1182 } else if (IsFileDeleted(Mcb->Target)) {
1183 DbgBreak();
1184 SetLongFlag(Mcb->Flags, MCB_TYPE_SPECIAL);
1185 ClearLongFlag(Mcb->Flags, MCB_TYPE_SYMLINK);
1186 Ext2DerefMcb(Mcb->Target);
1187 Mcb->Target = NULL;
1188 } else {
1189 SymLink = Mcb;
1190 Mcb = Mcb->Target;
1191 Ext2ReferMcb(Mcb);
1192 ASSERT (!IsMcbSymLink(Mcb));
1193 }
1194 }
1195
1196 // Check readonly flag
1197 if (BooleanFlagOn(DesiredAccess, FILE_GENERIC_READ) &&
1198 !Ext2CheckFileAccess(Vcb, Mcb, Ext2FileCanRead)) {
1199 Status = STATUS_ACCESS_DENIED;
1200 _SEH2_LEAVE;
1201 }
1202 if (!Ext2CheckFileAccess(Vcb, Mcb, Ext2FileCanWrite)) {
1203 if (BooleanFlagOn(DesiredAccess, FILE_WRITE_DATA | FILE_APPEND_DATA |
1204 FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD)) {
1205 Status = STATUS_ACCESS_DENIED;
1206 _SEH2_LEAVE;
1207 } else if (IsFlagOn(Options, FILE_DELETE_ON_CLOSE )) {
1208 Status = STATUS_CANNOT_DELETE;
1209 _SEH2_LEAVE;
1210 }
1211 }
1212
1213 Fcb = Mcb->Fcb;
1214 if (Fcb == NULL) {
1215
1216 /* allocate Fcb for this file */
1217 Fcb = Ext2AllocateFcb (Vcb, Mcb);
1218 if (Fcb) {
1219 bFcbAllocated = TRUE;
1220 } else {
1221 Status = STATUS_INSUFFICIENT_RESOURCES;
1222 }
1223 } else {
1224 if (IsPagingFile) {
1225 Status = STATUS_SHARING_VIOLATION;
1226 Fcb = NULL;
1227 }
1228 }
1229
1230 /* Now it's safe to defer Mcb */
1231 Ext2DerefMcb(Mcb);
1232 }
1233
1234 if (Fcb) {
1235 /* grab Fcb's reference first to avoid the race between
1236 Ext2Close (it could free the Fcb we are accessing) */
1237 Ext2ReferXcb(&Fcb->ReferenceCount);
1238 }
1239
1240 ExReleaseResourceLite(&Vcb->FcbLock);
1241 bFcbLockAcquired = FALSE;
1242
1243 if (Fcb) {
1244
1245 ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE);
1246 bMainResourceAcquired = TRUE;
1247
1248 /* Open target directory ? */
1249 if (NULL == Mcb) {
1250 DbgBreak();
1251 Mcb = Fcb->Mcb;
1252 }
1253
1254 /* check Mcb reference */
1255 ASSERT(Fcb->Mcb->Refercount > 0);
1256
1257 /* file delted ? */
1258 if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) {
1259 Status = STATUS_FILE_DELETED;
1260 _SEH2_LEAVE;
1261 }
1262
1263 if (DeleteOnClose && NULL == SymLink) {
1264 Status = Ext2IsFileRemovable(IrpContext, Vcb, Fcb, Ccb);
1265 if (!NT_SUCCESS(Status)) {
1266 _SEH2_LEAVE;
1267 }
1268 }
1269
1270 /* check access and oplock access for opened files */
1271 if (!bFcbAllocated && !IsDirectory(Fcb)) {
1272
1273 /* whether there's batch oplock grabed on the file */
1274 if (FsRtlCurrentBatchOplock(&Fcb->Oplock)) {
1275
1276 Irp->IoStatus.Information = FILE_OPBATCH_BREAK_UNDERWAY;
1277
1278 /* break the batch lock if the sharing check fails */
1279 Status = FsRtlCheckOplock( &Fcb->Oplock,
1280 IrpContext->Irp,
1281 IrpContext,
1282 Ext2OplockComplete,
1283 Ext2LockIrp );
1284
1285 if ( Status != STATUS_SUCCESS &&
1286 Status != STATUS_OPLOCK_BREAK_IN_PROGRESS) {
1287 *OpPostIrp = TRUE;
1288 _SEH2_LEAVE;
1289 }
1290 }
1291 }
1292
1293 if (bCreated) {
1294
1295 //
1296 // This file is just created.
1297 //
1298
1299 if (DirectoryFile) {
1300
1301 Status = Ext2AddDotEntries(IrpContext, &ParentMcb->Inode, &Mcb->Inode);
1302 if (!NT_SUCCESS(Status)) {
1303 Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
1304 _SEH2_LEAVE;
1305 }
1306
1307 } else {
1308
1309 if ((LONGLONG)ext3_free_blocks_count(SUPER_BLOCK) <=
1310 Ext2TotalBlocks(Vcb, &Irp->Overlay.AllocationSize, NULL)) {
1311 DbgBreak();
1312 Status = STATUS_DISK_FULL;
1313 _SEH2_LEAVE;
1314 }
1315
1316 /* disable data blocks allocation */
1317 #if 0
1318 Fcb->Header.AllocationSize.QuadPart =
1319 Irp->Overlay.AllocationSize.QuadPart;
1320
1321 if (Fcb->Header.AllocationSize.QuadPart > 0) {
1322 Status = Ext2ExpandFile(IrpContext,
1323 Vcb,
1324 Fcb->Mcb,
1325 &(Fcb->Header.AllocationSize)
1326 );
1327 SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
1328 if (!NT_SUCCESS(Status)) {
1329 Fcb->Header.AllocationSize.QuadPart = 0;
1330 Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb,
1331 &Fcb->Header.AllocationSize);
1332 _SEH2_LEAVE;
1333 }
1334 }
1335 #endif
1336 }
1337
1338 } else {
1339
1340 //
1341 // This file alreayd exists.
1342 //
1343
1344 if (DeleteOnClose) {
1345
1346 if (IsVcbReadOnly(Vcb)) {
1347 Status = STATUS_MEDIA_WRITE_PROTECTED;
1348 _SEH2_LEAVE;
1349 }
1350
1351 if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
1352 Status = STATUS_MEDIA_WRITE_PROTECTED;
1353
1354 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
1355 Vcb->Vpb->RealDevice );
1356
1357 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
1358
1359 Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
1360 }
1361
1362 } else {
1363
1364 //
1365 // Just to Open file (Open/OverWrite ...)
1366 //
1367
1368 if ((!IsDirectory(Fcb)) && (IsFlagOn(IrpSp->FileObject->Flags,
1369 FO_NO_INTERMEDIATE_BUFFERING))) {
1370 Fcb->Header.IsFastIoPossible = FastIoIsPossible;
1371
1372 if (Fcb->SectionObject.DataSectionObject != NULL) {
1373
1374 if (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount) {
1375
1376 if (!IsVcbReadOnly(Vcb)) {
1377 CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
1378 ClearLongFlag(Fcb->Flags, FCB_FILE_MODIFIED);
1379 }
1380
1381 CcPurgeCacheSection(&Fcb->SectionObject,
1382 NULL,
1383 0,
1384 FALSE );
1385 }
1386 }
1387 }
1388 }
1389 }
1390
1391 if (!IsDirectory(Fcb)) {
1392
1393 if (!IsVcbReadOnly(Vcb)) {
1394 if ((CreateDisposition == FILE_SUPERSEDE) && !IsPagingFile) {
1395 DesiredAccess |= DELETE;
1396 } else if (((CreateDisposition == FILE_OVERWRITE) ||
1397 (CreateDisposition == FILE_OVERWRITE_IF)) && !IsPagingFile) {
1398 DesiredAccess |= (FILE_WRITE_DATA | FILE_WRITE_EA |
1399 FILE_WRITE_ATTRIBUTES );
1400 }
1401 }
1402
1403 if (!bFcbAllocated) {
1404
1405 //
1406 // check the oplock state of the file
1407 //
1408
1409 Status = FsRtlCheckOplock( &Fcb->Oplock,
1410 IrpContext->Irp,
1411 IrpContext,
1412 Ext2OplockComplete,
1413 Ext2LockIrp );
1414
1415 if ( Status != STATUS_SUCCESS &&
1416 Status != STATUS_OPLOCK_BREAK_IN_PROGRESS) {
1417 *OpPostIrp = TRUE;
1418 _SEH2_LEAVE;
1419 }
1420 }
1421 }
1422
1423 if (Fcb->OpenHandleCount > 0) {
1424
1425 /* check the shrae access conflicts */
1426 Status = IoCheckShareAccess( DesiredAccess,
1427 ShareAccess,
1428 IrpSp->FileObject,
1429 &(Fcb->ShareAccess),
1430 TRUE );
1431 if (!NT_SUCCESS(Status)) {
1432 _SEH2_LEAVE;
1433 }
1434
1435 } else {
1436
1437 /* set share access rights */
1438 IoSetShareAccess( DesiredAccess,
1439 ShareAccess,
1440 IrpSp->FileObject,
1441 &(Fcb->ShareAccess) );
1442 }
1443
1444 Ccb = Ext2AllocateCcb(CcbFlags, SymLink);
1445 if (!Ccb) {
1446 Status = STATUS_INSUFFICIENT_RESOURCES;
1447 DbgBreak();
1448 _SEH2_LEAVE;
1449 }
1450
1451 if (DeleteOnClose)
1452 SetLongFlag(Ccb->Flags, CCB_DELETE_ON_CLOSE);
1453
1454 if (SymLink)
1455 Ccb->filp.f_dentry = SymLink->de;
1456 else
1457 Ccb->filp.f_dentry = Fcb->Mcb->de;
1458
1459 Ccb->filp.f_version = Fcb->Mcb->Inode.i_version;
1460 Ext2ReferXcb(&Fcb->OpenHandleCount);
1461 Ext2ReferXcb(&Fcb->ReferenceCount);
1462
1463 if (!IsDirectory(Fcb)) {
1464 if (NoIntermediateBuffering) {
1465 Fcb->NonCachedOpenCount++;
1466 SetFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
1467 } else {
1468 SetFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
1469 }
1470 }
1471
1472 Ext2ReferXcb(&Vcb->OpenHandleCount);
1473 Ext2ReferXcb(&Vcb->ReferenceCount);
1474
1475 IrpSp->FileObject->FsContext = (void*) Fcb;
1476 IrpSp->FileObject->FsContext2 = (void*) Ccb;
1477 IrpSp->FileObject->PrivateCacheMap = NULL;
1478 IrpSp->FileObject->SectionObjectPointer = &(Fcb->SectionObject);
1479
1480 DEBUG(DL_INF, ( "Ext2CreateFile: %wZ OpenCount=%u ReferCount=%u NonCachedCount=%u\n",
1481 &Fcb->Mcb->FullName, Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->NonCachedOpenCount));
1482
1483 Status = STATUS_SUCCESS;
1484
1485 if (bCreated) {
1486
1487 if (IsDirectory(Fcb)) {
1488 Ext2NotifyReportChange(
1489 IrpContext,
1490 Vcb,
1491 Fcb->Mcb,
1492 FILE_NOTIFY_CHANGE_DIR_NAME,
1493 FILE_ACTION_ADDED );
1494 } else {
1495 Ext2NotifyReportChange(
1496 IrpContext,
1497 Vcb,
1498 Fcb->Mcb,
1499 FILE_NOTIFY_CHANGE_FILE_NAME,
1500 FILE_ACTION_ADDED );
1501 }
1502
1503 } else if (!IsDirectory(Fcb)) {
1504
1505 if ( DeleteOnClose ||
1506 IsFlagOn(DesiredAccess, FILE_WRITE_DATA) ||
1507 (CreateDisposition == FILE_OVERWRITE) ||
1508 (CreateDisposition == FILE_OVERWRITE_IF)) {
1509 if (!MmFlushImageSection( &Fcb->SectionObject,
1510 MmFlushForWrite )) {
1511
1512 Status = DeleteOnClose ? STATUS_CANNOT_DELETE :
1513 STATUS_SHARING_VIOLATION;
1514 _SEH2_LEAVE;
1515 }
1516 }
1517
1518 if ((CreateDisposition == FILE_SUPERSEDE) ||
1519 (CreateDisposition == FILE_OVERWRITE) ||
1520 (CreateDisposition == FILE_OVERWRITE_IF)) {
1521
1522 if (IsDirectory(Fcb)) {
1523 Status = STATUS_FILE_IS_A_DIRECTORY;
1524 _SEH2_LEAVE;
1525 }
1526
1527 if (SymLink != NULL) {
1528 DbgBreak();
1529 Status = STATUS_INVALID_PARAMETER;
1530 _SEH2_LEAVE;
1531 }
1532
1533 if (IsVcbReadOnly(Vcb)) {
1534 Status = STATUS_MEDIA_WRITE_PROTECTED;
1535 _SEH2_LEAVE;
1536 }
1537
1538 if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
1539
1540 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
1541 Vcb->Vpb->RealDevice );
1542 SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
1543 Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
1544 }
1545
1546 Status = Ext2SupersedeOrOverWriteFile(
1547 IrpContext,
1548 IrpSp->FileObject,
1549 Vcb,
1550 Fcb,
1551 &Irp->Overlay.AllocationSize,
1552 CreateDisposition );
1553
1554 if (!NT_SUCCESS(Status)) {
1555 DbgBreak();
1556 _SEH2_LEAVE;
1557 }
1558
1559 Ext2NotifyReportChange(
1560 IrpContext,
1561 Vcb,
1562 Fcb->Mcb,
1563 FILE_NOTIFY_CHANGE_LAST_WRITE |
1564 FILE_NOTIFY_CHANGE_ATTRIBUTES |
1565 FILE_NOTIFY_CHANGE_SIZE,
1566 FILE_ACTION_MODIFIED );
1567
1568
1569 if (CreateDisposition == FILE_SUPERSEDE) {
1570 Irp->IoStatus.Information = FILE_SUPERSEDED;
1571 } else {
1572 Irp->IoStatus.Information = FILE_OVERWRITTEN;
1573 }
1574 }
1575 }
1576
1577 } else {
1578 DbgBreak();
1579 _SEH2_LEAVE;
1580 }
1581
1582 } _SEH2_FINALLY {
1583
1584 if (bFcbLockAcquired) {
1585 ExReleaseResourceLite(&Vcb->FcbLock);
1586 }
1587
1588 if (ParentMcb) {
1589 Ext2DerefMcb(ParentMcb);
1590 }
1591
1592 /* cleanup Fcb and Ccb, Mcb if necessary */
1593 if (!NT_SUCCESS(Status)) {
1594
1595 if (Ccb != NULL) {
1596
1597 DbgBreak();
1598
1599 ASSERT(Fcb != NULL);
1600 ASSERT(Fcb->Mcb != NULL);
1601
1602 DEBUG(DL_ERR, ("Ext2CreateFile: failed to create %wZ status = %xh\n",
1603 &Fcb->Mcb->FullName, Status));
1604
1605 Ext2DerefXcb(&Fcb->OpenHandleCount);
1606 Ext2DerefXcb(&Fcb->ReferenceCount);
1607
1608 if (!IsDirectory(Fcb)) {
1609 if (NoIntermediateBuffering) {
1610 Fcb->NonCachedOpenCount--;
1611 } else {
1612 ClearFlag(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED);
1613 }
1614 }
1615
1616 Ext2DerefXcb(&Vcb->OpenHandleCount);
1617 Ext2DerefXcb(&Vcb->ReferenceCount);
1618
1619 IoRemoveShareAccess(IrpSp->FileObject, &Fcb->ShareAccess);
1620
1621 IrpSp->FileObject->FsContext = NULL;
1622 IrpSp->FileObject->FsContext2 = NULL;
1623 IrpSp->FileObject->PrivateCacheMap = NULL;
1624 IrpSp->FileObject->SectionObjectPointer = NULL;
1625
1626 Ext2FreeCcb(Vcb, Ccb);
1627 }
1628
1629 if (Fcb != NULL) {
1630
1631 if (IsFlagOn(Fcb->Flags, FCB_ALLOC_IN_CREATE)) {
1632 LARGE_INTEGER Size;
1633 ExAcquireResourceExclusiveLite(&Fcb->PagingIoResource, TRUE);
1634 _SEH2_TRY {
1635 Size.QuadPart = 0;
1636 Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
1637 } _SEH2_FINALLY {
1638 ExReleaseResourceLite(&Fcb->PagingIoResource);
1639 } _SEH2_END;
1640 }
1641
1642 if (bCreated) {
1643 Ext2DeleteFile(IrpContext, Vcb, Fcb, Mcb);
1644 }
1645 }
1646 }
1647
1648 if (bMainResourceAcquired) {
1649 ExReleaseResourceLite(&Fcb->MainResource);
1650 }
1651
1652 /* free file name buffer */
1653 if (FileName.Buffer) {
1654 DEC_MEM_COUNT(PS_FILE_NAME, FileName.Buffer, FileName.MaximumLength);
1655 Ext2FreePool(FileName.Buffer, EXT2_FNAME_MAGIC);
1656 }
1657
1658 /* dereference Fcb and parent */
1659 if (Fcb) {
1660 Ext2ReleaseFcb(Fcb);
1661 }
1662 if (ParentFcb) {
1663 Ext2ReleaseFcb(ParentFcb);
1664 }
1665
1666 /* drop SymLink's refer: If succeeds, Ext2AllocateCcb should refer
1667 it already. It fails, we need release the refer to let it freed */
1668 if (SymLink) {
1669 Ext2DerefMcb(SymLink);
1670 }
1671 } _SEH2_END;
1672
1673 return Status;
1674 }
1675
1676 NTSTATUS
1677 Ext2CreateVolume(PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb)
1678 {
1679 PIO_STACK_LOCATION IrpSp;
1680 PIRP Irp;
1681 PEXT2_CCB Ccb;
1682
1683 NTSTATUS Status;
1684
1685 ACCESS_MASK DesiredAccess;
1686 ULONG ShareAccess;
1687
1688 ULONG Options;
1689 BOOLEAN DirectoryFile;
1690 BOOLEAN OpenTargetDirectory;
1691
1692 ULONG CreateDisposition;
1693
1694 Irp = IrpContext->Irp;
1695 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1696
1697 Options = IrpSp->Parameters.Create.Options;
1698
1699 DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
1700 OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);
1701
1702 CreateDisposition = (Options >> 24) & 0x000000ff;
1703
1704 DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
1705 ShareAccess = IrpSp->Parameters.Create.ShareAccess;
1706
1707 if (DirectoryFile) {
1708 return STATUS_NOT_A_DIRECTORY;
1709 }
1710
1711 if (OpenTargetDirectory) {
1712 DbgBreak();
1713 return STATUS_INVALID_PARAMETER;
1714 }
1715
1716 if ( (CreateDisposition != FILE_OPEN) &&
1717 (CreateDisposition != FILE_OPEN_IF) ) {
1718 return STATUS_ACCESS_DENIED;
1719 }
1720
1721 if ( !FlagOn(ShareAccess, FILE_SHARE_READ) &&
1722 Vcb->OpenVolumeCount != 0 ) {
1723 return STATUS_SHARING_VIOLATION;
1724 }
1725
1726 Ccb = Ext2AllocateCcb(0, NULL);
1727 if (Ccb == NULL) {
1728 Status = STATUS_INSUFFICIENT_RESOURCES;
1729 goto errorout;
1730 }
1731
1732 Status = STATUS_SUCCESS;
1733
1734 if (Vcb->OpenVolumeCount > 0) {
1735 Status = IoCheckShareAccess( DesiredAccess, ShareAccess,
1736 IrpSp->FileObject,
1737 &(Vcb->ShareAccess), TRUE);
1738
1739 if (!NT_SUCCESS(Status)) {
1740 goto errorout;
1741 }
1742 } else {
1743 IoSetShareAccess( DesiredAccess, ShareAccess,
1744 IrpSp->FileObject,
1745 &(Vcb->ShareAccess) );
1746 }
1747
1748
1749 if (Vcb->OpenVolumeCount == 0 &&
1750 !IsFlagOn(ShareAccess, FILE_SHARE_READ) &&
1751 !IsFlagOn(ShareAccess, FILE_SHARE_WRITE) ){
1752
1753 if (!IsVcbReadOnly(Vcb)) {
1754 Ext2FlushFiles(IrpContext, Vcb, FALSE);
1755 Ext2FlushVolume(IrpContext, Vcb, FALSE);
1756 }
1757
1758 SetLongFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
1759 Vcb->LockFile = IrpSp->FileObject;
1760 } else {
1761 if (FlagOn(DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA) ) {
1762 if (!IsVcbReadOnly(Vcb)) {
1763 Ext2FlushFiles(IrpContext, Vcb, FALSE);
1764 Ext2FlushVolume(IrpContext, Vcb, FALSE);
1765 }
1766 }
1767 }
1768
1769 IrpSp->FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
1770 IrpSp->FileObject->FsContext = Vcb;
1771 IrpSp->FileObject->FsContext2 = Ccb;
1772 IrpSp->FileObject->Vpb = Vcb->Vpb;
1773
1774 Ext2ReferXcb(&Vcb->ReferenceCount);
1775 Ext2ReferXcb(&Vcb->OpenHandleCount);
1776 Ext2ReferXcb(&Vcb->OpenVolumeCount);
1777
1778 Irp->IoStatus.Information = FILE_OPENED;
1779
1780 errorout:
1781
1782 return Status;
1783 }
1784
1785
1786 NTSTATUS
1787 Ext2Create (IN PEXT2_IRP_CONTEXT IrpContext)
1788 {
1789 PDEVICE_OBJECT DeviceObject;
1790 PIRP Irp;
1791 PIO_STACK_LOCATION IrpSp;
1792 PEXT2_VCB Vcb = 0;
1793 NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
1794 PEXT2_FCBVCB Xcb = NULL;
1795 BOOLEAN PostIrp = FALSE;
1796 BOOLEAN VcbResourceAcquired = FALSE;
1797
1798 DeviceObject = IrpContext->DeviceObject;
1799 Irp = IrpContext->Irp;
1800 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1801
1802 Xcb = (PEXT2_FCBVCB) (IrpSp->FileObject->FsContext);
1803
1804 if (IsExt2FsDevice(DeviceObject)) {
1805
1806 DEBUG(DL_INF, ( "Ext2Create: Create on main device object.\n"));
1807
1808 Status = STATUS_SUCCESS;
1809 Irp->IoStatus.Information = FILE_OPENED;
1810
1811 Ext2CompleteIrpContext(IrpContext, Status);
1812
1813 return Status;
1814 }
1815
1816 _SEH2_TRY {
1817
1818 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
1819 ASSERT(Vcb->Identifier.Type == EXT2VCB);
1820 IrpSp->FileObject->Vpb = Vcb->Vpb;
1821
1822 if (!IsMounted(Vcb)) {
1823 DbgBreak();
1824 if (IsFlagOn(Vcb->Flags, VCB_DEVICE_REMOVED)) {
1825 Status = STATUS_NO_SUCH_DEVICE;
1826 } else {
1827 Status = STATUS_VOLUME_DISMOUNTED;
1828 }
1829 _SEH2_LEAVE;
1830 }
1831
1832 if (!ExAcquireResourceExclusiveLite(
1833 &Vcb->MainResource, TRUE)) {
1834 Status = STATUS_PENDING;
1835 _SEH2_LEAVE;
1836 }
1837 VcbResourceAcquired = TRUE;
1838
1839 Ext2VerifyVcb(IrpContext, Vcb);
1840
1841 if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) {
1842 Status = STATUS_ACCESS_DENIED;
1843 if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
1844 Status = STATUS_VOLUME_DISMOUNTED;
1845 }
1846 _SEH2_LEAVE;
1847 }
1848
1849 if ( ((IrpSp->FileObject->FileName.Length == 0) &&
1850 (IrpSp->FileObject->RelatedFileObject == NULL)) ||
1851 (Xcb && Xcb->Identifier.Type == EXT2VCB) ) {
1852 Status = Ext2CreateVolume(IrpContext, Vcb);
1853 } else {
1854
1855 Status = Ext2CreateFile(IrpContext, Vcb, &PostIrp);
1856 }
1857
1858 } _SEH2_FINALLY {
1859
1860 if (VcbResourceAcquired) {
1861 ExReleaseResourceLite(&Vcb->MainResource);
1862 }
1863
1864 if (!IrpContext->ExceptionInProgress && !PostIrp) {
1865 if ( Status == STATUS_PENDING ||
1866 Status == STATUS_CANT_WAIT) {
1867 Status = Ext2QueueRequest(IrpContext);
1868 } else {
1869 Ext2CompleteIrpContext(IrpContext, Status);
1870 }
1871 }
1872 } _SEH2_END;
1873
1874 return Status;
1875 }
1876
1877 NTSTATUS
1878 Ext2CreateInode(
1879 PEXT2_IRP_CONTEXT IrpContext,
1880 PEXT2_VCB Vcb,
1881 PEXT2_FCB Parent,
1882 ULONG Type,
1883 ULONG FileAttr,
1884 PUNICODE_STRING FileName)
1885 {
1886 NTSTATUS Status;
1887 ULONG iGrp;
1888 ULONG iNo;
1889 struct inode Inode = { 0 };
1890 struct dentry *Dentry = NULL;
1891
1892 LARGE_INTEGER SysTime;
1893
1894 iGrp = (Parent->Inode->i_ino - 1) / BLOCKS_PER_GROUP;
1895
1896 DEBUG(DL_INF, ("Ext2CreateInode: %S in %S(Inode=%xh)\n",
1897 FileName->Buffer,
1898 Parent->Mcb->ShortName.Buffer,
1899 Parent->Inode->i_ino));
1900
1901 Status = Ext2NewInode(IrpContext, Vcb, iGrp, Type, &iNo);
1902 if (!NT_SUCCESS(Status)) {
1903 goto errorout;
1904 }
1905
1906 KeQuerySystemTime(&SysTime);
1907 Ext2ClearInode(IrpContext, Vcb, iNo);
1908 Inode.i_sb = &Vcb->sb;
1909 Inode.i_ino = iNo;
1910 Inode.i_ctime = Inode.i_mtime =
1911 Inode.i_atime = Ext2LinuxTime(SysTime);
1912 if (IsFlagOn(Vcb->Flags, VCB_USER_IDS)) {
1913 Inode.i_uid = Vcb->uid;
1914 Inode.i_gid = Vcb->gid;
1915 } else {
1916 Inode.i_uid = Parent->Mcb->Inode.i_uid;
1917 Inode.i_gid = Parent->Mcb->Inode.i_gid;
1918 }
1919 Inode.i_generation = Parent->Inode->i_generation;
1920 Inode.i_mode = S_IPERMISSION_MASK &
1921 Parent->Inode->i_mode;
1922 if (Type == EXT2_FT_DIR) {
1923 Inode.i_mode |= S_IFDIR;
1924 } else if (Type == EXT2_FT_REG_FILE) {
1925 Inode.i_mode &= S_IFATTR;
1926 Inode.i_mode |= S_IFREG;
1927 } else {
1928 DbgBreak();
1929 }
1930
1931 /* Force using extent */
1932 if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
1933 Inode.i_flags |= EXT2_EXTENTS_FL;
1934 ext4_ext_tree_init(IrpContext, NULL, &Inode);
1935 /* ext4_ext_tree_init will save inode body */
1936 } else {
1937 /* save inode body to cache */
1938 Ext2SaveInode(IrpContext, Vcb, &Inode);
1939 }
1940
1941 /* add new entry to its parent */
1942 Status = Ext2AddEntry(
1943 IrpContext,
1944 Vcb,
1945 Parent,
1946 &Inode,
1947 FileName,
1948 &Dentry
1949 );
1950
1951 if (!NT_SUCCESS(Status)) {
1952 DbgBreak();
1953 Ext2FreeInode(IrpContext, Vcb, iNo, Type);
1954 goto errorout;
1955 }
1956
1957 DEBUG(DL_INF, ("Ext2CreateInode: New Inode = %xh (Type=%xh)\n",
1958 Inode.i_ino, Type));
1959
1960 errorout:
1961
1962 if (Dentry)
1963 Ext2FreeEntry(Dentry);
1964
1965 return Status;
1966 }
1967
1968
1969 NTSTATUS
1970 Ext2SupersedeOrOverWriteFile(
1971 IN PEXT2_IRP_CONTEXT IrpContext,
1972 IN PFILE_OBJECT FileObject,
1973 IN PEXT2_VCB Vcb,
1974 IN PEXT2_FCB Fcb,
1975 IN PLARGE_INTEGER AllocationSize,
1976 IN ULONG Disposition
1977 )
1978 {
1979 LARGE_INTEGER CurrentTime;
1980 LARGE_INTEGER Size;
1981
1982 KeQuerySystemTime(&CurrentTime);
1983
1984 Size.QuadPart = 0;
1985 if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &(Size))) {
1986 return STATUS_USER_MAPPED_FILE;
1987 }
1988
1989 /* purge all file cache and shrink cache windows size */
1990 CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE);
1991 Fcb->Header.AllocationSize.QuadPart =
1992 Fcb->Header.FileSize.QuadPart =
1993 Fcb->Header.ValidDataLength.QuadPart = 0;
1994 CcSetFileSizes(FileObject,
1995 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
1996
1997 Size.QuadPart = CEILING_ALIGNED(ULONGLONG,
1998 (ULONGLONG)AllocationSize->QuadPart,
1999 (ULONGLONG)BLOCK_SIZE);
2000
2001 if ((loff_t)Size.QuadPart > Fcb->Inode->i_size) {
2002 Ext2ExpandFile(IrpContext, Vcb, Fcb->Mcb, &Size);
2003 } else {
2004 Ext2TruncateFile(IrpContext, Vcb, Fcb->Mcb, &Size);
2005 }
2006
2007 Fcb->Header.AllocationSize = Size;
2008 if (Fcb->Header.AllocationSize.QuadPart > 0) {
2009 SetLongFlag(Fcb->Flags, FCB_ALLOC_IN_CREATE);
2010 CcSetFileSizes(FileObject,
2011 (PCC_FILE_SIZES)&Fcb->Header.AllocationSize );
2012 }
2013
2014 /* remove all extent mappings */
2015 DEBUG(DL_EXT, ("Ext2SuperSede ...: %wZ\n", &Fcb->Mcb->FullName));
2016 Fcb->Inode->i_size = 0;
2017
2018 if (Disposition == FILE_SUPERSEDE) {
2019 Fcb->Inode->i_ctime = Ext2LinuxTime(CurrentTime);
2020 }
2021 Fcb->Inode->i_atime =
2022 Fcb->Inode->i_mtime = Ext2LinuxTime(CurrentTime);
2023 Ext2SaveInode(IrpContext, Vcb, Fcb->Inode);
2024
2025 return STATUS_SUCCESS;
2026 }