2 * YAFFS: Yet another FFS. A NAND-flash specific file system.
3 * yaffsfsd.c: FSD interface funtions for WinCE.
5 * Copyright (C) 2002 Trimble Navigation Ltd.
7 * Created by Charles Manning <charles.manning@trimble.co.nz>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details. You should have received a
17 * copy of the GNU General Public License along with this program;
18 * if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 * Various clean-ups and WinCE4 support by Steve Fogle and Lynn Winter
23 * $Id: yaffsfsd.c,v 1.4 2003-01-31 03:30:33 charles Exp $
27 #include <yaffs_guts.h>
33 #define MAX_WIN_FILE 200
34 #define YFSD_NAME_LENGTH 128
35 #define YFSD_FULL_PATH_NAME_SIZE 500
38 #define YFSD_DISK_NAME L"Disk"
39 #define YFSD_BOOT_NAME L"Boot"
41 #define PARTITION_START_NUMBER (1280)
44 // if this is defined the there will be a constant message box raised to display status
45 //#define MSGBOX_DISPLAY
50 //#define DISABLE_BOOT_PARTITION
52 // Define DO_PARTITION_TABLE to cause the partition table
53 // information to be retrieved from the block driver.
54 // Can define this in your sources file.
55 //#define DO_PARTITION_TABLE
56 // How many partitions the disk might have. 2 gives
57 // space for the "Disk" and "Boot" partitions.
58 #define MAXPARTITIONS (2)
61 //unsigned yaffs_traceMask=0xffffffff;
62 unsigned yaffs_traceMask=0;
69 DWORD mgrVolume; // The volume id from the manager issed when we registered it - it is an HVOL
74 SHELLFILECHANGEFUNC_t shellFunction;
85 yfsd_Volume *myVolume;
93 struct yfsd_FoundObjectStruct
96 struct yfsd_FoundObjectStruct *next;
99 typedef struct yfsd_FoundObjectStruct yaffs_FoundObject;
104 char pattern[YFSD_NAME_LENGTH+1];
105 yaffs_FoundObject *foundObjects;
110 #define PSEARCH yfsd_WinFind*
112 #define PVOLUME yfsd_Volume*
113 #define PFILE yfsd_WinFile*
120 //static yfsd_Volume disk_volume;
121 //static yfsd_Volume boot_volume;
122 static yfsd_Volume * disk_volumes[MAXPARTITIONS];
125 static CRITICAL_SECTION yaffsLock;
126 static CRITICAL_SECTION winFileLock;
128 static int yaffsLockInited = 0;
130 static yfsd_WinFile yfsd_winFile[MAX_WIN_FILE];
133 static yfsd_SetGuards(void)
136 for(i = 0; i < 100; i++)
138 yfsd_volume.guard0[i] = yfsd_volume.guard1[i] = i;
142 static void yfsd_CheckGuards(void)
146 for(i = found = 0; i < 100 && !found; i++)
148 if(yfsd_volume.guard0[i] != i)
150 RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
153 if(yfsd_volume.guard1[i] != i)
155 RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
163 #ifdef MSGBOX_DISPLAY
164 DWORD WINAPI yfsd_MessageThread(LPVOID param)
166 yaffs_Device *dev = (yaffs_Device *)param;
167 TCHAR dataBuffer[1000];
170 // note : if the device gets free'd from under us, we will cause an exception in the loop
173 wsprintf(dataBuffer, L"nShortOpCaches %i\r\n"
174 L"nErasedBlocks %i\r\n"
175 L"allocationBlock %i\r\n"
176 L"allocationPage %i\r\n"
177 L"garbageCollectionRequired %i\r\n"
178 L"nRetiredBlocks %i\r\n"
182 L"tagsEccFixed %i\r\n"
183 L"tagsEccUnfixed %i\r\n",
186 dev->allocationBlock,
188 dev->garbageCollectionRequired,
194 dev->tagsEccUnfixed);
205 void yfsd_LockWinFiles(void)
207 //RETAILMSG (MSGSTATE, (L"YAFFS::LockWinfiles\r\n"));
208 EnterCriticalSection(&winFileLock);
210 void yfsd_UnlockWinFiles(void)
212 //RETAILMSG (MSGSTATE, (L"YAFFS::UnlockWinFiles\r\n"));
213 LeaveCriticalSection(&winFileLock);
218 void yfsd_LockYAFFS(void)
220 //yfsd_CheckGuards();
221 //RETAILMSG (MSGSTATE, (L"YAFFS::LockYAFFS %d ",lockwaits));
223 EnterCriticalSection(&yaffsLock);
224 //RETAILMSG (MSGSTATE, (L" locked\r\n"));
226 void yfsd_UnlockYAFFS(void)
228 //yfsd_CheckGuards();
229 //RETAILMSG (MSGSTATE, (L"YAFFS::UnLockYAFFS "));
230 LeaveCriticalSection(&yaffsLock);
232 //RETAILMSG (MSGSTATE, (L" unlocked\r\n"));
236 void yfsd_InitialiseWinFiles(void)
240 RETAILMSG (MSGSTATE, (L"YAFFS::InitWinFiles\r\n"));
242 InitializeCriticalSection(&winFileLock);
245 for(i = 0; i < MAX_WIN_FILE; i++)
247 yfsd_winFile[i].isopen = 0;
249 yfsd_UnlockWinFiles();
252 yfsd_WinFile * yfsd_GetWinFile(void)
255 RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles\r\n"));
259 for(i = 0; i < MAX_WIN_FILE; i++)
261 if(!yfsd_winFile[i].isopen)
263 yfsd_winFile[i].isopen = 1;
264 yfsd_winFile[i].writePermitted = 0;
265 yfsd_winFile[i].readPermitted = 0;
266 yfsd_winFile[i].shareRead = 0;
267 yfsd_winFile[i].shareWrite = 0;
268 yfsd_winFile[i].dirty = 0;
269 yfsd_winFile[i].fullName = NULL;
270 yfsd_winFile[i].obj = NULL;
272 yfsd_UnlockWinFiles();
273 return &yfsd_winFile[i];
277 yfsd_UnlockWinFiles();
279 RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles did not find a handle. Too many open.\r\n"));
284 void yfsd_PutWinFile(yfsd_WinFile *f)
286 RETAILMSG (MSGSTATE, (L"YAFFS::PutWinFile\r\n"));
296 yfsd_UnlockWinFiles();
301 void yfsd_FlushAllFiles(void)
304 RETAILMSG (MSGSTATE, (L"YAFFS::FlushAllFiles\r\n"));
308 for(i = 0; i < MAX_WIN_FILE; i++)
310 if(yfsd_winFile[i].isopen &&
313 yaffs_FlushFile(yfsd_winFile[i].obj,1);
316 yfsd_UnlockWinFiles();
321 //////////////////////////////////////////////////////////////////////
322 // Search through winFiles to see if any are open.
324 BOOL yfsd_FilesOpen(void)
328 RETAILMSG (MSGSTATE, (L"YAFFS::FilesOpen?\r\n"));
331 for(i = 0, rval = FALSE; i < MAX_WIN_FILE; i++)
333 if(yfsd_winFile[i].isopen)
339 yfsd_UnlockWinFiles();
344 PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
347 // todo check for bounds
349 //volName already has the initial backslash if it needs it.
351 //wcscat(fpn,vol->volName);
352 wcscpy(fpn,vol->volName);
354 if(pathName[0] != '\\')
358 wcscat(fpn,pathName);
365 // FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.
367 void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)
370 wft->dwLowDateTime = target[0];
371 wft->dwHighDateTime = target[1];
375 void yfsd_NullWinFileTime(FILETIME *wft)
377 wft->dwLowDateTime = 0;
378 wft->dwHighDateTime = 0;
381 void yfsd_WinFileTimeToU32s(const FILETIME *wft, __u32 target[2])
383 target[0] = wft->dwLowDateTime;
384 target[1] = wft->dwHighDateTime;
387 void yfsd_WinFileTimeNow(__u32 target[2])
393 SystemTimeToFileTime(&st,&ft);
394 yfsd_WinFileTimeToU32s(&ft,target);
397 // Cut down the name to the parent directory, then inform the shell of
398 // a change to the directory.
399 void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)
403 wcscpy(str,fullPathName);
413 // Curveball if the name is a directory (ie. we're doing an update of
414 // a directory because we added a directory item). , then it might end in a \
415 // which we must toss first
416 if(i >= 0 && (str[i] == '\\' || str[i] == '/'))
422 // Ok, now strip back...
424 while(i >= 0 && str[i] != '\\' && str[i] != '/')
430 if(pVolume->shellFunction)
434 fc.cbSize = sizeof(FILECHANGEINFO);
435 fc.wEventId = SHCNE_UPDATEDIR;
436 fc.uFlags = SHCNF_PATH;
437 fc.dwItem1 = (DWORD)str;
440 yfsd_NullWinFileTime(&fc.ftModified);
443 pVolume->shellFunction(&fc);
444 RETAILMSG (MSGSTATE, (L"YAFFS:: directory changed %s\r\n",str));
452 // Minimal name test for now
453 BOOL yfsd_NameIsValid (const char *name)
455 int length = strlen(name);
457 return (length > 0 && length <= YFSD_NAME_LENGTH);
462 // Wince understands the following attributes of any use to YAFFS:
470 // Also, FILE_ATTRIBUTE_DIRECTORY is used to mark directories.
472 // It also understands NORMAL. If no other flag is set, then set NORMAL.
473 // If any of the above are set, then NORMAL must **not** be set.
474 // Ignore this and the WinCE Explorer barfs the file.
477 // in addition, GetAttributes also returns FILE_ATTRIBUTE_DIRECTORY
479 // The following are valid ones we get presented with,
480 // but must filter out the stuff we don't unserstand
481 //#define FILE_ATTRIBUTE_READONLY 0x00000001
482 //#define FILE_ATTRIBUTE_HIDDEN 0x00000002
483 //#define FILE_ATTRIBUTE_SYSTEM 0x00000004
484 //#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
485 //#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
486 //#define FILE_ATTRIBUTE_INROM 0x00000040
487 //#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
488 //#define FILE_ATTRIBUTE_NORMAL 0x00000080
489 //#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
490 //#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
491 //#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
492 //#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
493 //#define FILE_ATTRIBUTE_OFFLINE 0x00001000
494 //#define FILE_ATTRIBUTE_ROMSTATICREF 0x00001000
495 //#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
496 //#define FILE_ATTRIBUTE_ROMMODULE 0x00002000
499 BOOL yfsd_CheckValidAttributes(DWORD attribs)
502 RETAILMSG (MSGSTATE, (L"Attributes:%X\r\n", attribs));
505 // If NORMAL, then nothing else
506 if(attribs & FILE_ATTRIBUTE_NORMAL && attribs != FILE_ATTRIBUTE_NORMAL)
508 if(attribs == FILE_ATTRIBUTE_NORMAL)
511 // Check that the bits are in the valid set
512 if(attribs & ~(0x3FE7))
518 DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)
523 result = obj->st_mode &
524 (FILE_ATTRIBUTE_READONLY |
525 FILE_ATTRIBUTE_ARCHIVE |
526 FILE_ATTRIBUTE_HIDDEN |
527 FILE_ATTRIBUTE_SYSTEM);
529 if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;
531 if(result & ~FILE_ATTRIBUTE_NORMAL)
533 result &= ~FILE_ATTRIBUTE_NORMAL;
537 result = FILE_ATTRIBUTE_NORMAL;
547 * Runs over input until a '\' is found, or '\0' is found, or outSize - 1 is
548 * reached. Characters are copied from input into output until the above stop
549 * condition is reached - output is then given a '\0'. output must be at least
550 * as large as outSize
552 static int parseToNextSlash(const unsigned short *input, char *output, int outSize)
556 /* strip any starting \'s */
557 //RETAILMSG(1, (L"\r\nParsing.. "));
558 while (*input == '\\' || *input == '/') input++, counter++;
560 for (; counter < outSize - 1; counter++)
562 if (*input == '\0' ||
563 ((*input == '\\' || *input == '/') && input[1] == '\0')) // special case: if the string ends in a '\', then toss the '\'
565 counter = -1; // break & tell people we've run to the end
568 if (*input == '\\' || *input == '/')
570 //RETAILMSG(1, (L"%c", *input));
571 *output = (char) (*input);
577 // RETAILMSG(1, (L"\r\nOut %a\r\n", t));
583 * Since the notion of paths as WinCE sees them and as YAFFS sees them
584 * is different, we needed a helper function to search from the root of
585 * device along the string in path. The processed pointer is set to where
586 * abouts in the string the function was able to search up to.
588 yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *path, char *processed, int length)
590 // a buffer to keep the current chunk of path we're talking about it
594 // the current object we are at
595 yaffs_Object *current;
597 RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));
598 // start at the root of this device
599 current = yaffs_Root(device);
604 // parse chunks until we run out
605 chunkSize = parseToNextSlash(path, pathChunk, 255);
606 // RETAILMSG(1, (L"Chunk %a\r\n", pathChunk));
609 // move the path pointer along
611 // try and find the next yaffs object by chunkname
612 current = yaffs_FindObjectByName(current, pathChunk);
620 for (counter = 0; counter < length; counter++)
622 // Get the rest of the string
623 processed[counter] = pathChunk[counter];
624 if (pathChunk[counter] == '\0')
628 RETAILMSG (MSGSTATE, (L"YAFFS::FindDirectoryByWinPath parent:%X name:%a\r\n", current,processed));
634 yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )
636 yaffs_Object *obj = NULL;
637 yaffs_Object *parent = NULL;
638 char name[YFSD_NAME_LENGTH+1];
640 RETAILMSG (MSGSTATE, (L"YAFFS::FindObjByWinPath\r\n"));
642 parent = yfsd_FindDirectoryByWinPath(dev,pwsFileName,name,YFSD_NAME_LENGTH);
644 if(parent && yfsd_NameIsValid(name))
646 obj = yaffs_FindObjectByName(parent,name);
649 RETAILMSG (MSGSTATE, (L"YAFFS::FindObjectByWinPath parent:%X obj:%X\r\n", parent,obj));
654 BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)
657 WCHAR szName[MAX_PATH];
660 RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));
661 //slf021104b Begin filled in later.
662 //vol->volName = volName;
668 //slf021220a Begin Cleanup block driver interface
669 #if _WINCEOSVER >= 400
670 // For Win'CE 4.0 and later pass the hdsk for use by the yandif layer.
671 vol->dev.genericDevice = (PVOID)hdsk;
673 //slf021220a End Cleanup block driver interface
675 //Mount/initialise YAFFs here
676 //slf021127a begin check for error returns!
677 if (ynandif_InitialiseNAND(&vol->dev))
679 //slf021127a end check for error returns!
680 vol->dev.writeChunkToNAND = ynandif_WriteChunkToNAND;
681 vol->dev.readChunkFromNAND = ynandif_ReadChunkFromNAND;
682 vol->dev.eraseBlockInNAND = ynandif_EraseBlockInNAND;
683 vol->dev.initialiseNAND = ynandif_InitialiseNAND;
684 vol->dev.startBlock = startBlock;
686 vol->dev.endBlock = endBlock;
687 vol->dev.nShortOpCaches = 10; // a nice number of caches.
688 vol->dev.nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
689 vol->dev.nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
690 vol->dev.nReservedBlocks = 5; // a nice reserve size
693 // nBlocks is set the total size of the disk, not the partition
694 // vol->dev.nBlocks = endBlock - startBlock + 1;
696 // qnand_EraseAllBlocks(&vol->dev);
698 //slf021127a begin check for error returns!
699 if (yaffs_GutsInitialise(&vol->dev))
701 //slf021127a end check for error returns!
702 RETAILMSG(1, (L"YAFFS::Done yaffs_GutsInitialise\r\n"));
704 RETAILMSG(1, (L"Blocks start %d end %d Group size %d bits %d\r\n",
705 vol->dev.startBlock,vol->dev.endBlock,
706 vol->dev.chunkGroupSize,vol->dev.chunkGroupBits));
710 for(i = vol->dev.startBlock; i <= vol->dev.endBlock; i++)
712 switch(vol->dev.blockInfo[i].blockState)
714 case YAFFS_BLOCK_STATE_DEAD:
716 RETAILMSG(1, (L"YAFFS::Dead block %d\r\n",i));
719 case YAFFS_BLOCK_STATE_EMPTY: emptyBlox++; break;
720 case YAFFS_BLOCK_STATE_FULL: fullBlox++; break;
721 case YAFFS_BLOCK_STATE_ALLOCATING: allocatingBlox++; break;
722 case YAFFS_BLOCK_STATE_DIRTY: dirtyBlox++; break;
724 RETAILMSG(1, (L"YAFFS::Block %d has goofus state %d\r\n",i,vol->dev.blockInfo[i].blockState));
729 RETAILMSG(1, (L"Blocks dead %d empty %d full %d allocating %d dirty %d\r\n",
730 deadBlox,emptyBlox,fullBlox,allocatingBlox,dirtyBlox));
734 //slf021127a begin check for error returns!
738 //slf021127a begin check for error returns!
742 //slf021127a begin check for error returns!
743 // vol->isMounted = 1;
744 //slf021127a begin check for error returns!
747 //vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);
748 // If the caller passed a volume name use it.
750 wcscpy( szName, volName);
751 #if WINCEOSVER >= 400
752 // The user passed an empty volume name. On CE 4.xx try to get
753 // if from the block driver (which got it from the registry).
754 else if (!FSDMGR_DiskIoControl(hdsk, DISK_IOCTL_GETNAME, NULL, 0, (LPVOID)szName, sizeof(szName), &dwAvail, NULL))
759 // Didn't get a volume name so use "Disk" by default.
760 wcscpy( szName, YFSD_DISK_NAME);
762 vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,szName,vol);
768 // Get some space for the volume name.
769 vol->volName = malloc( MAX_PATH * sizeof(WCHAR));
772 #if WINCEOSVER >= 400
773 // Get the name we were really mounted under.
774 FSDMGR_GetVolumeName(vol->mgrVolume, vol->volName, MAX_PATH);
776 // If we got mounted as root then throw away the backslash
777 // so we won't get a double backslash when volName is
778 // prepended to the path in the full path name calculation
779 // that is used for shell callbacks.
780 if (0 == wcscmp(vol->volName,L"\\"))
783 // Use the name we asked to be mounted under for
785 wcscpy(vol->volName,L"\\");
786 wcscat(vol->volName, szName);
795 SetLastError(ERROR_OUTOFMEMORY);
801 BOOL YFSD_MountDisk(HDSK hdsk)
804 #ifdef DO_PARTITION_TABLE
805 ynandif_partition PartTable[MAXPARTITIONS];
811 int deadBlox=0,emptyBlox=0,fullBlox=0,allocatingBlox=0,dirtyBlox=0;
813 // Called to mount a disk.
814 // NB THis call might happen redundantly.
817 // If yaffs is not initialised, then call the
818 // initialisation function
820 RETAILMSG (MSGSTATE, (L"YAFFS::MountDisk\r\n"));
822 if (!yaffsLockInited)
824 InitializeCriticalSection(&yaffsLock);
825 yfsd_InitialiseWinFiles();
830 memset(disk_volumes,0,sizeof(disk_volumes));
831 #ifdef DO_PARTITION_TABLE
832 memset(&PartTable,0,sizeof(PartTable));
833 // Call the block driver to get the partition table from it.
834 if (FSDMGR_DiskIoControl(hdsk, YNANDIF_GETPARTITIONS, NULL, 0, (LPVOID)&PartTable, sizeof(PartTable), &dwAvail, NULL))
836 // Scan throught the table it return.
837 for (i=0; i<MAXPARTITIONS; i++)
839 // At the very lease check that the end is later than the beginning
840 // and don't let it start at 0.
841 // Probably could do more thorough checking but I trust the block
843 if (PartTable[i].startBlock && (PartTable[i].endBlock > PartTable[i].startBlock))
845 // Found a partion. Get a volume structure to hold it.
846 disk_volumes[i] = malloc(sizeof(yfsd_Volume));
849 memset(disk_volumes[i],0,sizeof(yfsd_Volume));
850 // Go init the volume. Note that if the block driver wants the
851 // name to come from the registry it will have returned an
852 // empty name string.
853 YFSD_InitVolume(hdsk,disk_volumes[i],PartTable[i].startBlock,PartTable[i].endBlock,PartTable[i].volName);
854 if (disk_volumes[i]->isMounted)
855 rval = TRUE; //Hey, we found at least on partition.
864 #ifdef DISABLE_BOOT_PARTITION
865 // Only want disk volume
866 disk_volumes[0] = malloc(sizeof(yfsd_Volume));
869 memset(disk_volumes[0],0,sizeof(yfsd_Volume));
870 YFSD_InitVolume(hdsk, disk_volumes[0], 1, -1, YFSD_DISK_NAME);
872 if(disk_volumes[0].isMounted)
879 free(disk_volumes[0];
880 disk_volumes[0] = NULL;
883 // Want both boot and disk
884 disk_volumes[0] = malloc(sizeof(yfsd_Volume));
885 disk_volumes[1] = malloc(sizeof(yfsd_Volume));
886 if (disk_volumes[0] && disk_volumes[1])
888 memset(disk_volumes[0],0,sizeof(yfsd_Volume));
889 memset(disk_volumes[1],0,sizeof(yfsd_Volume));
890 YFSD_InitVolume(hdsk, disk_volumes[0], PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
891 YFSD_InitVolume(hdsk, disk_volumes[1], 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
893 #ifdef MSGBOX_DISPLAY
894 // pass the device we are sniffing to the thread
895 CreateThread(NULL, 0, yfsd_MessageThread, (LPVOID)&disk_volumes[0]->dev, 0, NULL);
898 if(disk_volumes[0]->isMounted && disk_volumes[1]->isMounted)
904 // If we got this far something went wrong. Make sure to
905 // free any memory we allocated.
908 if (disk_volumes[0]->volName)
910 free(disk_volumes[0]->volName);
912 free(disk_volumes[0]);
913 disk_volumes[0] = NULL;
917 if (disk_volumes[1]->volName)
919 free(disk_volumes[1]->volName);
921 free(disk_volumes[1]);
922 disk_volumes[1] = NULL;
928 // Only want disk volume
929 // YFSD_InitVolume(hdsk, &disk_volume, 1, -1, YFSD_DISK_NAME);
932 // if(disk_volume.isMounted)
937 // // Want both boot and disk
938 // YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
939 // YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
942 // if(disk_volume.isMounted && boot_volume.isMounted)
954 // todo - get name from registry
959 BOOL YFSD_UnmountDisk(HDSK hdsk)
964 RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));
967 // If there are any files open don't let them dismount
968 // it or the system will get very confused.
969 if (yfsd_FilesOpen())
972 //yfsd_FlushAllFiles();
977 // yaffs_Deinitialise(&disk_volume.dev);
978 // yaffs_Deinitialise(&boot_volume.dev);
979 // yfsd_UnlockYAFFS();
981 // FSDMGR_DeregisterVolume(disk_volume.mgrVolume);
982 // FSDMGR_DeregisterVolume(boot_volume.mgrVolume);
984 // Walk through the partions deinitializing, deregistering
986 for (i=0; i<MAXPARTITIONS; i++)
990 yaffs_Deinitialise(&(disk_volumes[i]->dev));
991 //slf021220a Begin Cleanup block driver interface
992 ynandif_DeinitialiseNAND(&(disk_volumes[i]->dev));
993 //slf021220a end Cleanup block driver interface
994 FSDMGR_DeregisterVolume(disk_volumes[i]->mgrVolume);
995 if (disk_volumes[i]->volName)
997 free(disk_volumes[i]->volName);
999 free(disk_volumes[i]);
1000 disk_volumes[i] = NULL;
1009 BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTES pSecurityAttributes)
1011 // security attributes are ignored (should be NULL)
1013 yaffs_Object *newDir = NULL;
1014 yaffs_Object *parent = NULL;
1015 char name[YFSD_NAME_LENGTH+1];
1018 unsigned modifiedTime[2];
1020 RETAILMSG (MSGSTATE, (L"YAFFS::CreateDirectory (%s)\r\n", pathName));
1024 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
1029 if(yfsd_NameIsValid(name))
1031 newDir = yaffs_MknodDirectory(parent,name,0,0,0);
1034 objSize = yaffs_GetObjectFileLength(newDir);
1035 attribs = yfsd_GetObjectWinAttributes(newDir);
1036 modifiedTime[0] = newDir->win_mtime[0];
1037 modifiedTime[1] = newDir->win_mtime[1];
1041 if(yaffs_FindObjectByName(parent,name))
1042 SetLastError(ERROR_ALREADY_EXISTS);
1044 SetLastError(ERROR_DISK_FULL);
1048 SetLastError(ERROR_INVALID_NAME);
1052 SetLastError(ERROR_PATH_NOT_FOUND);
1058 // Call shell function to tell of new directory
1059 if(newDir && pVolume->shellFunction)
1062 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1064 fc.cbSize = sizeof(FILECHANGEINFO);
1065 fc.wEventId = SHCNE_MKDIR;
1066 fc.uFlags = SHCNF_PATH;
1067 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume, fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
1069 fc.dwAttributes = attribs;
1070 yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
1071 fc.nFileSize = objSize;
1073 pVolume->shellFunction(&fc);
1074 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1076 //yfsd_ShellDirectoryChanged(pVolume,fpn);
1081 // if(parent && !newDir)
1083 // SetLastError(ERROR_DISK_FULL);
1087 return newDir ? TRUE : FALSE;
1091 BOOL YFSD_RemoveDirectoryW(PVOLUME pVolume, PCWSTR pathName)
1094 yaffs_Object *parent = NULL;
1096 char name[YFSD_NAME_LENGTH+1];
1098 RETAILMSG (MSGSTATE, (L"YAFFS::RemoveDirectory (%s)\r\n", pathName));
1102 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pathName);
1105 SetLastError(ERROR_PATH_NOT_FOUND);
1108 else if (obj->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
1110 SetLastError(ERROR_ACCESS_DENIED);
1113 else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)
1115 SetLastError(ERROR_ACCESS_DENIED);
1120 SetLastError(ERROR_ACCESS_DENIED);
1126 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
1128 if(parent && yfsd_NameIsValid(name))
1130 result = yaffs_Unlink(parent,name);
1132 SetLastError(ERROR_DIR_NOT_EMPTY);
1138 if(result && pVolume->shellFunction)
1141 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1143 fc.cbSize = sizeof(FILECHANGEINFO);
1144 fc.wEventId = SHCNE_RMDIR;
1145 fc.uFlags = SHCNF_PATH;
1146 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
1148 fc.dwAttributes = 0;
1149 yfsd_NullWinFileTime(&fc.ftModified);
1152 pVolume->shellFunction(&fc);
1153 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1155 yfsd_ShellDirectoryChanged(pVolume,fpn);
1158 return result ? TRUE : FALSE;
1162 DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )
1164 yaffs_Object *obj = NULL;
1166 DWORD result = 0xFFFFFFFF;
1168 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes\r\n"));
1172 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1176 result = yfsd_GetObjectWinAttributes(obj);
1180 SetLastError(ERROR_FILE_NOT_FOUND);
1185 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes for %s returning %X\r\n",pwsFileName,result));
1191 BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )
1193 yaffs_Object *obj = NULL;
1200 RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));
1202 if(!yfsd_CheckValidAttributes(dwFileAttributes))
1204 SetLastError(ERROR_INVALID_PARAMETER);
1210 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1214 obj->st_mode = dwFileAttributes;
1216 result = yaffs_FlushFile(obj,0);
1217 attribs = yfsd_GetObjectWinAttributes(obj);
1218 objSize = yaffs_GetObjectFileLength(obj);
1219 mtime[0] = obj->win_mtime[0];
1220 mtime[1] = obj->win_mtime[1];
1224 SetLastError(ERROR_FILE_NOT_FOUND);
1229 if(result && pVolume->shellFunction)
1232 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1234 fc.cbSize = sizeof(FILECHANGEINFO);
1235 fc.wEventId = SHCNE_ATTRIBUTES;
1236 fc.uFlags = SHCNF_PATH;
1237 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1239 fc.dwAttributes = attribs;
1240 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
1241 fc.nFileSize = objSize;
1243 pVolume->shellFunction(&fc);
1244 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1246 //yfsd_ShellDirectoryChanged(pVolume,fpn);
1254 BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )
1257 yaffs_Object *parent = NULL;
1259 char name[YFSD_NAME_LENGTH+1];
1261 RETAILMSG (MSGSTATE, (L"YAFFS::DeleteFileW (%s)\r\n", pwsFileName));
1265 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1268 SetLastError(ERROR_FILE_NOT_FOUND);
1271 else if (obj->variantType != YAFFS_OBJECT_TYPE_FILE)
1273 SetLastError(ERROR_ACCESS_DENIED);
1276 else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)
1278 SetLastError(ERROR_ACCESS_DENIED);
1283 SetLastError(ERROR_ACCESS_DENIED);
1289 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);
1291 if(parent && yfsd_NameIsValid(name))
1293 result = yaffs_Unlink(parent,name);
1295 SetLastError(ERROR_ACCESS_DENIED);
1301 if(result && pVolume->shellFunction)
1304 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1306 fc.cbSize = sizeof(FILECHANGEINFO);
1307 fc.wEventId = SHCNE_DELETE;
1308 fc.uFlags = SHCNF_PATH;
1309 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1311 fc.dwAttributes = -1;
1312 yfsd_NullWinFileTime(&fc.ftModified);
1315 pVolume->shellFunction(&fc);
1316 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1318 yfsd_ShellDirectoryChanged(pVolume,fpn);
1321 return result ? TRUE : FALSE;
1324 BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
1326 yaffs_Object *newParent = NULL;
1327 yaffs_Object *oldParent = NULL;
1328 yaffs_Object *obj = NULL;
1329 char oldName[YFSD_NAME_LENGTH+1];
1330 char newName[YFSD_NAME_LENGTH+1];
1337 RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));
1341 oldParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsOldFileName,oldName,YFSD_NAME_LENGTH);
1342 newParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsNewFileName,newName,YFSD_NAME_LENGTH);
1344 if(oldParent && yfsd_NameIsValid(oldName) && newParent && yfsd_NameIsValid(newName))
1346 result = yaffs_RenameObject(oldParent,oldName,newParent,newName);
1349 SetLastError(ERROR_FILE_NOT_FOUND);
1352 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsNewFileName);
1355 objIsDir = (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY);
1356 attribs = yfsd_GetObjectWinAttributes(obj);
1357 objSize = yaffs_GetObjectFileLength(obj);
1358 mtime[0] = obj->win_mtime[0];
1359 mtime[1] = obj->win_mtime[1];
1364 SetLastError(ERROR_PATH_NOT_FOUND);
1370 if(result && pVolume->shellFunction)
1373 WCHAR fpn1[YFSD_FULL_PATH_NAME_SIZE];
1374 WCHAR fpn2[YFSD_FULL_PATH_NAME_SIZE];
1376 fc.cbSize = sizeof(FILECHANGEINFO);
1377 fc.wEventId = objIsDir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM;
1378 fc.uFlags = SHCNF_PATH;
1379 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn1,YFSD_FULL_PATH_NAME_SIZE,pwsOldFileName);
1380 fc.dwItem2 = (DWORD)yfsd_FullPathName(pVolume,fpn2,YFSD_FULL_PATH_NAME_SIZE,pwsNewFileName);
1381 fc.dwAttributes = attribs;
1382 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
1383 fc.nFileSize = objSize;
1385 pVolume->shellFunction(&fc);
1386 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1388 yfsd_ShellDirectoryChanged(pVolume,fpn1);
1389 yfsd_ShellDirectoryChanged(pVolume,fpn2);
1393 return result ? TRUE : FALSE;
1397 BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
1403 RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));
1406 if (fSuccess = YFSD_DeleteFileW(pVolume, pwsOldFileName))
1407 fSuccess = YFSD_MoveFileW(pVolume, pwsNewFileName, pwsOldFileName);
1413 BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )
1418 RETAILMSG (MSGSTATE, (L"YAFFS::GetFreeSpace\r\n"));
1421 nChunks = yaffs_GetNumberOfFreeChunks(&pVolume->dev);
1426 // Let's pretentd our clusters are the same size as eraseable blocks...
1427 *pBytesPerSector = 512;
1428 *pSectorsPerCluster =32;
1429 *pFreeClusters = nChunks/32;
1430 *pClusters = pVolume->dev.endBlock - pVolume->dev.startBlock + 1;
1433 return (nChunks >= 0)? TRUE : FALSE;
1439 void YFSD_Notify(PVOLUME pVolume, DWORD dwFlags )
1441 // Flags can be one of:
1442 // FSNOTIFY_POWER_ON: no action required
1443 // FSNOTIFY_POWER_OFF: flush all files
1444 // FSNOTIFY_DEVICE_ON: no action required
1446 RETAILMSG (MSGSTATE, (L"YAFFS::Notify\r\n"));
1447 if(dwFlags == FSNOTIFY_POWER_OFF)
1449 yfsd_FlushAllFiles();
1455 BOOL YFSD_RegisterFileSystemFunction(PVOLUME pVolume,SHELLFILECHANGEFUNC_t pfn )
1457 RETAILMSG (MSGSTATE, (L"YAFFS::RegisterFileSysFunction\r\n"));
1459 pVolume->shellFunction = pfn;
1468 int iMatch(const char a, const char b)
1470 if (a == '?' || b == '?')
1472 return (toupper(a) == toupper(b));
1475 void pString(const char *inp)
1477 while (*inp) RETAILMSG(1, (L"%c", *inp++));
1480 int regularMatch(const char *regexp, const char *str)
1483 // RETAILMSG(1, (L" "));
1485 // RETAILMSG(1, (L"\r\n"));
1487 if (*regexp == 0 && *str == 0)
1489 //RETAILMSG(1, (L"Match!\r\n"));
1495 if (*regexp == 0) // end of the expression is a *, we must match
1497 //RETAILMSG(1, (L"Match!\r\n"));
1500 while (!iMatch(*regexp, *str)) // throw away chars from str until we match
1502 if (*str == 0) // if we're not at the end
1504 // if we have .* left to match, but the str is finished then match it OK
1505 if (regexp[0] == '.' && regexp[1] == '*')
1507 //RETAILMSG(1, (L"Match!\r\n"));
1512 // the extension failed the match
1513 //RETAILMSG(1, (L"No Match!\r\n"));
1519 // right now we should either eat more characters, or try to match
1520 return (regularMatch(regexp, str) || regularMatch(--regexp, ++str));
1522 // compare chars until we hit another *, or we fail
1523 while (iMatch(*regexp, *str))
1525 if (*regexp == 0 && *str == 0)
1527 //RETAILMSG(1, (L"Match!\r\n"));
1534 if (*regexp == 0 && *str == 0)
1536 //RETAILMSG(1, (L"Match!\r\n"));
1541 return regularMatch(regexp, str);
1543 //RETAILMSG(1, (L"No Match!\r\n"));
1548 void yfsd_DeleteFinder(PSEARCH pSearch)
1550 if(pSearch->foundObjects) //If we found some objects we must clean up the cached linked list.
1552 yaffs_FoundObject *it;
1553 yaffs_FoundObject *temp;
1555 it = pSearch->foundObjects;
1565 pSearch->foundObjects = NULL;
1568 pSearch->dir->inUse--;
1572 BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)
1574 //Iterate through the current list of objs already found and return true if already exists.
1575 //If the object hasn't already been found then add it to the list (SIDE-EFFECT alert) and return false.
1578 yaffs_FoundObject *it;
1579 it = pSearch->foundObjects;
1582 while(it->next != NULL) //iterate through singly linked list.
1594 //Add the item to the list.
1595 //'it' will currently be pointing to the last of the list nodes. i.e node->next == NULL
1596 it->next = malloc(sizeof(yaffs_FoundObject));
1597 it->next->next = NULL;
1608 BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
1611 struct list_head *i;
1616 char name[YAFFS_MAX_NAME_LENGTH+1];
1618 if(!pSearch->foundObjects)
1620 pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
1621 pSearch->foundObjects->next = NULL;
1622 pSearch->foundObjects->obj = 0;
1629 list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
1632 l = list_entry(i, yaffs_Object,siblings);
1634 yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
1636 if(regularMatch(pSearch->pattern,name))
1638 if(!yfsd_ObjectAlreadyFound(pSearch, l))//pos == pSearch->currentPos)
1643 //pSearch->currentPos++;
1645 // fill out find data
1647 pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
1649 yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
1650 yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
1651 yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
1653 pfd->nFileSizeHigh = 0;
1654 pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
1655 pfd->dwOID = (CEOID)(INVALID_HANDLE_VALUE); // wtf is this???
1657 MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
1659 RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
1660 pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
1661 l->variant.fileVariant.scannedFileSize));
1677 SetLastError(ERROR_NO_MORE_FILES);
1685 BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
1688 struct list_head *i;
1692 char name[YAFFS_MAX_NAME_LENGTH+1];
1694 if(!pSearch->foundObjects)
1696 pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
1697 pSearch->foundObjects->next = NULL;
1698 pSearch->foundObjects->obj = 0;
1704 list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
1707 l = list_entry(i, yaffs_Object,siblings);
1708 if(!yfsd_ObjectAlreadyFound(pSearch,l))
1710 // Only look at things we have not looked at already
1711 yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
1713 if(regularMatch(pSearch->pattern,name))
1716 // fill out find data
1718 pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
1720 yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
1721 yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
1722 yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
1724 pfd->nFileSizeHigh = 0;
1725 pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
1726 pfd->dwOID = (CEOID)(INVALID_HANDLE_VALUE); // wtf is this???
1728 MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
1730 RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
1731 pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
1732 l->variant.fileVariant.scannedFileSize));
1747 SetLastError(ERROR_NO_MORE_FILES);
1754 HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWIN32_FIND_DATAW pfd )
1757 // Create a search context, register it, and do the first search
1760 HANDLE h = INVALID_HANDLE_VALUE;
1763 RETAILMSG (MSGSTATE, (L"YAFFS::FindFirst\r\n"));
1765 pSearch = malloc(sizeof(yfsd_WinFind));
1768 SetLastError(ERROR_OUTOFMEMORY);
1775 pSearch->foundObjects = NULL; //pSearch->currentPos = 0;
1776 pSearch->dir = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileSpec,pSearch->pattern,YFSD_NAME_LENGTH);
1779 pSearch->dir->inUse++;
1785 SetLastError(ERROR_PATH_NOT_FOUND);
1795 found = yfsd_DoFindFile(pSearch,pfd);
1799 h = FSDMGR_CreateSearchHandle(pVolume->mgrVolume,hProc,pSearch);
1800 if(h == INVALID_HANDLE_VALUE)
1802 SetLastError(ERROR_NO_MORE_SEARCH_HANDLES);
1807 SetLastError(ERROR_FILE_NOT_FOUND);
1810 if(h == INVALID_HANDLE_VALUE)
1812 yfsd_DeleteFinder(pSearch);
1821 BOOL YFSD_FindNextFileW(PSEARCH pSearch, PWIN32_FIND_DATAW pfd )
1823 RETAILMSG (MSGSTATE, (L"YAFFS::FindNext\r\n"));
1828 return yfsd_DoFindFile(pSearch,pfd);
1831 BOOL YFSD_FindClose( PSEARCH pSearch )
1833 RETAILMSG (MSGSTATE, (L"YAFFS::FindClose\r\n"));
1838 yfsd_DeleteFinder(pSearch);
1843 HANDLE YFSD_CreateFileW(
1849 PSECURITY_ATTRIBUTES pSecurityAttributes, // ignore
1851 DWORD dwFlagsAndAttributes,
1852 HANDLE hTemplateFile ) // ignore
1856 yaffs_Object *parent = NULL;
1857 yaffs_Object *obj = NULL;
1858 char name[YFSD_NAME_LENGTH+1];
1860 yfsd_WinFile *f = NULL;
1861 HANDLE handle = INVALID_HANDLE_VALUE;
1862 unsigned modifiedTime[2];
1865 BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;
1866 BOOL readPermitted = (dwAccess & GENERIC_READ) ? TRUE : FALSE;
1867 BOOL shareRead = (dwShareMode & FILE_SHARE_READ) ? TRUE : FALSE;
1868 BOOL shareWrite = (dwShareMode & FILE_SHARE_WRITE) ? TRUE : FALSE;
1870 BOOL openRead, openWrite, openReadAllowed, openWriteAllowed;
1872 BOOL fileCreated = FALSE;
1874 BOOL fAlwaysCreateOnExistingFile = FALSE;
1875 BOOL fTruncateExistingFile = FALSE;
1878 mode = dwFlagsAndAttributes & 0x00FFFFFF; // ding off the flags
1879 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile (%s) flags %X mode %X\r\n", pwsFileName,dwFlagsAndAttributes,mode));
1882 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write permitted\r\n"));
1886 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write not permitted\r\n"));
1889 if(!yfsd_CheckValidAttributes(mode))
1891 SetLastError(ERROR_INVALID_PARAMETER);
1898 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);
1901 if(parent && yfsd_NameIsValid(name))
1904 //slf021220b begin Fix still more bugs in CreateFile.
1905 // Get the object for this file if it exists (only once).
1906 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1907 //slf021220b end Fix still more bugs in CreateFile.
1908 if(dwCreate == CREATE_NEW)
1910 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));
1913 //slf021220b begin Fix still more bugs in CreateFile.
1914 // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1915 //slf021220b end Fix still more bugs in CreateFile.
1918 obj = yaffs_MknodFile(parent,name,mode,0,0);
1920 SetLastError(ERROR_DISK_FULL);
1923 //slf021220b begin Fix still more bugs in CreateFile.
1924 else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
1927 SetLastError(ERROR_ALREADY_EXISTS);
1929 //slf021220b end Fix still more bugs in CreateFile.
1933 //slf021220b begin Fix still more bugs in CreateFile.
1934 //Match CE FAT error return SetLastError(ERROR_ALREADY_EXISTS);
1935 SetLastError(ERROR_FILE_EXISTS);
1936 //slf021220b begin Fix still more bugs in CreateFile.
1940 else if( dwCreate == OPEN_ALWAYS)
1942 //slf021220b begin Fix still more bugs in CreateFile.
1943 // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1944 //slf021220b end Fix still more bugs in CreateFile.
1947 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in OPEN_ALWAYS\r\n"));
1948 obj = yaffs_MknodFile(parent,name,mode,0,0);
1950 SetLastError(ERROR_DISK_FULL);
1954 //slf021220b begin Fix still more bugs in CreateFile.
1955 else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
1958 SetLastError(ERROR_ACCESS_DENIED);
1960 //slf021220b end Fix still more bugs in CreateFile.
1963 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening existing file in OPEN_ALWAYS\r\n"));
1966 else if(dwCreate == OPEN_EXISTING)
1968 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in OPEN_EXISTING\r\n"));
1969 //slf021220b begin Fix still more bugs in CreateFile.
1970 // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1971 //slf021220b end Fix still more bugs in CreateFile.
1973 SetLastError(ERROR_FILE_NOT_FOUND);
1974 //slf021220b begin Fix still more bugs in CreateFile.
1977 // if (yfsd_GetObjectWinAttributes(obj) & FILE_ATTRIBUTE_DIRECTORY)
1979 // SetLastError(ERROR_ACCESS_DENIED);
1983 else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
1985 SetLastError(ERROR_ACCESS_DENIED);
1988 //slf021220b end Fix still more bugs in CreateFile.
1990 else if(dwCreate == TRUNCATE_EXISTING)
1992 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in TRUNCATE_EXISTING\r\n"));
1993 //slf021220b begin Fix still more bugs in CreateFile.
1994 // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1996 if (!writePermitted || (obj && (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)))
1999 SetLastError(ERROR_ACCESS_DENIED);
2002 //slf021220b end Fix still more bugs in CreateFile.
2004 // Indicate that file is to be truncated. This will happen later on assuming
2005 // that a sharing violation does not occur and that we can get a file handle.
2006 fTruncateExistingFile = TRUE;
2010 SetLastError(ERROR_FILE_NOT_FOUND);
2013 else if(dwCreate == CREATE_ALWAYS)
2015 //slf021220b begin Fix still more bugs in CreateFile.
2016 // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
2017 //slf021220b end Fix still more bugs in CreateFile.
2021 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file parent %X, name %a in CREATE_ALWAYS\r\n",parent,name));
2022 obj = yaffs_MknodFile(parent,name,mode,0,0);
2024 SetLastError(ERROR_DISK_FULL);
2027 //slf021220b begin Fix still more bugs in CreateFile.
2028 else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
2031 SetLastError(ERROR_ACCESS_DENIED);
2033 //slf021220b end Fix still more bugs in CreateFile.
2036 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile in CREATE_ALWAYS (already exists)\r\n"));
2037 // Indicate that file is to be recreated. This will happen later on assuming
2038 // that a sharing violation does not occur and that we can get a file handle.
2039 fAlwaysCreateOnExistingFile = TRUE;
2044 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile called with unknown flags %x\r\n", dwCreate));
2045 SetLastError(ERROR_INVALID_PARAMETER);
2050 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));
2051 SetLastError(ERROR_PATH_NOT_FOUND);
2058 openRead = openWrite =0;
2059 openReadAllowed = openWriteAllowed = 1;
2061 for(i = 0; i < MAX_WIN_FILE; i++)
2063 p = &yfsd_winFile[i];
2067 if (p->readPermitted) openRead = 1;
2068 if (p->writePermitted) openWrite = 1;
2069 if (!p->shareRead) openReadAllowed = 0;
2070 if (!p->shareWrite) openWriteAllowed = 0;
2075 // Now we test if the share works out.
2077 if((openRead && !shareRead) || // already open for read, but we are not prepared to share it for read
2078 (openWrite && !shareWrite) || // already open for write, but we are not prepared to share it for write
2079 (!openReadAllowed && readPermitted) || // already open with read sharing not permitted
2080 (!openWriteAllowed && writePermitted)) // same... write
2082 //slf021220c begin Fix error code for new sharing mode check code.
2083 SetLastError(ERROR_SHARING_VIOLATION);
2084 //slf021220c end Fix error code for new sharing mode check code.
2092 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));
2093 f = yfsd_GetWinFile();
2097 RETAILMSG (MSGSTATE, (L"YAFFS::Creatfile - no object\r\n"));
2103 handle = FSDMGR_CreateFileHandle(pVolume->mgrVolume,hProc,f);
2105 if(handle != INVALID_HANDLE_VALUE)
2107 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));
2109 if (fTruncateExistingFile)
2111 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - TRUNCATE_EXISTING - truncating existing file\r\n"));
2112 yaffs_ResizeFile(obj,0);
2115 if (fAlwaysCreateOnExistingFile)
2117 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - CREATE_ALWAYS - zapping existing file\r\n"));
2118 obj->st_mode = mode;
2120 yaffs_ResizeFile(obj,0);
2121 yaffs_FlushFile(obj,1);
2126 f->writePermitted = writePermitted;
2127 //slf021220d begin oops typo.
2128 f->readPermitted = readPermitted;
2129 //slf021220d end oops typo.
2130 f->shareRead= shareRead;
2131 f->shareWrite = shareWrite;
2132 f->myVolume = pVolume;
2135 modifiedTime[0] = obj->win_mtime[0];
2136 modifiedTime[1] = obj->win_mtime[1];
2137 objSize = yaffs_GetObjectFileLength(obj);
2138 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - file size %d\r\n",objSize));
2143 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have no fsdmgr handle\r\n"));
2150 if(handle != INVALID_HANDLE_VALUE &&
2152 pVolume->shellFunction)
2155 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2157 fc.cbSize = sizeof(FILECHANGEINFO);
2158 fc.wEventId = SHCNE_CREATE;
2159 fc.uFlags = SHCNF_PATH;
2160 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
2162 fc.dwAttributes = mode;
2163 yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
2164 fc.nFileSize = objSize;
2166 pVolume->shellFunction(&fc);
2167 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2169 yfsd_ShellDirectoryChanged(pVolume,fpn);
2172 if(handle != INVALID_HANDLE_VALUE && (fileCreated || writePermitted))
2174 // Remember the name
2176 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2179 yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
2181 f->fullName = malloc((slen+1)* sizeof(WCHAR));
2184 wcscpy(f->fullName,fpn);
2194 BOOL yfsd_DoReadFile(
2203 yaffs_Object *obj = NULL;
2212 RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile pcbRead was NULL. naughty.\r\n"));
2215 RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile %d bytes\r\n",cbRead));
2217 if(!pFile || !pFile->obj)
2219 SetLastError(ERROR_INVALID_HANDLE);
2225 if(yaffs_GetObjectFileLength(obj) > pFile->offset)
2227 maxRead = yaffs_GetObjectFileLength(obj) - pFile->offset;
2234 if(cbRead > maxRead)
2241 nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);
2244 pFile->offset += nread;
2261 return nread < 0? FALSE : TRUE;
2270 OVERLAPPED *pOverlapped ) //ignore
2274 RETAILMSG (MSGSTATE, (L"YAFFS::ReadFile\r\n"));
2276 if(!pFile || !pFile->obj)
2278 SetLastError(ERROR_INVALID_HANDLE);
2284 result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
2291 BOOL YFSD_ReadFileWithSeek(
2296 OVERLAPPED *pOverlapped,
2298 DWORD dwHighOffset )
2301 DWORD rememberedOffset;
2303 RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));
2305 // To determine if paging is supported, the kernel calls this with all parameters except pFile
2307 if(!pBuffer && !cbRead && !pcbRead && !pOverlapped && !dwLowOffset && !dwHighOffset)
2309 return TRUE; // paging suppported
2310 //return FALSE; // paging not supported
2313 if(!pFile || !pFile->obj)
2315 SetLastError(ERROR_INVALID_HANDLE);
2321 rememberedOffset = pFile->offset;
2323 pFile->offset = dwLowOffset;
2324 // ignore high offset for now
2326 result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
2328 //pFile->offset = rememberedOffset;
2338 BOOL yfsd_DoWriteFile(
2345 yaffs_Object *obj = NULL;
2347 RETAILMSG (MSGSTATE, (L"YAFFS::DoWriteFile size %d\r\n",cbWrite));
2349 if(!pFile || !pFile->obj)
2351 SetLastError(ERROR_INVALID_HANDLE);
2355 if(!pFile->writePermitted)
2358 SetLastError(ERROR_ACCESS_DENIED);
2367 nwritten = yaffs_WriteDataToFile(obj,pBuffer,pFile->offset,cbWrite);
2370 pFile->offset += nwritten;
2371 *pcbWritten = nwritten;
2373 if(nwritten != cbWrite)
2375 SetLastError(ERROR_DISK_FULL);
2379 return nwritten != cbWrite? FALSE : TRUE;
2383 BOOL YFSD_WriteFile(
2388 OVERLAPPED *pOverlapped )
2393 RETAILMSG (MSGSTATE, (L"YAFFS::WriteFile\r\n"));
2395 result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
2402 BOOL YFSD_WriteFileWithSeek(
2407 OVERLAPPED *pOverlapped,
2409 DWORD dwHighOffset )
2412 DWORD rememberedOffset;
2413 RETAILMSG (MSGSTATE, (L"YAFFS::WriteFileWithSeek %d bytes at %d,%d pcbWritten %X\r\n",cbWrite,dwHighOffset,dwLowOffset,pcbWritten));
2417 if(!pFile || !pFile->obj)
2419 SetLastError(ERROR_INVALID_HANDLE);
2425 rememberedOffset = pFile->offset;
2427 pFile->offset = dwLowOffset;
2428 // ignore high offset for now
2430 result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
2432 //pFile->offset = rememberedOffset;
2439 DWORD YFSD_SetFilePointer(
2441 LONG lDistanceToMove,
2442 PLONG pDistanceToMoveHigh,
2443 DWORD dwMoveMethod )
2445 // ignore high offset for now
2447 DWORD offset = 0xFFFFFFFF;
2450 int seekNegative = 0;
2453 if(!pFile || !pFile->obj)
2455 SetLastError(ERROR_INVALID_HANDLE);
2462 oldPos = pFile->offset;
2464 if(dwMoveMethod == FILE_BEGIN)
2466 if(lDistanceToMove >= 0)
2468 offset = pFile->offset = lDistanceToMove;
2475 else if(dwMoveMethod == FILE_END)
2477 fileSize = yaffs_GetObjectFileLength(pFile->obj);
2479 (fileSize + lDistanceToMove) >= 0)
2481 offset = pFile->offset = fileSize + lDistanceToMove;
2488 else if(dwMoveMethod == FILE_CURRENT)
2490 if(pFile->offset + lDistanceToMove >= 0)
2492 offset = pFile->offset = pFile->offset + lDistanceToMove;
2502 SetLastError(ERROR_NEGATIVE_SEEK);
2508 RETAILMSG (MSGSTATE, (L"YAFFS::SetFilePtr method %d distance %d high %X oldpos %d newpos %d\r\n",
2509 dwMoveMethod,lDistanceToMove,pDistanceToMoveHigh,oldPos,offset));
2515 DWORD YFSD_GetFileSize(
2517 PDWORD pFileSizeHigh )
2521 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileSize high %X\r\n",pFileSizeHigh));
2524 if(!pFile || !pFile->obj)
2526 SetLastError(ERROR_INVALID_HANDLE);
2532 fileSize = yaffs_GetObjectFileLength(pFile->obj);
2543 BOOL YFSD_GetFileInformationByHandle(
2545 PBY_HANDLE_FILE_INFORMATION pFileInfo )
2547 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileInfoByHandle\r\n"));
2549 if(!pFile || !pFile->obj || !pFileInfo)
2551 SetLastError(ERROR_INVALID_HANDLE);
2557 pFileInfo->dwFileAttributes = yfsd_GetObjectWinAttributes(pFile->obj);
2558 yfsd_U32sToWinFileTime(pFile->obj->win_ctime,&pFileInfo->ftCreationTime);
2559 yfsd_U32sToWinFileTime(pFile->obj->win_atime,&pFileInfo->ftLastAccessTime);
2560 yfsd_U32sToWinFileTime(pFile->obj->win_mtime,&pFileInfo->ftLastWriteTime);
2561 pFileInfo->dwVolumeSerialNumber = 0; //todo is this OK?
2562 pFileInfo->nFileSizeHigh = 0;
2563 pFileInfo->nFileSizeLow = yaffs_GetObjectFileLength(pFile->obj);
2564 pFileInfo->nNumberOfLinks = 1; // only primary link supported like FAT
2565 pFileInfo->nFileIndexHigh = 0;
2566 pFileInfo->nFileIndexLow = pFile->obj->objectId;
2567 pFileInfo->dwOID = (CEOID)(INVALID_HANDLE_VALUE);
2574 BOOL YFSD_FlushFileBuffers(PFILE pFile )
2576 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2578 yfsd_Volume *vol = NULL;
2584 RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));
2586 if(!pFile || !pFile->obj)
2588 SetLastError(ERROR_INVALID_HANDLE);
2594 yaffs_FlushFile(pFile->obj,1);
2595 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2596 objSize = yaffs_GetObjectFileLength(pFile->obj);
2597 mtime[0] = pFile->obj->win_mtime[0];
2598 mtime[1] = pFile->obj->win_mtime[1];
2601 wcscpy(fpn,pFile->fullName);
2604 vol = pFile->myVolume;
2608 if(vol && vol->shellFunction && nameExists)
2612 fc.cbSize = sizeof(FILECHANGEINFO);
2613 fc.wEventId = SHCNE_UPDATEITEM;
2614 fc.uFlags = SHCNF_PATH;
2615 fc.dwItem1 = (DWORD)fpn;
2617 fc.dwAttributes = attribs;
2618 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2619 fc.nFileSize = objSize;
2621 vol->shellFunction(&fc);
2622 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2623 //yfsd_ShellDirectoryChanged(vol,fpn);
2630 BOOL YFSD_GetFileTime(
2632 FILETIME *pCreation,
2633 FILETIME *pLastAccess,
2634 FILETIME *pLastWrite )
2637 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileTime\r\n"));
2638 if(!pFile || !pFile->obj)
2640 SetLastError(ERROR_INVALID_HANDLE);
2646 if(pCreation) yfsd_U32sToWinFileTime(pFile->obj->win_ctime,pCreation);
2647 if(pLastAccess) yfsd_U32sToWinFileTime(pFile->obj->win_atime,pLastAccess);
2648 if(pLastWrite) yfsd_U32sToWinFileTime(pFile->obj->win_mtime,pLastWrite);
2655 BOOL YFSD_SetFileTime(
2657 CONST FILETIME *pCreation,
2658 CONST FILETIME *pLastAccess,
2659 CONST FILETIME *pLastWrite )
2661 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2664 yfsd_Volume *vol = NULL;
2670 RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));
2672 if(!pFile || !pFile->obj)
2674 SetLastError(ERROR_INVALID_HANDLE);
2683 yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);
2684 pFile->obj->dirty = 1;
2688 yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);
2689 pFile->obj->dirty = 1;
2693 yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);
2694 pFile->obj->dirty = 1;
2696 if(pCreation || pLastAccess || pLastWrite)
2698 result = yaffs_FlushFile(pFile->obj,0);
2703 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2704 objSize = yaffs_GetObjectFileLength(pFile->obj);
2705 mtime[0] = pFile->obj->win_mtime[0];
2706 mtime[1] = pFile->obj->win_mtime[1];
2709 wcscpy(fpn,pFile->fullName);
2712 vol = pFile->myVolume;
2717 // Call shell function
2718 if(nameExists && result && vol && vol->shellFunction)
2722 fc.cbSize = sizeof(FILECHANGEINFO);
2723 fc.wEventId = SHCNE_UPDATEITEM;
2724 fc.uFlags = SHCNF_PATH;
2725 fc.dwItem1 = (DWORD)fpn;
2727 fc.dwAttributes = attribs;
2728 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2729 fc.nFileSize = objSize;
2731 vol->shellFunction(&fc);
2732 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2733 //yfsd_ShellDirectoryChanged(vol,fpn);
2739 BOOL YFSD_SetEndOfFile(
2743 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2745 yfsd_Volume *vol = NULL;
2749 static unsigned char zeros[512];
2752 BOOL retVal = FALSE;
2754 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF\r\n"));
2756 if(!pFile || !pFile->obj)
2758 SetLastError(ERROR_INVALID_HANDLE);
2763 result = yaffs_ResizeFile(pFile->obj,pFile->offset);
2765 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF resizing to %d, result %d\r\n",pFile->offset,result));
2767 // Resize only works if we're shortening the file.
2768 // If the result is shorter than the offset, then we need to write zeros....
2770 if(result != pFile->offset)
2772 if(result < pFile->offset)
2775 int nBytes = pFile->offset - result;
2780 memset(zeros,0,512);
2782 pFile->offset = result;
2783 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF expanding file by %d bytes\r\n",nBytes));
2784 while(nBytes > 0 && ok)
2786 thisWriteSize = (nBytes > 512) ? 512 : nBytes;
2788 ok = yfsd_DoWriteFile(pFile,zeros,thisWriteSize,&written);
2789 if(written != thisWriteSize)
2794 nBytes -= thisWriteSize;
2802 SetLastError(ERROR_ACCESS_DENIED);
2812 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2813 objSize = yaffs_GetObjectFileLength(pFile->obj);
2814 mtime[0] = pFile->obj->win_mtime[0];
2815 mtime[1] = pFile->obj->win_mtime[1];
2818 wcscpy(fpn,pFile->fullName);
2821 vol = pFile->myVolume;
2827 if(nameExists && retVal && vol && vol->shellFunction)
2831 fc.cbSize = sizeof(FILECHANGEINFO);
2832 fc.wEventId = SHCNE_UPDATEITEM;
2833 fc.uFlags = SHCNF_PATH;
2834 fc.dwItem1 = (DWORD)fpn;
2836 fc.dwAttributes = attribs;
2837 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2838 fc.nFileSize = objSize;
2840 vol->shellFunction(&fc);
2841 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2842 //yfsd_ShellDirectoryChanged(vol,fpn);
2845 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF file size %d\r\n",yaffs_GetObjectFileLength(pFile->obj)));
2852 BOOL YFSD_DeviceIoControl(
2854 DWORD dwIoControlCode,
2859 PDWORD pBytesReturned,
2860 OVERLAPPED *pOverlapped )
2862 RETAILMSG (MSGSTATE, (L"YAFFS::DeviceIoControl\r\n"));
2867 BOOL YFSD_CloseFile( PFILE pFile )
2869 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2871 yfsd_Volume *vol = NULL;
2876 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));
2882 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null pFile\r\n"));
2888 pFile->obj->inUse--;
2889 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));
2890 yaffs_FlushFile(pFile->obj,1);
2891 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2892 objSize = yaffs_GetObjectFileLength(pFile->obj);
2893 mtime[0] = pFile->obj->win_mtime[0];
2894 mtime[1] = pFile->obj->win_mtime[1];
2895 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));
2898 wcscpy(fpn,pFile->fullName);
2901 vol = pFile->myVolume;
2902 yfsd_PutWinFile(pFile);
2906 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null obj\r\n"));
2913 if(nameExists && vol && vol->shellFunction)
2917 fc.cbSize = sizeof(FILECHANGEINFO);
2918 fc.wEventId = SHCNE_UPDATEITEM;
2919 fc.uFlags = SHCNF_PATH;
2920 fc.dwItem1 = (DWORD)fpn;
2922 fc.dwAttributes = attribs;
2923 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2924 fc.nFileSize = objSize;
2926 vol->shellFunction(&fc);
2927 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2928 //yfsd_ShellDirectoryChanged(vol,fpn);
2933 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile done\r\n"));
2940 BOOL YFSD_CloseVolume(PVOLUME pVolume )
2942 RETAILMSG (MSGSTATE, (L"YAFFS::CloseVolume\r\n"));
2943 yfsd_FlushAllFiles();