2 * YAFFS: Yet another FFS. A NAND-flash specific file system.
\r
3 * ynandif.c: NAND interface functions for the WinCE port of YAFFS.
\r
5 * Copyright (C) 2002 Trimble Navigation Ltd.
\r
7 * Created by Charles Manning <charles.manning@trimble.co.nz>
\r
9 * This program is free software; you can redistribute it and/or modify
\r
10 * it under the terms of the GNU General Public License version 2 as
\r
11 * published by the Free Software Foundation.
\r
13 * This program is distributed in the hope that it will be useful,
\r
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
\r
16 * General Public License for more details. You should have received a
\r
17 * copy of the GNU General Public License along with this program;
\r
18 * if not, write to the Free Software Foundation, Inc.,
\r
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
22 * Various clean-ups and WinCE4 support by Steve Fogle
\r
23 * $Id: yaffsfsd.c,v 1.2 2003-01-14 23:15:41 charles Exp $
\r
27 #include <yaffs_guts.h>
28 #include <ynandif.h>
\r
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"
\r
41 #define PARTITION_START_NUMBER (1280)
43 //#define MSGSTATE 1
\r
45 //#define DISABLE_BOOT_PARTITION
\r
47 // Define DO_PARTITION_TABLE to cause the partition table
\r
48 // information to be retrieved from the block driver.
\r
49 //#define DO_PARTITION_TABLE
\r
50 // How many partitions the disk might have. 2 gives
\r
51 // space for the "Disk" and "Boot" partitions.
\r
52 #define MAXPARTITIONS (2)
\r
55 //unsigned yaffs_traceMask=0xffffffff;
56 unsigned yaffs_traceMask=0;
\r
63 DWORD mgrVolume; // The volume id from the manager issed when we registered it - it is an HVOL
68 SHELLFILECHANGEFUNC_t shellFunction;
79 yfsd_Volume *myVolume;
80 BOOL writePermitted;
\r
87 struct yfsd_FoundObjectStruct
90 struct yfsd_FoundObjectStruct *next;
93 typedef struct yfsd_FoundObjectStruct yaffs_FoundObject;
98 char pattern[YFSD_NAME_LENGTH+1];
99 yaffs_FoundObject *foundObjects;
104 #define PSEARCH yfsd_WinFind*
106 #define PVOLUME yfsd_Volume*
107 #define PFILE yfsd_WinFile*
114 //static yfsd_Volume disk_volume;
115 //static yfsd_Volume boot_volume;
\r
116 static yfsd_Volume * disk_volumes[MAXPARTITIONS];
\r
119 static CRITICAL_SECTION yaffsLock;
120 static CRITICAL_SECTION winFileLock;
122 static int yaffsLockInited = 0;
124 static yfsd_WinFile yfsd_winFile[MAX_WIN_FILE];
127 static yfsd_SetGuards(void)
130 for(i = 0; i < 100; i++)
132 yfsd_volume.guard0[i] = yfsd_volume.guard1[i] = i;
136 static void yfsd_CheckGuards(void)
140 for(i = found = 0; i < 100 && !found; i++)
142 if(yfsd_volume.guard0[i] != i)
144 RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
147 if(yfsd_volume.guard1[i] != i)
149 RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
156 void yfsd_LockWinFiles(void)
158 //RETAILMSG (MSGSTATE, (L"YAFFS::LockWinfiles\r\n"));
159 EnterCriticalSection(&winFileLock);
161 void yfsd_UnlockWinFiles(void)
163 //RETAILMSG (MSGSTATE, (L"YAFFS::UnlockWinFiles\r\n"));
164 LeaveCriticalSection(&winFileLock);
169 void yfsd_LockYAFFS(void)
171 //yfsd_CheckGuards();
172 //RETAILMSG (MSGSTATE, (L"YAFFS::LockYAFFS %d ",lockwaits));
174 EnterCriticalSection(&yaffsLock);
175 //RETAILMSG (MSGSTATE, (L" locked\r\n"));
177 void yfsd_UnlockYAFFS(void)
179 //yfsd_CheckGuards();
180 //RETAILMSG (MSGSTATE, (L"YAFFS::UnLockYAFFS "));
181 LeaveCriticalSection(&yaffsLock);
183 //RETAILMSG (MSGSTATE, (L" unlocked\r\n"));
187 void yfsd_InitialiseWinFiles(void)
191 RETAILMSG (MSGSTATE, (L"YAFFS::InitWinFiles\r\n"));
193 InitializeCriticalSection(&winFileLock);
196 for(i = 0; i < MAX_WIN_FILE; i++)
198 yfsd_winFile[i].isopen = 0;
200 yfsd_UnlockWinFiles();
203 yfsd_WinFile * yfsd_GetWinFile(void)
206 RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles\r\n"));
210 for(i = 0; i < MAX_WIN_FILE; i++)
212 if(!yfsd_winFile[i].isopen)
214 yfsd_winFile[i].isopen = 1;
215 yfsd_winFile[i].writePermitted = 0;
\r
216 yfsd_winFile[i].readPermitted = 0;
\r
217 yfsd_winFile[i].shareRead = 0;
\r
218 yfsd_winFile[i].shareWrite = 0;
\r
219 yfsd_winFile[i].dirty = 0;
220 yfsd_winFile[i].fullName = NULL;
221 yfsd_winFile[i].obj = NULL;
223 yfsd_UnlockWinFiles();
224 return &yfsd_winFile[i];
228 yfsd_UnlockWinFiles();
230 RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles did not find a handle. Too many open.\r\n"));
235 void yfsd_PutWinFile(yfsd_WinFile *f)
237 RETAILMSG (MSGSTATE, (L"YAFFS::PutWinFile\r\n"));
247 yfsd_UnlockWinFiles();
252 void yfsd_FlushAllFiles(void)
255 RETAILMSG (MSGSTATE, (L"YAFFS::FlushAllFiles\r\n"));
259 for(i = 0; i < MAX_WIN_FILE; i++)
261 if(yfsd_winFile[i].isopen &&
264 yaffs_FlushFile(yfsd_winFile[i].obj,1);
267 yfsd_UnlockWinFiles();
272 //////////////////////////////////////////////////////////////////////
\r
273 // Search through winFiles to see if any are open.
\r
275 BOOL yfsd_FilesOpen(void)
\r
279 RETAILMSG (MSGSTATE, (L"YAFFS::FilesOpen?\r\n"));
\r
281 yfsd_LockWinFiles();
\r
282 for(i = 0, rval = FALSE; i < MAX_WIN_FILE; i++)
\r
284 if(yfsd_winFile[i].isopen)
\r
290 yfsd_UnlockWinFiles();
\r
295 PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
298 // todo check for bounds
\r
300 //volName already has the initial backslash if it needs it.
301 //wcscpy(fpn,L"\\");
\r
302 //wcscat(fpn,vol->volName);
303 wcscpy(fpn,vol->volName);
\r
305 if(pathName[0] != '\\')
309 wcscat(fpn,pathName);
316 // FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.
318 void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)
321 wft->dwLowDateTime = target[0];
322 wft->dwHighDateTime = target[1];
326 void yfsd_NullWinFileTime(FILETIME *wft)
328 wft->dwLowDateTime = 0;
329 wft->dwHighDateTime = 0;
332 void yfsd_WinFileTimeToU32s(const FILETIME *wft, __u32 target[2])
334 target[0] = wft->dwLowDateTime;
335 target[1] = wft->dwHighDateTime;
338 void yfsd_WinFileTimeNow(__u32 target[2])
344 SystemTimeToFileTime(&st,&ft);
345 yfsd_WinFileTimeToU32s(&ft,target);
348 // Cut down the name to the parent directory, then inform the shell of
349 // a change to the directory.
350 void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)
354 wcscpy(str,fullPathName);
364 // Curveball if the name is a directory (ie. we're doing an update of
365 // a directory because we added a directory item). , then it might end in a \
366 // which we must toss first
367 if(i >= 0 && (str[i] == '\\' || str[i] == '/'))
373 // Ok, now strip back...
375 while(i >= 0 && str[i] != '\\' && str[i] != '/')
381 if(pVolume->shellFunction)
385 fc.cbSize = sizeof(FILECHANGEINFO);
386 fc.wEventId = SHCNE_UPDATEDIR;
387 fc.uFlags = SHCNF_PATH;
388 fc.dwItem1 = (DWORD)str;
391 yfsd_NullWinFileTime(&fc.ftModified);
394 pVolume->shellFunction(&fc);
395 RETAILMSG (MSGSTATE, (L"YAFFS:: directory changed %s\r\n",str));
403 // Minimal name test for now
404 BOOL yfsd_NameIsValid (const char *name)
406 int length = strlen(name);
408 return (length > 0 && length <= YFSD_NAME_LENGTH);
413 // Wince understands the following attributes of any use to YAFFS:
421 // Also, FILE_ATTRIBUTE_DIRECTORY is used to mark directories.
423 // It also understands NORMAL. If no other flag is set, then set NORMAL.
424 // If any of the above are set, then NORMAL must **not** be set.
425 // Ignore this and the WinCE Explorer barfs the file.
428 // in addition, GetAttributes also returns FILE_ATTRIBUTE_DIRECTORY
430 // The following are valid ones we get presented with,
431 // but must filter out the stuff we don't unserstand
432 //#define FILE_ATTRIBUTE_READONLY 0x00000001
433 //#define FILE_ATTRIBUTE_HIDDEN 0x00000002
434 //#define FILE_ATTRIBUTE_SYSTEM 0x00000004
435 //#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
436 //#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
437 //#define FILE_ATTRIBUTE_INROM 0x00000040
438 //#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
439 //#define FILE_ATTRIBUTE_NORMAL 0x00000080
440 //#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
441 //#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
442 //#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
443 //#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
444 //#define FILE_ATTRIBUTE_OFFLINE 0x00001000
445 //#define FILE_ATTRIBUTE_ROMSTATICREF 0x00001000
446 //#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
447 //#define FILE_ATTRIBUTE_ROMMODULE 0x00002000
450 BOOL yfsd_CheckValidAttributes(DWORD attribs)
453 RETAILMSG (MSGSTATE, (L"Attributes:%X\r\n", attribs));
456 // If NORMAL, then nothing else
457 if(attribs & FILE_ATTRIBUTE_NORMAL && attribs != FILE_ATTRIBUTE_NORMAL)
459 if(attribs == FILE_ATTRIBUTE_NORMAL)
462 // Check that the bits are in the valid set
463 if(attribs & ~(0x3FE7))
469 DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)
474 result = obj->st_mode &
475 (FILE_ATTRIBUTE_READONLY |
476 FILE_ATTRIBUTE_ARCHIVE |
477 FILE_ATTRIBUTE_HIDDEN |
478 FILE_ATTRIBUTE_SYSTEM);
480 if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;
482 if(result & ~FILE_ATTRIBUTE_NORMAL)
484 result &= ~FILE_ATTRIBUTE_NORMAL;
488 result = FILE_ATTRIBUTE_NORMAL;
498 * Runs over input until a '\' is found, or '\0' is found, or outSize - 1 is
499 * reached. Characters are copied from input into output until the above stop
500 * condition is reached - output is then given a '\0'. output must be at least
501 * as large as outSize
503 static int parseToNextSlash(const unsigned short *input, char *output, int outSize)
507 /* strip any starting \'s */
508 //RETAILMSG(1, (L"\r\nParsing.. "));
509 while (*input == '\\' || *input == '/') input++, counter++;
511 for (; counter < outSize - 1; counter++)
513 if (*input == '\0' ||
514 ((*input == '\\' || *input == '/') && input[1] == '\0')) // special case: if the string ends in a '\', then toss the '\'
516 counter = -1; // break & tell people we've run to the end
519 if (*input == '\\' || *input == '/')
521 //RETAILMSG(1, (L"%c", *input));
522 *output = (char) (*input);
528 // RETAILMSG(1, (L"\r\nOut %a\r\n", t));
534 * Since the notion of paths as WinCE sees them and as YAFFS sees them
535 * is different, we needed a helper function to search from the root of
536 * device along the string in path. The processed pointer is set to where
537 * abouts in the string the function was able to search up to.
539 yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *path, char *processed, int length)
541 // a buffer to keep the current chunk of path we're talking about it
545 // the current object we are at
546 yaffs_Object *current;
548 RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));
549 // start at the root of this device
550 current = yaffs_Root(device);
555 // parse chunks until we run out
556 chunkSize = parseToNextSlash(path, pathChunk, 255);
557 // RETAILMSG(1, (L"Chunk %a\r\n", pathChunk));
560 // move the path pointer along
562 // try and find the next yaffs object by chunkname
563 current = yaffs_FindObjectByName(current, pathChunk);
571 for (counter = 0; counter < length; counter++)
573 // Get the rest of the string
574 processed[counter] = pathChunk[counter];
575 if (pathChunk[counter] == '\0')
579 RETAILMSG (MSGSTATE, (L"YAFFS::FindDirectoryByWinPath parent:%X name:%a\r\n", current,processed));
585 yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )
587 yaffs_Object *obj = NULL;
588 yaffs_Object *parent = NULL;
589 char name[YFSD_NAME_LENGTH+1];
591 RETAILMSG (MSGSTATE, (L"YAFFS::FindObjByWinPath\r\n"));
593 parent = yfsd_FindDirectoryByWinPath(dev,pwsFileName,name,YFSD_NAME_LENGTH);
595 if(parent && yfsd_NameIsValid(name))
597 obj = yaffs_FindObjectByName(parent,name);
600 RETAILMSG (MSGSTATE, (L"YAFFS::FindObjectByWinPath parent:%X obj:%X\r\n", parent,obj));
605 BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)
608 WCHAR szName[MAX_PATH];
\r
611 RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));
\r
612 //slf021104b Begin filled in later.
613 //vol->volName = volName;
\r
619 //Mount/initialise YAFFs here
620 ynandif_InitialiseNAND(&vol->dev);
622 vol->dev.writeChunkToNAND = ynandif_WriteChunkToNAND;
623 vol->dev.readChunkFromNAND = ynandif_ReadChunkFromNAND;
624 vol->dev.eraseBlockInNAND = ynandif_EraseBlockInNAND;
625 vol->dev.initialiseNAND = ynandif_InitialiseNAND;
626 vol->dev.startBlock = startBlock;
628 vol->dev.endBlock = endBlock;
\r
629 vol->dev.nShortOpCaches = 10; // a nice number of caches.
631 // nBlocks is set the total size of the disk, not the partition
632 // vol->dev.nBlocks = endBlock - startBlock + 1;
634 // qnand_EraseAllBlocks(&vol->dev);
636 yaffs_GutsInitialise(&vol->dev);
637 RETAILMSG(1, (L"YAFFS::Done yaffs_GutsInitialise\r\n"));
639 RETAILMSG(1, (L"Blocks start %d end %d Group size %d bits %d\r\n",
640 vol->dev.startBlock,vol->dev.endBlock,
641 vol->dev.chunkGroupSize,vol->dev.chunkGroupBits));
645 for(i = vol->dev.startBlock; i <= vol->dev.endBlock; i++)
647 switch(vol->dev.blockInfo[i].blockState)
649 case YAFFS_BLOCK_STATE_DEAD:
651 RETAILMSG(1, (L"YAFFS::Dead block %d\r\n",i));
654 case YAFFS_BLOCK_STATE_EMPTY: emptyBlox++; break;
655 case YAFFS_BLOCK_STATE_FULL: fullBlox++; break;
656 case YAFFS_BLOCK_STATE_ALLOCATING: allocatingBlox++; break;
657 case YAFFS_BLOCK_STATE_DIRTY: dirtyBlox++; break;
659 RETAILMSG(1, (L"YAFFS::Block %d has goofus state %d\r\n",i,vol->dev.blockInfo[i].blockState));
664 RETAILMSG(1, (L"Blocks dead %d empty %d full %d allocating %d dirty %d\r\n",
665 deadBlox,emptyBlox,fullBlox,allocatingBlox,dirtyBlox));
674 //vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);
\r
675 // If the caller passed a volume name use it.
\r
677 wcscpy( szName, volName);
\r
678 #if WINCEOSVER >= 400
\r
679 // The user passed an empty volume name. On CE 4.xx try to get
\r
680 // if from the block driver (which got it from the registry).
\r
681 else if (!FSDMGR_DiskIoControl(hdsk, DISK_IOCTL_GETNAME, NULL, 0, (LPVOID)szName, sizeof(szName), &dwAvail, NULL))
\r
686 // Didn't get a volume name so use "Disk" by default.
\r
687 wcscpy( szName, YFSD_DISK_NAME);
\r
689 vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,szName,vol);
\r
695 // Get some space for the volume name.
696 vol->volName = malloc( MAX_PATH * sizeof(WCHAR));
\r
699 #if WINCEOSVER >= 400
\r
700 // Get the name we were really mounted under.
\r
701 FSDMGR_GetVolumeName(vol->mgrVolume, vol->volName, MAX_PATH);
\r
703 // If we got mounted as root then throw away the backslash
\r
704 // so we won't get a double backslash when volName is
\r
705 // prepended to the path in the full path name calculation
\r
706 // that is used for shell callbacks.
\r
707 if (0 == wcscmp(vol->volName,L"\\"))
\r
708 vol->volName[0] = 0;
\r
710 // Use the name we asked to be mounted under for
\r
712 wcscpy(vol->volName,L"\\");
\r
713 wcscat(vol->volName, szName);
\r
722 SetLastError(ERROR_OUTOFMEMORY);
728 BOOL YFSD_MountDisk(HDSK hdsk)
731 #ifdef DO_PARTITION_TABLE
\r
732 ynandif_partition PartTable[MAXPARTITIONS];
\r
738 int deadBlox=0,emptyBlox=0,fullBlox=0,allocatingBlox=0,dirtyBlox=0;
740 // Called to mount a disk.
741 // NB THis call might happen redundantly.
744 // If yaffs is not initialised, then call the
745 // initialisation function
747 RETAILMSG (MSGSTATE, (L"YAFFS::MountDisk\r\n"));
749 if (!yaffsLockInited)
751 InitializeCriticalSection(&yaffsLock);
752 yfsd_InitialiseWinFiles();
757 memset(disk_volumes,0,sizeof(disk_volumes));
\r
758 #ifdef DO_PARTITION_TABLE
\r
759 memset(&PartTable,0,sizeof(PartTable));
\r
760 // Call the block driver to get the partition table from it.
\r
761 if (FSDMGR_DiskIoControl(hdsk, YNANDIF_GETPARTITIONS, NULL, 0, (LPVOID)&PartTable, sizeof(PartTable), &dwAvail, NULL))
\r
763 // Scan throught the table it return.
\r
764 for (i=0; i<MAXPARTITIONS; i++)
\r
766 // At the very lease check that the end is later than the beginning
\r
767 // and don't let it start at 0.
\r
768 // Probably could do more thorough checking but I trust the block
\r
770 if (PartTable[i].startBlock && (PartTable[i].endBlock > PartTable[i].startBlock))
\r
772 // Found a partion. Get a volume structure to hold it.
\r
773 disk_volumes[i] = malloc(sizeof(yfsd_Volume));
\r
774 if (disk_volumes[i])
\r
776 memset(disk_volumes[i],0,sizeof(yfsd_Volume));
\r
777 // Go init the volume. Note that if the block driver wants the
\r
778 // name to come from the registry it will have returned an
\r
779 // empty name string.
\r
780 YFSD_InitVolume(hdsk,disk_volumes[i],PartTable[i].startBlock,PartTable[i].endBlock,PartTable[i].volName);
\r
781 if (disk_volumes[i]->isMounted)
\r
782 rval = TRUE; //Hey, we found at least on partition.
\r
791 #ifdef DISABLE_BOOT_PARTITION
792 // Only want disk volume
\r
793 disk_volumes[0] = malloc(sizeof(yfsd_Volume));
\r
794 if (disk_volumes[0])
\r
796 memset(disk_volumes[0],0,sizeof(yfsd_Volume));
\r
797 YFSD_InitVolume(hdsk, disk_volumes[0], 1, -1, YFSD_DISK_NAME);
\r
799 if(disk_volumes[0].isMounted)
\r
804 if (disk_volumes[0])
\r
806 free(disk_volumes[0];
\r
807 disk_volumes[0] = NULL;
\r
810 // Want both boot and disk
\r
811 disk_volumes[0] = malloc(sizeof(yfsd_Volume));
\r
812 disk_volumes[1] = malloc(sizeof(yfsd_Volume));
\r
813 if (disk_volumes[0] && disk_volumes[1])
\r
815 memset(disk_volumes[0],0,sizeof(yfsd_Volume));
\r
816 memset(disk_volumes[1],0,sizeof(yfsd_Volume));
\r
817 YFSD_InitVolume(hdsk, disk_volumes[0], PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
\r
818 YFSD_InitVolume(hdsk, disk_volumes[1], 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
\r
820 if(disk_volumes[0]->isMounted && disk_volumes[1]->isMounted)
\r
826 // If we got this far something went wrong. Make sure to
\r
827 // free any memory we allocated.
\r
828 if (disk_volumes[0])
\r
830 if (disk_volumes[0]->volName)
\r
832 free(disk_volumes[0]->volName);
\r
834 free(disk_volumes[0]);
\r
835 disk_volumes[0] = NULL;
\r
837 if (disk_volumes[1])
\r
839 if (disk_volumes[1]->volName)
\r
841 free(disk_volumes[1]->volName);
\r
843 free(disk_volumes[1]);
\r
844 disk_volumes[1] = NULL;
\r
850 // Only want disk volume
\r
851 // YFSD_InitVolume(hdsk, &disk_volume, 1, -1, YFSD_DISK_NAME);
854 // if(disk_volume.isMounted)
859 // // Want both boot and disk
860 // YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
861 // YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
864 // if(disk_volume.isMounted && boot_volume.isMounted)
876 // todo - get name from registry
881 BOOL YFSD_UnmountDisk(HDSK hdsk)
886 RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));
889 // If there are any files open don't let them dismount
\r
890 // it or the system will get very confused.
\r
891 if (yfsd_FilesOpen())
\r
894 //yfsd_FlushAllFiles();
\r
899 // yaffs_Deinitialise(&disk_volume.dev);
\r
900 // yaffs_Deinitialise(&boot_volume.dev);
\r
901 // yfsd_UnlockYAFFS();
903 // FSDMGR_DeregisterVolume(disk_volume.mgrVolume);
\r
904 // FSDMGR_DeregisterVolume(boot_volume.mgrVolume);
\r
906 // Walk through the partions deinitializing, deregistering
\r
907 // and freeing them.
\r
908 for (i=0; i<MAXPARTITIONS; i++)
\r
910 if (disk_volumes[i])
\r
912 yaffs_Deinitialise(&(disk_volumes[i]->dev));
\r
913 FSDMGR_DeregisterVolume(disk_volumes[i]->mgrVolume);
\r
914 if (disk_volumes[i]->volName)
\r
916 free(disk_volumes[i]->volName);
\r
918 free(disk_volumes[i]);
\r
919 disk_volumes[i] = NULL;
\r
922 yfsd_UnlockYAFFS();
\r
928 BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTES pSecurityAttributes)
930 // security attributes are ignored (should be NULL)
932 yaffs_Object *newDir = NULL;
933 yaffs_Object *parent = NULL;
934 char name[YFSD_NAME_LENGTH+1];
937 unsigned modifiedTime[2];
939 RETAILMSG (MSGSTATE, (L"YAFFS::CreateDirectory (%s)\r\n", pathName));
943 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
948 if(yfsd_NameIsValid(name))
950 newDir = yaffs_MknodDirectory(parent,name,0,0,0);
953 objSize = yaffs_GetObjectFileLength(newDir);
954 attribs = yfsd_GetObjectWinAttributes(newDir);
955 modifiedTime[0] = newDir->win_mtime[0];
956 modifiedTime[1] = newDir->win_mtime[1];
960 if(yaffs_FindObjectByName(parent,name))
961 SetLastError(ERROR_ALREADY_EXISTS);
963 SetLastError(ERROR_DISK_FULL);
967 SetLastError(ERROR_INVALID_NAME);
971 SetLastError(ERROR_PATH_NOT_FOUND);
977 // Call shell function to tell of new directory
978 if(newDir && pVolume->shellFunction)
981 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
983 fc.cbSize = sizeof(FILECHANGEINFO);
984 fc.wEventId = SHCNE_MKDIR;
985 fc.uFlags = SHCNF_PATH;
986 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume, fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
988 fc.dwAttributes = attribs;
989 yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
990 fc.nFileSize = objSize;
992 pVolume->shellFunction(&fc);
993 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
995 //yfsd_ShellDirectoryChanged(pVolume,fpn);
1000 // if(parent && !newDir)
1002 // SetLastError(ERROR_DISK_FULL);
1006 return newDir ? TRUE : FALSE;
1010 BOOL yfsd_RemoveObjectW(PVOLUME pVolume, PCWSTR pathName)
1012 // Fails if directory is not empty
1014 yaffs_Object *parent = NULL;
1016 char name[YFSD_NAME_LENGTH+1];
1018 RETAILMSG (MSGSTATE, (L"YAFFS::RemoveObjectW (%s)\r\n", pathName));
1022 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pathName);
1025 SetLastError(ERROR_FILE_NOT_FOUND);
1028 else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)
1030 SetLastError(ERROR_ACCESS_DENIED);
1035 SetLastError(ERROR_ACCESS_DENIED);
1041 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
1043 if(parent && yfsd_NameIsValid(name))
1045 result = yaffs_Unlink(parent,name);
1047 SetLastError(ERROR_ACCESS_DENIED);
1053 return result ? TRUE : FALSE;
1057 BOOL YFSD_RemoveDirectoryW(PVOLUME pVolume, PCWSTR pathName)
1060 RETAILMSG (MSGSTATE, (L"YAFFS::RemoveDirectory\r\n"));
1062 result = yfsd_RemoveObjectW(pVolume, pathName);
1064 if(result && pVolume->shellFunction)
1067 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1069 fc.cbSize = sizeof(FILECHANGEINFO);
1070 fc.wEventId = SHCNE_RMDIR;
1071 fc.uFlags = SHCNF_PATH;
1072 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
1074 fc.dwAttributes = 0;
1075 yfsd_NullWinFileTime(&fc.ftModified);
1078 pVolume->shellFunction(&fc);
1079 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1081 yfsd_ShellDirectoryChanged(pVolume,fpn);
1089 DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )
1091 yaffs_Object *obj = NULL;
1093 DWORD result = 0xFFFFFFFF;
1095 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes\r\n"));
1099 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1103 result = yfsd_GetObjectWinAttributes(obj);
1107 SetLastError(ERROR_FILE_NOT_FOUND);
1112 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes for %s returning %X\r\n",pwsFileName,result));
1118 BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )
1120 yaffs_Object *obj = NULL;
1127 RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));
1129 if(!yfsd_CheckValidAttributes(dwFileAttributes))
1131 SetLastError(ERROR_INVALID_PARAMETER);
1137 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1141 obj->st_mode = dwFileAttributes;
1143 result = yaffs_FlushFile(obj,0);
1144 attribs = yfsd_GetObjectWinAttributes(obj);
1145 objSize = yaffs_GetObjectFileLength(obj);
1146 mtime[0] = obj->win_mtime[0];
1147 mtime[1] = obj->win_mtime[1];
1151 SetLastError(ERROR_FILE_NOT_FOUND);
1156 if(result && pVolume->shellFunction)
1159 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1161 fc.cbSize = sizeof(FILECHANGEINFO);
1162 fc.wEventId = SHCNE_ATTRIBUTES;
1163 fc.uFlags = SHCNF_PATH;
1164 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1166 fc.dwAttributes = attribs;
1167 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
1168 fc.nFileSize = objSize;
1170 pVolume->shellFunction(&fc);
1171 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1173 //yfsd_ShellDirectoryChanged(pVolume,fpn);
1181 BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )
1184 RETAILMSG (MSGSTATE, (L"YAFFS::DeleteFileW (%s)\r\n", pwsFileName));
1186 result = yfsd_RemoveObjectW(pVolume, pwsFileName);
1187 if(result && pVolume->shellFunction)
1190 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1192 fc.cbSize = sizeof(FILECHANGEINFO);
1193 fc.wEventId = SHCNE_DELETE;
1194 fc.uFlags = SHCNF_PATH;
1195 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1197 fc.dwAttributes = -1;
1198 yfsd_NullWinFileTime(&fc.ftModified);
1201 pVolume->shellFunction(&fc);
1202 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1204 yfsd_ShellDirectoryChanged(pVolume,fpn);
1210 BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
1212 yaffs_Object *newParent = NULL;
1213 yaffs_Object *oldParent = NULL;
1214 yaffs_Object *obj = NULL;
1215 char oldName[YFSD_NAME_LENGTH+1];
1216 char newName[YFSD_NAME_LENGTH+1];
1223 RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));
1227 oldParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsOldFileName,oldName,YFSD_NAME_LENGTH);
1228 newParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsNewFileName,newName,YFSD_NAME_LENGTH);
1230 if(oldParent && yfsd_NameIsValid(oldName) && newParent && yfsd_NameIsValid(newName))
1232 result = yaffs_RenameObject(oldParent,oldName,newParent,newName);
1235 SetLastError(ERROR_FILE_NOT_FOUND);
1238 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsNewFileName);
1241 objIsDir = (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY);
1242 attribs = yfsd_GetObjectWinAttributes(obj);
1243 objSize = yaffs_GetObjectFileLength(obj);
1244 mtime[0] = obj->win_mtime[0];
1245 mtime[1] = obj->win_mtime[1];
1250 SetLastError(ERROR_PATH_NOT_FOUND);
1256 if(result && pVolume->shellFunction)
1259 WCHAR fpn1[YFSD_FULL_PATH_NAME_SIZE];
1260 WCHAR fpn2[YFSD_FULL_PATH_NAME_SIZE];
1262 fc.cbSize = sizeof(FILECHANGEINFO);
1263 fc.wEventId = objIsDir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM;
1264 fc.uFlags = SHCNF_PATH;
1265 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn1,YFSD_FULL_PATH_NAME_SIZE,pwsOldFileName);
1266 fc.dwItem2 = (DWORD)yfsd_FullPathName(pVolume,fpn2,YFSD_FULL_PATH_NAME_SIZE,pwsNewFileName);
1267 fc.dwAttributes = attribs;
1268 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
1269 fc.nFileSize = objSize;
1271 pVolume->shellFunction(&fc);
1272 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1274 yfsd_ShellDirectoryChanged(pVolume,fpn1);
1275 yfsd_ShellDirectoryChanged(pVolume,fpn2);
1279 return result ? TRUE : FALSE;
1283 BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
1285 //slf021104c begin
\r
1289 RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));
\r
1292 if (fSuccess = YFSD_DeleteFileW(pVolume, pwsOldFileName))
\r
1293 fSuccess = YFSD_MoveFileW(pVolume, pwsNewFileName, pwsOldFileName);
\r
1299 BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )
1304 RETAILMSG (MSGSTATE, (L"YAFFS::GetFreeSpace\r\n"));
1307 nChunks = yaffs_GetNumberOfFreeChunks(&pVolume->dev);
1312 // Let's pretentd our clusters are the same size as eraseable blocks...
1313 *pBytesPerSector = 512;
1314 *pSectorsPerCluster =32;
1315 *pFreeClusters = nChunks/32;
1316 *pClusters = pVolume->dev.endBlock - pVolume->dev.startBlock + 1;
1319 return (nChunks >= 0)? TRUE : FALSE;
1325 void YFSD_Notify(PVOLUME pVolume, DWORD dwFlags )
1327 // Flags can be one of:
1328 // FSNOTIFY_POWER_ON: no action required
1329 // FSNOTIFY_POWER_OFF: flush all files
1330 // FSNOTIFY_DEVICE_ON: no action required
1332 RETAILMSG (MSGSTATE, (L"YAFFS::Notify\r\n"));
1333 if(dwFlags == FSNOTIFY_POWER_OFF)
1335 yfsd_FlushAllFiles();
1341 BOOL YFSD_RegisterFileSystemFunction(PVOLUME pVolume,SHELLFILECHANGEFUNC_t pfn )
1343 RETAILMSG (MSGSTATE, (L"YAFFS::RegisterFileSysFunction\r\n"));
1345 pVolume->shellFunction = pfn;
1354 int iMatch(const char a, const char b)
1356 if (a == '?' || b == '?')
1358 return (toupper(a) == toupper(b));
1361 void pString(const char *inp)
1363 while (*inp) RETAILMSG(1, (L"%c", *inp++));
1366 int regularMatch(const char *regexp, const char *str)
1369 // RETAILMSG(1, (L" "));
1371 // RETAILMSG(1, (L"\r\n"));
1373 if (*regexp == 0 && *str == 0)
1375 //RETAILMSG(1, (L"Match!\r\n"));
1381 if (*regexp == 0) // end of the expression is a *, we must match
1383 //RETAILMSG(1, (L"Match!\r\n"));
1386 while (!iMatch(*regexp, *str)) // throw away chars from str until we match
1388 if (*str == 0) // if we're not at the end
1390 // if we have .* left to match, but the str is finished then match it OK
1391 if (regexp[0] == '.' && regexp[1] == '*')
1393 //RETAILMSG(1, (L"Match!\r\n"));
1398 // the extension failed the match
1399 //RETAILMSG(1, (L"No Match!\r\n"));
1405 // right now we should either eat more characters, or try to match
1406 return (regularMatch(regexp, str) || regularMatch(--regexp, ++str));
1408 // compare chars until we hit another *, or we fail
1409 while (iMatch(*regexp, *str))
1411 if (*regexp == 0 && *str == 0)
1413 //RETAILMSG(1, (L"Match!\r\n"));
1420 if (*regexp == 0 && *str == 0)
1422 //RETAILMSG(1, (L"Match!\r\n"));
1427 return regularMatch(regexp, str);
1429 //RETAILMSG(1, (L"No Match!\r\n"));
1434 void yfsd_DeleteFinder(PSEARCH pSearch)
1436 if(pSearch->foundObjects) //If we found some objects we must clean up the cached linked list.
1438 yaffs_FoundObject *it;
1439 yaffs_FoundObject *temp;
1441 it = pSearch->foundObjects;
1451 pSearch->foundObjects = NULL;
1454 pSearch->dir->inUse--;
1458 BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)
1460 //Iterate through the current list of objs already found and return true if already exists.
1461 //If the object hasn't already been found then add it to the list (SIDE-EFFECT alert) and return false.
1464 yaffs_FoundObject *it;
1465 it = pSearch->foundObjects;
1468 while(it->next != NULL) //iterate through singly linked list.
1480 //Add the item to the list.
1481 //'it' will currently be pointing to the last of the list nodes. i.e node->next == NULL
1482 it->next = malloc(sizeof(yaffs_FoundObject));
1483 it->next->next = NULL;
1494 BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
1497 struct list_head *i;
1502 char name[YAFFS_MAX_NAME_LENGTH+1];
1504 if(!pSearch->foundObjects)
1506 pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
1507 pSearch->foundObjects->next = NULL;
1508 pSearch->foundObjects->obj = 0;
1515 list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
1518 l = list_entry(i, yaffs_Object,siblings);
1520 yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
1522 if(regularMatch(pSearch->pattern,name))
1524 if(!yfsd_ObjectAlreadyFound(pSearch, l))//pos == pSearch->currentPos)
1529 //pSearch->currentPos++;
1531 // fill out find data
1533 pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
1535 yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
1536 yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
1537 yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
1539 pfd->nFileSizeHigh = 0;
1540 pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
1541 pfd->dwOID = 0; // wtf is this???
1543 MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
1545 RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
1546 pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
1547 l->variant.fileVariant.scannedFileSize));
1563 SetLastError(ERROR_NO_MORE_FILES);
1571 BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
1574 struct list_head *i;
1578 char name[YAFFS_MAX_NAME_LENGTH+1];
1580 if(!pSearch->foundObjects)
1582 pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
1583 pSearch->foundObjects->next = NULL;
1584 pSearch->foundObjects->obj = 0;
1590 list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
1593 l = list_entry(i, yaffs_Object,siblings);
1594 if(!yfsd_ObjectAlreadyFound(pSearch,l))
1596 // Only look at things we have not looked at already
1597 yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
1599 if(regularMatch(pSearch->pattern,name))
1602 // fill out find data
1604 pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
1606 yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
1607 yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
1608 yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
1610 pfd->nFileSizeHigh = 0;
1611 pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
1612 pfd->dwOID = 0; // wtf is this???
1614 MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
1616 RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
1617 pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
1618 l->variant.fileVariant.scannedFileSize));
1633 SetLastError(ERROR_NO_MORE_FILES);
1640 HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWIN32_FIND_DATAW pfd )
1643 // Create a search context, register it, and do the first search
1646 HANDLE h = INVALID_HANDLE_VALUE;
1649 RETAILMSG (MSGSTATE, (L"YAFFS::FindFirst\r\n"));
1651 pSearch = malloc(sizeof(yfsd_WinFind));
1654 SetLastError(ERROR_OUTOFMEMORY);
1661 pSearch->foundObjects = NULL; //pSearch->currentPos = 0;
1662 pSearch->dir = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileSpec,pSearch->pattern,YFSD_NAME_LENGTH);
1665 pSearch->dir->inUse++;
1680 found = yfsd_DoFindFile(pSearch,pfd);
1685 h = FSDMGR_CreateSearchHandle(pVolume->mgrVolume,hProc,pSearch);
1688 if(h == INVALID_HANDLE_VALUE && pSearch)
1690 yfsd_DeleteFinder(pSearch);
1691 SetLastError(ERROR_NO_MORE_SEARCH_HANDLES);
1699 BOOL YFSD_FindNextFileW(PSEARCH pSearch, PWIN32_FIND_DATAW pfd )
1701 RETAILMSG (MSGSTATE, (L"YAFFS::FindNext\r\n"));
1706 return yfsd_DoFindFile(pSearch,pfd);
1709 BOOL YFSD_FindClose( PSEARCH pSearch )
1711 RETAILMSG (MSGSTATE, (L"YAFFS::FindClose\r\n"));
1716 yfsd_DeleteFinder(pSearch);
1721 HANDLE YFSD_CreateFileW(
1727 PSECURITY_ATTRIBUTES pSecurityAttributes, // ignore
1729 DWORD dwFlagsAndAttributes,
1730 HANDLE hTemplateFile ) // ignore
1734 yaffs_Object *parent = NULL;
1735 yaffs_Object *obj = NULL;
1736 char name[YFSD_NAME_LENGTH+1];
1738 yfsd_WinFile *f = NULL;
1739 HANDLE handle = INVALID_HANDLE_VALUE;
1740 unsigned modifiedTime[2];
1743 BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;
\r
1744 BOOL readPermitted = (dwAccess & GENERIC_READ) ? TRUE : FALSE;
\r
1745 BOOL shareRead = (dwShareMode & FILE_SHARE_READ) ? TRUE : FALSE;
\r
1746 BOOL shareWrite = (dwShareMode & FILE_SHARE_WRITE) ? TRUE : FALSE;
\r
1748 BOOL openRead, openWrite, openReadAllowed, openWriteAllowed;
\r
1750 BOOL fileCreated = FALSE;
1753 mode = dwFlagsAndAttributes & 0x00FFFFFF; // ding off the flags
1756 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile (%s) flags %X mode %X\r\n", pwsFileName,dwFlagsAndAttributes,mode));
1759 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write permitted\r\n"));
1763 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write not permitted\r\n"));
1766 if(!yfsd_CheckValidAttributes(mode))
1768 SetLastError(ERROR_INVALID_PARAMETER);
1775 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);
1778 if(parent && yfsd_NameIsValid(name))
1781 if(dwCreate == CREATE_NEW)
1783 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));
1786 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1789 obj = yaffs_MknodFile(parent,name,mode,0,0);
1791 SetLastError(ERROR_DISK_FULL);
1797 SetLastError(ERROR_ALREADY_EXISTS);
1801 else if( dwCreate == OPEN_ALWAYS)
1803 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1806 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in OPEN_ALWAYS\r\n"));
1807 obj = yaffs_MknodFile(parent,name,mode,0,0);
1809 SetLastError(ERROR_DISK_FULL);
1815 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening existing file in OPEN_ALWAYS\r\n"));
1818 else if(dwCreate == OPEN_EXISTING)
1820 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in OPEN_EXISTING\r\n"));
1821 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1823 SetLastError(ERROR_FILE_NOT_FOUND);
1826 if (yfsd_GetObjectWinAttributes(obj) & FILE_ATTRIBUTE_DIRECTORY)
1828 SetLastError(ERROR_ACCESS_DENIED);
1833 else if(dwCreate == TRUNCATE_EXISTING)
1835 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in TRUNCATE_EXISTING\r\n"));
1836 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1839 yaffs_ResizeFile(obj,0);
1843 SetLastError(ERROR_FILE_NOT_FOUND);
1846 else if(dwCreate == CREATE_ALWAYS)
1848 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
1852 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file parent %X, name %a in CREATE_ALWAYS\r\n",parent,name));
1853 obj = yaffs_MknodFile(parent,name,mode,0,0);
1855 SetLastError(ERROR_DISK_FULL);
1860 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile in CREATE_ALWAYS (already exists)\r\n"));
1861 obj->st_mode = mode;
1863 yaffs_ResizeFile(obj,0);
1864 yaffs_FlushFile(obj,1);
1869 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile called with unknown flags %x\r\n", dwCreate));
1870 SetLastError(ERROR_INVALID_PARAMETER);
1875 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));
1876 SetLastError(ERROR_PATH_NOT_FOUND);
1883 openRead = openWrite =0;
\r
1884 openReadAllowed = openWriteAllowed = 1;
\r
1886 for(i = 0; i < MAX_WIN_FILE; i++)
\r
1888 p = &yfsd_winFile[i];
\r
1892 if (p->readPermitted) openRead = 1;
\r
1893 if (p->writePermitted) openWrite = 1;
\r
1894 if (!p->shareRead) openReadAllowed = 0;
\r
1895 if (!p->shareWrite) openWriteAllowed = 0;
\r
1900 // Now we test if the share works out.
\r
1902 if((openRead && !shareRead) || // already open for read, but we are not prepared to share it for read
\r
1903 (openWrite && !shareWrite) || // already open for write, but we are not prepared to share it for write
\r
1904 (!openReadAllowed && readPermitted) || // already open with read sharing not permitted
\r
1905 (!openWriteAllowed && writePermitted)) // same... write
\r
1907 SetLastError(ERROR_ACCESS_DENIED);
\r
1915 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));
1916 f = yfsd_GetWinFile();
1920 RETAILMSG (MSGSTATE, (L"YAFFS::Creatfile - no object\r\n"));
1926 handle = FSDMGR_CreateFileHandle(pVolume->mgrVolume,hProc,f);
1928 if(handle != INVALID_HANDLE_VALUE)
1930 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));
1933 f->writePermitted = writePermitted;
\r
1934 f->readPermitted = writePermitted;
\r
1935 f->shareRead= shareRead;
\r
1936 f->shareWrite = shareWrite;
\r
1937 f->myVolume = pVolume;
1940 modifiedTime[0] = obj->win_mtime[0];
1941 modifiedTime[1] = obj->win_mtime[1];
1942 objSize = yaffs_GetObjectFileLength(obj);
1943 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - file size %d\r\n",objSize));
1948 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have no fsdmgr handle\r\n"));
1955 if(handle != INVALID_HANDLE_VALUE &&
1957 pVolume->shellFunction)
1960 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1962 fc.cbSize = sizeof(FILECHANGEINFO);
1963 fc.wEventId = SHCNE_CREATE;
1964 fc.uFlags = SHCNF_PATH;
1965 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1967 fc.dwAttributes = mode;
1968 yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
1969 fc.nFileSize = objSize;
1971 pVolume->shellFunction(&fc);
1972 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
1974 yfsd_ShellDirectoryChanged(pVolume,fpn);
1977 if(handle != INVALID_HANDLE_VALUE && (fileCreated || writePermitted))
1979 // Remember the name
1981 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
1984 yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
1986 f->fullName = malloc((slen+1)* sizeof(WCHAR));
1989 wcscpy(f->fullName,fpn);
1999 BOOL yfsd_DoReadFile(
2008 yaffs_Object *obj = NULL;
2017 RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile pcbRead was NULL. naughty.\r\n"));
2020 RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile %d bytes\r\n",cbRead));
2022 if(!pFile || !pFile->obj)
2024 SetLastError(ERROR_INVALID_HANDLE);
2030 if(yaffs_GetObjectFileLength(obj) > pFile->offset)
2032 maxRead = yaffs_GetObjectFileLength(obj) - pFile->offset;
2039 if(cbRead > maxRead)
2046 nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);
2049 pFile->offset += nread;
2066 return nread < 0? FALSE : TRUE;
2075 OVERLAPPED *pOverlapped ) //ignore
2079 RETAILMSG (MSGSTATE, (L"YAFFS::ReadFile\r\n"));
2081 if(!pFile || !pFile->obj)
2083 SetLastError(ERROR_INVALID_HANDLE);
2089 result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
2096 BOOL YFSD_ReadFileWithSeek(
2101 OVERLAPPED *pOverlapped,
2103 DWORD dwHighOffset )
2106 DWORD rememberedOffset;
2108 RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));
2110 // To determine if paging is supported, the kernel calls this with all parameters except pFile
2112 if(!pBuffer && !cbRead && !pcbRead && !pOverlapped && !dwLowOffset && !dwHighOffset)
2114 return TRUE; // paging suppported
2115 //return FALSE; // paging not supported
2118 if(!pFile || !pFile->obj)
2120 SetLastError(ERROR_INVALID_HANDLE);
2126 rememberedOffset = pFile->offset;
2128 pFile->offset = dwLowOffset;
2129 // ignore high offset for now
2131 result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
2133 //pFile->offset = rememberedOffset;
2143 BOOL yfsd_DoWriteFile(
2150 yaffs_Object *obj = NULL;
2152 RETAILMSG (MSGSTATE, (L"YAFFS::DoWriteFile size %d\r\n",cbWrite));
2154 if(!pFile || !pFile->obj)
2156 SetLastError(ERROR_INVALID_HANDLE);
2160 if(!pFile->writePermitted)
2163 SetLastError(ERROR_ACCESS_DENIED);
2172 nwritten = yaffs_WriteDataToFile(obj,pBuffer,pFile->offset,cbWrite);
2175 pFile->offset += nwritten;
2176 *pcbWritten = nwritten;
2178 if(nwritten != cbWrite)
2180 SetLastError(ERROR_DISK_FULL);
2184 return nwritten != cbWrite? FALSE : TRUE;
2188 BOOL YFSD_WriteFile(
2193 OVERLAPPED *pOverlapped )
2198 RETAILMSG (MSGSTATE, (L"YAFFS::WriteFile\r\n"));
2200 result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
2207 BOOL YFSD_WriteFileWithSeek(
2212 OVERLAPPED *pOverlapped,
2214 DWORD dwHighOffset )
2217 DWORD rememberedOffset;
2218 RETAILMSG (MSGSTATE, (L"YAFFS::WriteFileWithSeek %d bytes at %d,%d pcbWritten %X\r\n",cbWrite,dwHighOffset,dwLowOffset,pcbWritten));
2222 if(!pFile || !pFile->obj)
2224 SetLastError(ERROR_INVALID_HANDLE);
2230 rememberedOffset = pFile->offset;
2232 pFile->offset = dwLowOffset;
2233 // ignore high offset for now
2235 result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
2237 //pFile->offset = rememberedOffset;
2244 DWORD YFSD_SetFilePointer(
2246 LONG lDistanceToMove,
2247 PLONG pDistanceToMoveHigh,
2248 DWORD dwMoveMethod )
2250 // ignore high offset for now
2252 DWORD offset = 0xFFFFFFFF;
2255 int seekNegative = 0;
2258 if(!pFile || !pFile->obj)
2260 SetLastError(ERROR_INVALID_HANDLE);
2267 oldPos = pFile->offset;
2269 if(dwMoveMethod == FILE_BEGIN)
2271 if(lDistanceToMove >= 0)
2273 offset = pFile->offset = lDistanceToMove;
2280 else if(dwMoveMethod == FILE_END)
2282 fileSize = yaffs_GetObjectFileLength(pFile->obj);
2284 (fileSize + lDistanceToMove) >= 0)
2286 offset = pFile->offset = fileSize + lDistanceToMove;
2293 else if(dwMoveMethod == FILE_CURRENT)
2295 if(pFile->offset + lDistanceToMove >= 0)
2297 offset = pFile->offset = pFile->offset + lDistanceToMove;
2307 SetLastError(ERROR_NEGATIVE_SEEK);
2313 RETAILMSG (MSGSTATE, (L"YAFFS::SetFilePtr method %d distance %d high %X oldpos %d newpos %d\r\n",
2314 dwMoveMethod,lDistanceToMove,pDistanceToMoveHigh,oldPos,offset));
2320 DWORD YFSD_GetFileSize(
2322 PDWORD pFileSizeHigh )
2326 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileSize high %X\r\n",pFileSizeHigh));
2329 if(!pFile || !pFile->obj)
2331 SetLastError(ERROR_INVALID_HANDLE);
2337 fileSize = yaffs_GetObjectFileLength(pFile->obj);
2348 BOOL YFSD_GetFileInformationByHandle(
2350 PBY_HANDLE_FILE_INFORMATION pFileInfo )
2352 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileInfoByHandle\r\n"));
2354 if(!pFile || !pFile->obj || !pFileInfo)
2356 SetLastError(ERROR_INVALID_HANDLE);
2362 pFileInfo->dwFileAttributes = yfsd_GetObjectWinAttributes(pFile->obj);
2363 yfsd_U32sToWinFileTime(pFile->obj->win_ctime,&pFileInfo->ftCreationTime);
2364 yfsd_U32sToWinFileTime(pFile->obj->win_atime,&pFileInfo->ftLastAccessTime);
2365 yfsd_U32sToWinFileTime(pFile->obj->win_mtime,&pFileInfo->ftLastWriteTime);
2366 pFileInfo->dwVolumeSerialNumber = 0; //todo is this OK?
2367 pFileInfo->nFileSizeHigh = 0;
2368 pFileInfo->nFileSizeLow = yaffs_GetObjectFileLength(pFile->obj);
2369 pFileInfo->nNumberOfLinks = 1; // only primary link supported like FAT
2370 pFileInfo->nFileIndexHigh = 0;
2371 pFileInfo->nFileIndexLow = pFile->obj->objectId;
\r
2372 //slf021104a Begin Window CE 4.0 added an additional field.
\r
2373 #if _WINCEOSVER >= 400
2374 pFileInfo->dwOID = (CEOID)(INVALID_HANDLE_VALUE);
\r
2383 BOOL YFSD_FlushFileBuffers(PFILE pFile )
2385 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2387 yfsd_Volume *vol = NULL;
2393 RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));
2395 if(!pFile || !pFile->obj)
2397 SetLastError(ERROR_INVALID_HANDLE);
2403 yaffs_FlushFile(pFile->obj,1);
2404 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2405 objSize = yaffs_GetObjectFileLength(pFile->obj);
2406 mtime[0] = pFile->obj->win_mtime[0];
2407 mtime[1] = pFile->obj->win_mtime[1];
2410 wcscpy(fpn,pFile->fullName);
2413 vol = pFile->myVolume;
2417 if(vol && vol->shellFunction && nameExists)
2421 fc.cbSize = sizeof(FILECHANGEINFO);
2422 fc.wEventId = SHCNE_UPDATEITEM;
2423 fc.uFlags = SHCNF_PATH;
2424 fc.dwItem1 = (DWORD)fpn;
2426 fc.dwAttributes = attribs;
2427 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2428 fc.nFileSize = objSize;
2430 vol->shellFunction(&fc);
2431 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2432 //yfsd_ShellDirectoryChanged(vol,fpn);
2439 BOOL YFSD_GetFileTime(
2441 FILETIME *pCreation,
2442 FILETIME *pLastAccess,
2443 FILETIME *pLastWrite )
2446 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileTime\r\n"));
2447 if(!pFile || !pFile->obj)
2449 SetLastError(ERROR_INVALID_HANDLE);
2455 if(pCreation) yfsd_U32sToWinFileTime(pFile->obj->win_ctime,pCreation);
2456 if(pLastAccess) yfsd_U32sToWinFileTime(pFile->obj->win_atime,pLastAccess);
2457 if(pLastWrite) yfsd_U32sToWinFileTime(pFile->obj->win_mtime,pLastWrite);
2464 BOOL YFSD_SetFileTime(
2466 CONST FILETIME *pCreation,
2467 CONST FILETIME *pLastAccess,
2468 CONST FILETIME *pLastWrite )
2470 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2473 yfsd_Volume *vol = NULL;
2479 RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));
2481 if(!pFile || !pFile->obj)
2483 SetLastError(ERROR_INVALID_HANDLE);
2492 yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);
2493 pFile->obj->dirty = 1;
2497 yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);
2498 pFile->obj->dirty = 1;
2502 yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);
2503 pFile->obj->dirty = 1;
2505 if(pCreation || pLastAccess || pLastWrite)
2507 result = yaffs_FlushFile(pFile->obj,0);
2512 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2513 objSize = yaffs_GetObjectFileLength(pFile->obj);
2514 mtime[0] = pFile->obj->win_mtime[0];
2515 mtime[1] = pFile->obj->win_mtime[1];
2518 wcscpy(fpn,pFile->fullName);
2521 vol = pFile->myVolume;
2526 // Call shell function
2527 if(nameExists && result && vol && vol->shellFunction)
2531 fc.cbSize = sizeof(FILECHANGEINFO);
2532 fc.wEventId = SHCNE_UPDATEITEM;
2533 fc.uFlags = SHCNF_PATH;
2534 fc.dwItem1 = (DWORD)fpn;
2536 fc.dwAttributes = attribs;
2537 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2538 fc.nFileSize = objSize;
2540 vol->shellFunction(&fc);
2541 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2542 //yfsd_ShellDirectoryChanged(vol,fpn);
2548 BOOL YFSD_SetEndOfFile(
2552 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2554 yfsd_Volume *vol = NULL;
2558 static unsigned char zeros[512];
2561 BOOL retVal = FALSE;
2563 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF\r\n"));
2565 if(!pFile || !pFile->obj)
2567 SetLastError(ERROR_INVALID_HANDLE);
2572 result = yaffs_ResizeFile(pFile->obj,pFile->offset);
2574 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF resizing to %d, result %d\r\n",pFile->offset,result));
2576 // Resize only works if we're shortening the file.
2577 // If the result is shorter than the offset, then we need to write zeros....
2579 if(result != pFile->offset)
2581 if(result < pFile->offset)
2584 int nBytes = pFile->offset - result;
2589 memset(zeros,0,512);
2591 pFile->offset = result;
2592 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF expanding file by %d bytes\r\n",nBytes));
2593 while(nBytes > 0 && ok)
2595 thisWriteSize = (nBytes > 512) ? 512 : nBytes;
2597 ok = yfsd_DoWriteFile(pFile,zeros,thisWriteSize,&written);
2598 if(written != thisWriteSize)
2603 nBytes -= thisWriteSize;
2611 SetLastError(ERROR_ACCESS_DENIED);
2621 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2622 objSize = yaffs_GetObjectFileLength(pFile->obj);
2623 mtime[0] = pFile->obj->win_mtime[0];
2624 mtime[1] = pFile->obj->win_mtime[1];
2627 wcscpy(fpn,pFile->fullName);
2630 vol = pFile->myVolume;
2636 if(nameExists && retVal && vol && vol->shellFunction)
2640 fc.cbSize = sizeof(FILECHANGEINFO);
2641 fc.wEventId = SHCNE_UPDATEITEM;
2642 fc.uFlags = SHCNF_PATH;
2643 fc.dwItem1 = (DWORD)fpn;
2645 fc.dwAttributes = attribs;
2646 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2647 fc.nFileSize = objSize;
2649 vol->shellFunction(&fc);
2650 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2651 //yfsd_ShellDirectoryChanged(vol,fpn);
2654 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF file size %d\r\n",yaffs_GetObjectFileLength(pFile->obj)));
2661 BOOL YFSD_DeviceIoControl(
2663 DWORD dwIoControlCode,
2668 PDWORD pBytesReturned,
2669 OVERLAPPED *pOverlapped )
2671 RETAILMSG (MSGSTATE, (L"YAFFS::DeviceIoControl\r\n"));
2676 BOOL YFSD_CloseFile( PFILE pFile )
2678 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
2680 yfsd_Volume *vol = NULL;
2685 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));
2691 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null pFile\r\n"));
2697 pFile->obj->inUse--;
2698 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));
2699 yaffs_FlushFile(pFile->obj,1);
2700 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
2701 objSize = yaffs_GetObjectFileLength(pFile->obj);
2702 mtime[0] = pFile->obj->win_mtime[0];
2703 mtime[1] = pFile->obj->win_mtime[1];
2704 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));
2707 wcscpy(fpn,pFile->fullName);
2710 vol = pFile->myVolume;
2711 yfsd_PutWinFile(pFile);
2715 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null obj\r\n"));
2722 if(nameExists && vol && vol->shellFunction)
2726 fc.cbSize = sizeof(FILECHANGEINFO);
2727 fc.wEventId = SHCNE_UPDATEITEM;
2728 fc.uFlags = SHCNF_PATH;
2729 fc.dwItem1 = (DWORD)fpn;
2731 fc.dwAttributes = attribs;
2732 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
2733 fc.nFileSize = objSize;
2735 vol->shellFunction(&fc);
2736 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
2737 //yfsd_ShellDirectoryChanged(vol,fpn);
2742 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile done\r\n"));
2749 BOOL YFSD_CloseVolume(PVOLUME pVolume )
2751 RETAILMSG (MSGSTATE, (L"YAFFS::CloseVolume\r\n"));
2752 yfsd_FlushAllFiles();