2 * YAFFS: Yet another FFS. A NAND-flash specific file system.
\r
3 * yaffsfsd.c: FSD interface funtions for WinCE.
\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 and Lynn Winter
\r
23 * $Id: yaffsfsd.c,v 1.3 2003-01-31 00:52:53 charles Exp $
\r
25 #include <windows.h>
\r
26 #include <extfile.h>
\r
27 #include <yaffs_guts.h>
\r
28 #include <ynandif.h>
\r
33 #define MAX_WIN_FILE 200
\r
34 #define YFSD_NAME_LENGTH 128
\r
35 #define YFSD_FULL_PATH_NAME_SIZE 500
\r
38 #define YFSD_DISK_NAME L"Disk"
\r
39 #define YFSD_BOOT_NAME L"Boot"
\r
41 #define PARTITION_START_NUMBER (1280)
\r
44 // if this is defined the there will be a constant message box raised to display status
\r
45 //#define MSGBOX_DISPLAY
\r
48 //#define MSGSTATE 1
\r
50 //#define DISABLE_BOOT_PARTITION
\r
52 // Define DO_PARTITION_TABLE to cause the partition table
\r
53 // information to be retrieved from the block driver.
\r
54 // Can define this in your sources file.
\r
55 //#define DO_PARTITION_TABLE
\r
56 // How many partitions the disk might have. 2 gives
\r
57 // space for the "Disk" and "Boot" partitions.
\r
58 #define MAXPARTITIONS (2)
\r
61 //unsigned yaffs_traceMask=0xffffffff;
\r
62 unsigned yaffs_traceMask=0;
\r
69 DWORD mgrVolume; // The volume id from the manager issed when we registered it - it is an HVOL
\r
72 // DWORD guard0[100];
\r
73 // DWORD guard1[100];
\r
74 SHELLFILECHANGEFUNC_t shellFunction;
\r
85 yfsd_Volume *myVolume;
\r
86 BOOL writePermitted;
\r
93 struct yfsd_FoundObjectStruct
\r
96 struct yfsd_FoundObjectStruct *next;
\r
99 typedef struct yfsd_FoundObjectStruct yaffs_FoundObject;
\r
104 char pattern[YFSD_NAME_LENGTH+1];
\r
105 yaffs_FoundObject *foundObjects;
\r
110 #define PSEARCH yfsd_WinFind*
\r
112 #define PVOLUME yfsd_Volume*
\r
113 #define PFILE yfsd_WinFile*
\r
115 #define FSD_API YFSD
\r
117 #include <fsdmgr.h>
\r
120 //static yfsd_Volume disk_volume;
\r
121 //static yfsd_Volume boot_volume;
\r
122 static yfsd_Volume * disk_volumes[MAXPARTITIONS];
\r
125 static CRITICAL_SECTION yaffsLock;
\r
126 static CRITICAL_SECTION winFileLock;
\r
128 static int yaffsLockInited = 0;
\r
130 static yfsd_WinFile yfsd_winFile[MAX_WIN_FILE];
\r
133 static yfsd_SetGuards(void)
\r
136 for(i = 0; i < 100; i++)
\r
138 yfsd_volume.guard0[i] = yfsd_volume.guard1[i] = i;
\r
142 static void yfsd_CheckGuards(void)
\r
146 for(i = found = 0; i < 100 && !found; i++)
\r
148 if(yfsd_volume.guard0[i] != i)
\r
150 RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
\r
153 if(yfsd_volume.guard1[i] != i)
\r
155 RETAILMSG (MSGSTATE, (L"YAFFS:: guard 0 %d brocken\r\n",i));
\r
163 #ifdef MSGBOX_DISPLAY
\r
164 DWORD WINAPI yfsd_MessageThread(LPVOID param)
\r
166 yaffs_Device *dev = (yaffs_Device *)param;
\r
167 TCHAR dataBuffer[1000];
\r
170 // note : if the device gets free'd from under us, we will cause an exception in the loop
\r
173 wsprintf(dataBuffer, L"nShortOpCaches %i\r\n"
\r
174 L"nErasedBlocks %i\r\n"
\r
175 L"allocationBlock %i\r\n"
\r
176 L"allocationPage %i\r\n"
\r
177 L"garbageCollectionRequired %i\r\n"
\r
178 L"nRetiredBlocks %i\r\n"
\r
179 L"cacheHits %i\r\n"
\r
181 L"eccUnfixed %i\r\n"
\r
182 L"tagsEccFixed %i\r\n"
\r
183 L"tagsEccUnfixed %i\r\n",
\r
184 dev->nShortOpCaches,
\r
185 dev->nErasedBlocks,
\r
186 dev->allocationBlock,
\r
187 dev->allocationPage,
\r
188 dev->garbageCollectionRequired,
\r
189 dev->nRetiredBlocks,
\r
194 dev->tagsEccUnfixed);
\r
198 L"YAFFS PROC INFO",
\r
205 void yfsd_LockWinFiles(void)
\r
207 //RETAILMSG (MSGSTATE, (L"YAFFS::LockWinfiles\r\n"));
\r
208 EnterCriticalSection(&winFileLock);
\r
210 void yfsd_UnlockWinFiles(void)
\r
212 //RETAILMSG (MSGSTATE, (L"YAFFS::UnlockWinFiles\r\n"));
\r
213 LeaveCriticalSection(&winFileLock);
\r
218 void yfsd_LockYAFFS(void)
\r
220 //yfsd_CheckGuards();
\r
221 //RETAILMSG (MSGSTATE, (L"YAFFS::LockYAFFS %d ",lockwaits));
\r
223 EnterCriticalSection(&yaffsLock);
\r
224 //RETAILMSG (MSGSTATE, (L" locked\r\n"));
\r
226 void yfsd_UnlockYAFFS(void)
\r
228 //yfsd_CheckGuards();
\r
229 //RETAILMSG (MSGSTATE, (L"YAFFS::UnLockYAFFS "));
\r
230 LeaveCriticalSection(&yaffsLock);
\r
232 //RETAILMSG (MSGSTATE, (L" unlocked\r\n"));
\r
236 void yfsd_InitialiseWinFiles(void)
\r
240 RETAILMSG (MSGSTATE, (L"YAFFS::InitWinFiles\r\n"));
\r
242 InitializeCriticalSection(&winFileLock);
\r
244 yfsd_LockWinFiles();
\r
245 for(i = 0; i < MAX_WIN_FILE; i++)
\r
247 yfsd_winFile[i].isopen = 0;
\r
249 yfsd_UnlockWinFiles();
\r
252 yfsd_WinFile * yfsd_GetWinFile(void)
\r
255 RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles\r\n"));
\r
257 yfsd_LockWinFiles();
\r
259 for(i = 0; i < MAX_WIN_FILE; i++)
\r
261 if(!yfsd_winFile[i].isopen)
\r
263 yfsd_winFile[i].isopen = 1;
\r
264 yfsd_winFile[i].writePermitted = 0;
\r
265 yfsd_winFile[i].readPermitted = 0;
\r
266 yfsd_winFile[i].shareRead = 0;
\r
267 yfsd_winFile[i].shareWrite = 0;
\r
268 yfsd_winFile[i].dirty = 0;
\r
269 yfsd_winFile[i].fullName = NULL;
\r
270 yfsd_winFile[i].obj = NULL;
\r
272 yfsd_UnlockWinFiles();
\r
273 return &yfsd_winFile[i];
\r
277 yfsd_UnlockWinFiles();
\r
279 RETAILMSG (MSGSTATE, (L"YAFFS::GetWinFiles did not find a handle. Too many open.\r\n"));
\r
284 void yfsd_PutWinFile(yfsd_WinFile *f)
\r
286 RETAILMSG (MSGSTATE, (L"YAFFS::PutWinFile\r\n"));
\r
287 yfsd_LockWinFiles();
\r
293 f->fullName = NULL;
\r
296 yfsd_UnlockWinFiles();
\r
301 void yfsd_FlushAllFiles(void)
\r
304 RETAILMSG (MSGSTATE, (L"YAFFS::FlushAllFiles\r\n"));
\r
307 yfsd_LockWinFiles();
\r
308 for(i = 0; i < MAX_WIN_FILE; i++)
\r
310 if(yfsd_winFile[i].isopen &&
\r
311 yfsd_winFile[i].obj)
\r
313 yaffs_FlushFile(yfsd_winFile[i].obj,1);
\r
316 yfsd_UnlockWinFiles();
\r
317 yfsd_UnlockYAFFS();
\r
321 //////////////////////////////////////////////////////////////////////
\r
322 // Search through winFiles to see if any are open.
\r
324 BOOL yfsd_FilesOpen(void)
\r
328 RETAILMSG (MSGSTATE, (L"YAFFS::FilesOpen?\r\n"));
\r
330 yfsd_LockWinFiles();
\r
331 for(i = 0, rval = FALSE; i < MAX_WIN_FILE; i++)
\r
333 if(yfsd_winFile[i].isopen)
\r
339 yfsd_UnlockWinFiles();
\r
344 PWSTR yfsd_FullPathName(PVOLUME vol, PWSTR fpn,int slength,PCWSTR pathName)
\r
347 // todo check for bounds
\r
349 //volName already has the initial backslash if it needs it.
\r
350 //wcscpy(fpn,L"\\");
\r
351 //wcscat(fpn,vol->volName);
\r
352 wcscpy(fpn,vol->volName);
\r
354 if(pathName[0] != '\\')
\r
358 wcscat(fpn,pathName);
\r
365 // FILETIME is a 64-bit value as 100-nanosecond intervals since January 1, 1601.
\r
367 void yfsd_U32sToWinFileTime(__u32 target[2], FILETIME *wft)
\r
370 wft->dwLowDateTime = target[0];
\r
371 wft->dwHighDateTime = target[1];
\r
375 void yfsd_NullWinFileTime(FILETIME *wft)
\r
377 wft->dwLowDateTime = 0;
\r
378 wft->dwHighDateTime = 0;
\r
381 void yfsd_WinFileTimeToU32s(const FILETIME *wft, __u32 target[2])
\r
383 target[0] = wft->dwLowDateTime;
\r
384 target[1] = wft->dwHighDateTime;
\r
387 void yfsd_WinFileTimeNow(__u32 target[2])
\r
392 GetSystemTime(&st);
\r
393 SystemTimeToFileTime(&st,&ft);
\r
394 yfsd_WinFileTimeToU32s(&ft,target);
\r
397 // Cut down the name to the parent directory, then inform the shell of
\r
398 // a change to the directory.
\r
399 void yfsd_ShellDirectoryChanged(PVOLUME pVolume, PWSTR fullPathName)
\r
403 wcscpy(str,fullPathName);
\r
405 i = wcslen(str) - 1;
\r
413 // Curveball if the name is a directory (ie. we're doing an update of
\r
414 // a directory because we added a directory item). , then it might end in a \
\r
415 // which we must toss first
\r
416 if(i >= 0 && (str[i] == '\\' || str[i] == '/'))
\r
422 // Ok, now strip back...
\r
424 while(i >= 0 && str[i] != '\\' && str[i] != '/')
\r
430 if(pVolume->shellFunction)
\r
434 fc.cbSize = sizeof(FILECHANGEINFO);
\r
435 fc.wEventId = SHCNE_UPDATEDIR;
\r
436 fc.uFlags = SHCNF_PATH;
\r
437 fc.dwItem1 = (DWORD)str;
\r
439 fc.dwAttributes = 0;
\r
440 yfsd_NullWinFileTime(&fc.ftModified);
\r
443 pVolume->shellFunction(&fc);
\r
444 RETAILMSG (MSGSTATE, (L"YAFFS:: directory changed %s\r\n",str));
\r
452 // Minimal name test for now
\r
453 BOOL yfsd_NameIsValid (const char *name)
\r
455 int length = strlen(name);
\r
457 return (length > 0 && length <= YFSD_NAME_LENGTH);
\r
461 // File attributes:
\r
462 // Wince understands the following attributes of any use to YAFFS:
\r
470 // Also, FILE_ATTRIBUTE_DIRECTORY is used to mark directories.
\r
472 // It also understands NORMAL. If no other flag is set, then set NORMAL.
\r
473 // If any of the above are set, then NORMAL must **not** be set.
\r
474 // Ignore this and the WinCE Explorer barfs the file.
\r
477 // in addition, GetAttributes also returns FILE_ATTRIBUTE_DIRECTORY
\r
479 // The following are valid ones we get presented with,
\r
480 // but must filter out the stuff we don't unserstand
\r
481 //#define FILE_ATTRIBUTE_READONLY 0x00000001
\r
482 //#define FILE_ATTRIBUTE_HIDDEN 0x00000002
\r
483 //#define FILE_ATTRIBUTE_SYSTEM 0x00000004
\r
484 //#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
\r
485 //#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
\r
486 //#define FILE_ATTRIBUTE_INROM 0x00000040
\r
487 //#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
\r
488 //#define FILE_ATTRIBUTE_NORMAL 0x00000080
\r
489 //#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
\r
490 //#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
\r
491 //#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
\r
492 //#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
\r
493 //#define FILE_ATTRIBUTE_OFFLINE 0x00001000
\r
494 //#define FILE_ATTRIBUTE_ROMSTATICREF 0x00001000
\r
495 //#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
\r
496 //#define FILE_ATTRIBUTE_ROMMODULE 0x00002000
\r
499 BOOL yfsd_CheckValidAttributes(DWORD attribs)
\r
502 RETAILMSG (MSGSTATE, (L"Attributes:%X\r\n", attribs));
\r
505 // If NORMAL, then nothing else
\r
506 if(attribs & FILE_ATTRIBUTE_NORMAL && attribs != FILE_ATTRIBUTE_NORMAL)
\r
508 if(attribs == FILE_ATTRIBUTE_NORMAL)
\r
511 // Check that the bits are in the valid set
\r
512 if(attribs & ~(0x3FE7))
\r
518 DWORD yfsd_GetObjectWinAttributes(yaffs_Object *obj)
\r
523 result = obj->st_mode &
\r
524 (FILE_ATTRIBUTE_READONLY |
\r
525 FILE_ATTRIBUTE_ARCHIVE |
\r
526 FILE_ATTRIBUTE_HIDDEN |
\r
527 FILE_ATTRIBUTE_SYSTEM);
\r
529 if(obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) result |= FILE_ATTRIBUTE_DIRECTORY;
\r
531 if(result & ~FILE_ATTRIBUTE_NORMAL)
\r
533 result &= ~FILE_ATTRIBUTE_NORMAL;
\r
537 result = FILE_ATTRIBUTE_NORMAL;
\r
547 * Runs over input until a '\' is found, or '\0' is found, or outSize - 1 is
\r
548 * reached. Characters are copied from input into output until the above stop
\r
549 * condition is reached - output is then given a '\0'. output must be at least
\r
550 * as large as outSize
\r
552 static int parseToNextSlash(const unsigned short *input, char *output, int outSize)
\r
556 /* strip any starting \'s */
\r
557 //RETAILMSG(1, (L"\r\nParsing.. "));
\r
558 while (*input == '\\' || *input == '/') input++, counter++;
\r
560 for (; counter < outSize - 1; counter++)
\r
562 if (*input == '\0' ||
\r
563 ((*input == '\\' || *input == '/') && input[1] == '\0')) // special case: if the string ends in a '\', then toss the '\'
\r
565 counter = -1; // break & tell people we've run to the end
\r
568 if (*input == '\\' || *input == '/')
\r
570 //RETAILMSG(1, (L"%c", *input));
\r
571 *output = (char) (*input);
\r
577 // RETAILMSG(1, (L"\r\nOut %a\r\n", t));
\r
583 * Since the notion of paths as WinCE sees them and as YAFFS sees them
\r
584 * is different, we needed a helper function to search from the root of
\r
585 * device along the string in path. The processed pointer is set to where
\r
586 * abouts in the string the function was able to search up to.
\r
588 yaffs_Object *yfsd_FindDirectoryByWinPath(yaffs_Device *device, const wchar_t *path, char *processed, int length)
\r
590 // a buffer to keep the current chunk of path we're talking about it
\r
591 char pathChunk[255];
\r
594 // the current object we are at
\r
595 yaffs_Object *current;
\r
597 RETAILMSG (MSGSTATE, (L"YAFFS::FindByWinPath (%s) : ", path));
\r
598 // start at the root of this device
\r
599 current = yaffs_Root(device);
\r
604 // parse chunks until we run out
\r
605 chunkSize = parseToNextSlash(path, pathChunk, 255);
\r
606 // RETAILMSG(1, (L"Chunk %a\r\n", pathChunk));
\r
607 if (chunkSize == -1)
\r
609 // move the path pointer along
\r
611 // try and find the next yaffs object by chunkname
\r
612 current = yaffs_FindObjectByName(current, pathChunk);
\r
615 processed[0] = '\0';
\r
620 for (counter = 0; counter < length; counter++)
\r
622 // Get the rest of the string
\r
623 processed[counter] = pathChunk[counter];
\r
624 if (pathChunk[counter] == '\0')
\r
628 RETAILMSG (MSGSTATE, (L"YAFFS::FindDirectoryByWinPath parent:%X name:%a\r\n", current,processed));
\r
634 yaffs_Object *yfsd_FindObjectByWinPath(yaffs_Device *dev, PCWSTR pwsFileName )
\r
636 yaffs_Object *obj = NULL;
\r
637 yaffs_Object *parent = NULL;
\r
638 char name[YFSD_NAME_LENGTH+1];
\r
640 RETAILMSG (MSGSTATE, (L"YAFFS::FindObjByWinPath\r\n"));
\r
642 parent = yfsd_FindDirectoryByWinPath(dev,pwsFileName,name,YFSD_NAME_LENGTH);
\r
644 if(parent && yfsd_NameIsValid(name))
\r
646 obj = yaffs_FindObjectByName(parent,name);
\r
649 RETAILMSG (MSGSTATE, (L"YAFFS::FindObjectByWinPath parent:%X obj:%X\r\n", parent,obj));
\r
654 BOOL YFSD_InitVolume(HDSK hdsk, yfsd_Volume *vol, int startBlock, int endBlock, PWSTR volName)
\r
657 WCHAR szName[MAX_PATH];
\r
660 RETAILMSG (MSGSTATE, (L"YAFFS::InitVolume\r\n"));
\r
661 //slf021104b Begin filled in later.
\r
662 //vol->volName = volName;
\r
668 //slf021220a Begin Cleanup block driver interface
\r
669 #if _WINCEOSVER >= 400
\r
670 // For Win'CE 4.0 and later pass the hdsk for use by the yandif layer.
\r
671 vol->dev.genericDevice = (PVOID)hdsk;
\r
673 //slf021220a End Cleanup block driver interface
\r
675 //Mount/initialise YAFFs here
\r
676 //slf021127a begin check for error returns!
\r
677 if (ynandif_InitialiseNAND(&vol->dev))
\r
679 //slf021127a end check for error returns!
\r
680 vol->dev.writeChunkToNAND = ynandif_WriteChunkToNAND;
\r
681 vol->dev.readChunkFromNAND = ynandif_ReadChunkFromNAND;
\r
682 vol->dev.eraseBlockInNAND = ynandif_EraseBlockInNAND;
\r
683 vol->dev.initialiseNAND = ynandif_InitialiseNAND;
\r
684 vol->dev.startBlock = startBlock;
\r
685 if (endBlock != -1)
\r
686 vol->dev.endBlock = endBlock;
\r
687 vol->dev.nShortOpCaches = 10; // a nice number of caches.
\r
688 vol->dev.nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
\r
689 vol->dev.nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
\r
692 // nBlocks is set the total size of the disk, not the partition
\r
693 // vol->dev.nBlocks = endBlock - startBlock + 1;
\r
695 // qnand_EraseAllBlocks(&vol->dev);
\r
697 //slf021127a begin check for error returns!
\r
698 if (yaffs_GutsInitialise(&vol->dev))
\r
700 //slf021127a end check for error returns!
\r
701 RETAILMSG(1, (L"YAFFS::Done yaffs_GutsInitialise\r\n"));
\r
703 RETAILMSG(1, (L"Blocks start %d end %d Group size %d bits %d\r\n",
\r
704 vol->dev.startBlock,vol->dev.endBlock,
\r
705 vol->dev.chunkGroupSize,vol->dev.chunkGroupBits));
\r
709 for(i = vol->dev.startBlock; i <= vol->dev.endBlock; i++)
\r
711 switch(vol->dev.blockInfo[i].blockState)
\r
713 case YAFFS_BLOCK_STATE_DEAD:
\r
715 RETAILMSG(1, (L"YAFFS::Dead block %d\r\n",i));
\r
718 case YAFFS_BLOCK_STATE_EMPTY: emptyBlox++; break;
\r
719 case YAFFS_BLOCK_STATE_FULL: fullBlox++; break;
\r
720 case YAFFS_BLOCK_STATE_ALLOCATING: allocatingBlox++; break;
\r
721 case YAFFS_BLOCK_STATE_DIRTY: dirtyBlox++; break;
\r
723 RETAILMSG(1, (L"YAFFS::Block %d has goofus state %d\r\n",i,vol->dev.blockInfo[i].blockState));
\r
728 RETAILMSG(1, (L"Blocks dead %d empty %d full %d allocating %d dirty %d\r\n",
\r
729 deadBlox,emptyBlox,fullBlox,allocatingBlox,dirtyBlox));
\r
733 //slf021127a begin check for error returns!
\r
734 vol->isMounted = 1;
\r
737 //slf021127a begin check for error returns!
\r
739 yfsd_UnlockYAFFS();
\r
741 //slf021127a begin check for error returns!
\r
742 // vol->isMounted = 1;
\r
743 //slf021127a begin check for error returns!
\r
746 //vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,vol->volName,vol);
\r
747 // If the caller passed a volume name use it.
\r
749 wcscpy( szName, volName);
\r
750 #if WINCEOSVER >= 400
\r
751 // The user passed an empty volume name. On CE 4.xx try to get
\r
752 // if from the block driver (which got it from the registry).
\r
753 else if (!FSDMGR_DiskIoControl(hdsk, DISK_IOCTL_GETNAME, NULL, 0, (LPVOID)szName, sizeof(szName), &dwAvail, NULL))
\r
758 // Didn't get a volume name so use "Disk" by default.
\r
759 wcscpy( szName, YFSD_DISK_NAME);
\r
761 vol->mgrVolume = FSDMGR_RegisterVolume(hdsk,szName,vol);
\r
767 // Get some space for the volume name.
\r
768 vol->volName = malloc( MAX_PATH * sizeof(WCHAR));
\r
771 #if WINCEOSVER >= 400
\r
772 // Get the name we were really mounted under.
\r
773 FSDMGR_GetVolumeName(vol->mgrVolume, vol->volName, MAX_PATH);
\r
775 // If we got mounted as root then throw away the backslash
\r
776 // so we won't get a double backslash when volName is
\r
777 // prepended to the path in the full path name calculation
\r
778 // that is used for shell callbacks.
\r
779 if (0 == wcscmp(vol->volName,L"\\"))
\r
780 vol->volName[0] = 0;
\r
782 // Use the name we asked to be mounted under for
\r
784 wcscpy(vol->volName,L"\\");
\r
785 wcscat(vol->volName, szName);
\r
793 vol->isMounted = 0;
\r
794 SetLastError(ERROR_OUTOFMEMORY);
\r
800 BOOL YFSD_MountDisk(HDSK hdsk)
\r
803 #ifdef DO_PARTITION_TABLE
\r
804 ynandif_partition PartTable[MAXPARTITIONS];
\r
810 int deadBlox=0,emptyBlox=0,fullBlox=0,allocatingBlox=0,dirtyBlox=0;
\r
812 // Called to mount a disk.
\r
813 // NB THis call might happen redundantly.
\r
816 // If yaffs is not initialised, then call the
\r
817 // initialisation function
\r
819 RETAILMSG (MSGSTATE, (L"YAFFS::MountDisk\r\n"));
\r
821 if (!yaffsLockInited)
\r
823 InitializeCriticalSection(&yaffsLock);
\r
824 yfsd_InitialiseWinFiles();
\r
825 yaffsLockInited = 1;
\r
829 memset(disk_volumes,0,sizeof(disk_volumes));
\r
830 #ifdef DO_PARTITION_TABLE
\r
831 memset(&PartTable,0,sizeof(PartTable));
\r
832 // Call the block driver to get the partition table from it.
\r
833 if (FSDMGR_DiskIoControl(hdsk, YNANDIF_GETPARTITIONS, NULL, 0, (LPVOID)&PartTable, sizeof(PartTable), &dwAvail, NULL))
\r
835 // Scan throught the table it return.
\r
836 for (i=0; i<MAXPARTITIONS; i++)
\r
838 // At the very lease check that the end is later than the beginning
\r
839 // and don't let it start at 0.
\r
840 // Probably could do more thorough checking but I trust the block
\r
842 if (PartTable[i].startBlock && (PartTable[i].endBlock > PartTable[i].startBlock))
\r
844 // Found a partion. Get a volume structure to hold it.
\r
845 disk_volumes[i] = malloc(sizeof(yfsd_Volume));
\r
846 if (disk_volumes[i])
\r
848 memset(disk_volumes[i],0,sizeof(yfsd_Volume));
\r
849 // Go init the volume. Note that if the block driver wants the
\r
850 // name to come from the registry it will have returned an
\r
851 // empty name string.
\r
852 YFSD_InitVolume(hdsk,disk_volumes[i],PartTable[i].startBlock,PartTable[i].endBlock,PartTable[i].volName);
\r
853 if (disk_volumes[i]->isMounted)
\r
854 rval = TRUE; //Hey, we found at least on partition.
\r
863 #ifdef DISABLE_BOOT_PARTITION
\r
864 // Only want disk volume
\r
865 disk_volumes[0] = malloc(sizeof(yfsd_Volume));
\r
866 if (disk_volumes[0])
\r
868 memset(disk_volumes[0],0,sizeof(yfsd_Volume));
\r
869 YFSD_InitVolume(hdsk, disk_volumes[0], 1, -1, YFSD_DISK_NAME);
\r
871 if(disk_volumes[0].isMounted)
\r
876 if (disk_volumes[0])
\r
878 free(disk_volumes[0];
\r
879 disk_volumes[0] = NULL;
\r
882 // Want both boot and disk
\r
883 disk_volumes[0] = malloc(sizeof(yfsd_Volume));
\r
884 disk_volumes[1] = malloc(sizeof(yfsd_Volume));
\r
885 if (disk_volumes[0] && disk_volumes[1])
\r
887 memset(disk_volumes[0],0,sizeof(yfsd_Volume));
\r
888 memset(disk_volumes[1],0,sizeof(yfsd_Volume));
\r
889 YFSD_InitVolume(hdsk, disk_volumes[0], PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
\r
890 YFSD_InitVolume(hdsk, disk_volumes[1], 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
\r
892 #ifdef MSGBOX_DISPLAY
\r
893 // pass the device we are sniffing to the thread
\r
894 CreateThread(NULL, 0, yfsd_MessageThread, (LPVOID)&disk_volumes[0]->dev, 0, NULL);
\r
897 if(disk_volumes[0]->isMounted && disk_volumes[1]->isMounted)
\r
903 // If we got this far something went wrong. Make sure to
\r
904 // free any memory we allocated.
\r
905 if (disk_volumes[0])
\r
907 if (disk_volumes[0]->volName)
\r
909 free(disk_volumes[0]->volName);
\r
911 free(disk_volumes[0]);
\r
912 disk_volumes[0] = NULL;
\r
914 if (disk_volumes[1])
\r
916 if (disk_volumes[1]->volName)
\r
918 free(disk_volumes[1]->volName);
\r
920 free(disk_volumes[1]);
\r
921 disk_volumes[1] = NULL;
\r
927 // Only want disk volume
\r
928 // YFSD_InitVolume(hdsk, &disk_volume, 1, -1, YFSD_DISK_NAME);
\r
931 // if(disk_volume.isMounted)
\r
936 // // Want both boot and disk
\r
937 // YFSD_InitVolume(hdsk, &disk_volume, PARTITION_START_NUMBER+1, -1, YFSD_DISK_NAME);
\r
938 // YFSD_InitVolume(hdsk, &boot_volume, 1, PARTITION_START_NUMBER, YFSD_BOOT_NAME);
\r
941 // if(disk_volume.isMounted && boot_volume.isMounted)
\r
951 // yfsd_SetGuards();
\r
953 // todo - get name from registry
\r
958 BOOL YFSD_UnmountDisk(HDSK hdsk)
\r
963 RETAILMSG (MSGSTATE, (L"YAFFS::UnmountDisk\r\n"));
\r
966 // If there are any files open don't let them dismount
\r
967 // it or the system will get very confused.
\r
968 if (yfsd_FilesOpen())
\r
971 //yfsd_FlushAllFiles();
\r
976 // yaffs_Deinitialise(&disk_volume.dev);
\r
977 // yaffs_Deinitialise(&boot_volume.dev);
\r
978 // yfsd_UnlockYAFFS();
\r
980 // FSDMGR_DeregisterVolume(disk_volume.mgrVolume);
\r
981 // FSDMGR_DeregisterVolume(boot_volume.mgrVolume);
\r
983 // Walk through the partions deinitializing, deregistering
\r
984 // and freeing them.
\r
985 for (i=0; i<MAXPARTITIONS; i++)
\r
987 if (disk_volumes[i])
\r
989 yaffs_Deinitialise(&(disk_volumes[i]->dev));
\r
990 //slf021220a Begin Cleanup block driver interface
\r
991 ynandif_DeinitialiseNAND(&(disk_volumes[i]->dev));
\r
992 //slf021220a end Cleanup block driver interface
\r
993 FSDMGR_DeregisterVolume(disk_volumes[i]->mgrVolume);
\r
994 if (disk_volumes[i]->volName)
\r
996 free(disk_volumes[i]->volName);
\r
998 free(disk_volumes[i]);
\r
999 disk_volumes[i] = NULL;
\r
1002 yfsd_UnlockYAFFS();
\r
1008 BOOL YFSD_CreateDirectoryW(PVOLUME pVolume, PCWSTR pathName, PSECURITY_ATTRIBUTES pSecurityAttributes)
\r
1010 // security attributes are ignored (should be NULL)
\r
1012 yaffs_Object *newDir = NULL;
\r
1013 yaffs_Object *parent = NULL;
\r
1014 char name[YFSD_NAME_LENGTH+1];
\r
1017 unsigned modifiedTime[2];
\r
1019 RETAILMSG (MSGSTATE, (L"YAFFS::CreateDirectory (%s)\r\n", pathName));
\r
1023 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
\r
1025 //slf021101b begin
\r
1028 if(yfsd_NameIsValid(name))
\r
1030 newDir = yaffs_MknodDirectory(parent,name,0,0,0);
\r
1033 objSize = yaffs_GetObjectFileLength(newDir);
\r
1034 attribs = yfsd_GetObjectWinAttributes(newDir);
\r
1035 modifiedTime[0] = newDir->win_mtime[0];
\r
1036 modifiedTime[1] = newDir->win_mtime[1];
\r
1040 if(yaffs_FindObjectByName(parent,name))
\r
1041 SetLastError(ERROR_ALREADY_EXISTS);
\r
1043 SetLastError(ERROR_DISK_FULL);
\r
1047 SetLastError(ERROR_INVALID_NAME);
\r
1051 SetLastError(ERROR_PATH_NOT_FOUND);
\r
1055 yfsd_UnlockYAFFS();
\r
1057 // Call shell function to tell of new directory
\r
1058 if(newDir && pVolume->shellFunction)
\r
1060 FILECHANGEINFO fc;
\r
1061 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
1063 fc.cbSize = sizeof(FILECHANGEINFO);
\r
1064 fc.wEventId = SHCNE_MKDIR;
\r
1065 fc.uFlags = SHCNF_PATH;
\r
1066 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume, fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
\r
1068 fc.dwAttributes = attribs;
\r
1069 yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
\r
1070 fc.nFileSize = objSize;
\r
1072 pVolume->shellFunction(&fc);
\r
1073 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
1075 //yfsd_ShellDirectoryChanged(pVolume,fpn);
\r
1079 //slf021101b begin
\r
1080 // if(parent && !newDir)
\r
1082 // SetLastError(ERROR_DISK_FULL);
\r
1086 return newDir ? TRUE : FALSE;
\r
1090 BOOL YFSD_RemoveDirectoryW(PVOLUME pVolume, PCWSTR pathName)
\r
1092 int result = FALSE;
\r
1093 yaffs_Object *parent = NULL;
\r
1094 yaffs_Object *obj;
\r
1095 char name[YFSD_NAME_LENGTH+1];
\r
1097 RETAILMSG (MSGSTATE, (L"YAFFS::RemoveDirectory (%s)\r\n", pathName));
\r
1101 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pathName);
\r
1104 SetLastError(ERROR_PATH_NOT_FOUND);
\r
1107 else if (obj->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
\r
1109 SetLastError(ERROR_ACCESS_DENIED);
\r
1112 else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)
\r
1114 SetLastError(ERROR_ACCESS_DENIED);
\r
1117 else if(obj->inUse)
\r
1119 SetLastError(ERROR_ACCESS_DENIED);
\r
1125 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pathName,name,YFSD_NAME_LENGTH);
\r
1127 if(parent && yfsd_NameIsValid(name))
\r
1129 result = yaffs_Unlink(parent,name);
\r
1131 SetLastError(ERROR_DIR_NOT_EMPTY);
\r
1135 yfsd_UnlockYAFFS();
\r
1137 if(result && pVolume->shellFunction)
\r
1139 FILECHANGEINFO fc;
\r
1140 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
1142 fc.cbSize = sizeof(FILECHANGEINFO);
\r
1143 fc.wEventId = SHCNE_RMDIR;
\r
1144 fc.uFlags = SHCNF_PATH;
\r
1145 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pathName);
\r
1147 fc.dwAttributes = 0;
\r
1148 yfsd_NullWinFileTime(&fc.ftModified);
\r
1151 pVolume->shellFunction(&fc);
\r
1152 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
1154 yfsd_ShellDirectoryChanged(pVolume,fpn);
\r
1157 return result ? TRUE : FALSE;
\r
1161 DWORD YFSD_GetFileAttributesW(PVOLUME pVolume, PCWSTR pwsFileName )
\r
1163 yaffs_Object *obj = NULL;
\r
1165 DWORD result = 0xFFFFFFFF;
\r
1167 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes\r\n"));
\r
1171 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
\r
1175 result = yfsd_GetObjectWinAttributes(obj);
\r
1179 SetLastError(ERROR_FILE_NOT_FOUND);
\r
1182 yfsd_UnlockYAFFS();
\r
1184 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileAttributes for %s returning %X\r\n",pwsFileName,result));
\r
1190 BOOL YFSD_SetFileAttributesW( PVOLUME pVolume,PCWSTR pwsFileName, DWORD dwFileAttributes )
\r
1192 yaffs_Object *obj = NULL;
\r
1199 RETAILMSG (MSGSTATE, (L"YAFFS::SetFileAttributes %X\r\n",dwFileAttributes));
\r
1201 if(!yfsd_CheckValidAttributes(dwFileAttributes))
\r
1203 SetLastError(ERROR_INVALID_PARAMETER);
\r
1209 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
\r
1213 obj->st_mode = dwFileAttributes;
\r
1215 result = yaffs_FlushFile(obj,0);
\r
1216 attribs = yfsd_GetObjectWinAttributes(obj);
\r
1217 objSize = yaffs_GetObjectFileLength(obj);
\r
1218 mtime[0] = obj->win_mtime[0];
\r
1219 mtime[1] = obj->win_mtime[1];
\r
1223 SetLastError(ERROR_FILE_NOT_FOUND);
\r
1226 yfsd_UnlockYAFFS();
\r
1228 if(result && pVolume->shellFunction)
\r
1230 FILECHANGEINFO fc;
\r
1231 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
1233 fc.cbSize = sizeof(FILECHANGEINFO);
\r
1234 fc.wEventId = SHCNE_ATTRIBUTES;
\r
1235 fc.uFlags = SHCNF_PATH;
\r
1236 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
\r
1238 fc.dwAttributes = attribs;
\r
1239 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
\r
1240 fc.nFileSize = objSize;
\r
1242 pVolume->shellFunction(&fc);
\r
1243 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
1245 //yfsd_ShellDirectoryChanged(pVolume,fpn);
\r
1253 BOOL YFSD_DeleteFileW( PVOLUME pVolume, PCWSTR pwsFileName )
\r
1255 int result = FALSE;
\r
1256 yaffs_Object *parent = NULL;
\r
1257 yaffs_Object *obj;
\r
1258 char name[YFSD_NAME_LENGTH+1];
\r
1260 RETAILMSG (MSGSTATE, (L"YAFFS::DeleteFileW (%s)\r\n", pwsFileName));
\r
1264 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
\r
1267 SetLastError(ERROR_FILE_NOT_FOUND);
\r
1270 else if (obj->variantType != YAFFS_OBJECT_TYPE_FILE)
\r
1272 SetLastError(ERROR_ACCESS_DENIED);
\r
1275 else if(obj->st_mode & FILE_ATTRIBUTE_READONLY)
\r
1277 SetLastError(ERROR_ACCESS_DENIED);
\r
1280 else if(obj->inUse)
\r
1282 SetLastError(ERROR_ACCESS_DENIED);
\r
1288 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);
\r
1290 if(parent && yfsd_NameIsValid(name))
\r
1292 result = yaffs_Unlink(parent,name);
\r
1294 SetLastError(ERROR_ACCESS_DENIED);
\r
1298 yfsd_UnlockYAFFS();
\r
1300 if(result && pVolume->shellFunction)
\r
1302 FILECHANGEINFO fc;
\r
1303 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
1305 fc.cbSize = sizeof(FILECHANGEINFO);
\r
1306 fc.wEventId = SHCNE_DELETE;
\r
1307 fc.uFlags = SHCNF_PATH;
\r
1308 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
\r
1310 fc.dwAttributes = -1;
\r
1311 yfsd_NullWinFileTime(&fc.ftModified);
\r
1314 pVolume->shellFunction(&fc);
\r
1315 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
1317 yfsd_ShellDirectoryChanged(pVolume,fpn);
\r
1320 return result ? TRUE : FALSE;
\r
1323 BOOL YFSD_MoveFileW(PVOLUME pVolume,PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
\r
1325 yaffs_Object *newParent = NULL;
\r
1326 yaffs_Object *oldParent = NULL;
\r
1327 yaffs_Object *obj = NULL;
\r
1328 char oldName[YFSD_NAME_LENGTH+1];
\r
1329 char newName[YFSD_NAME_LENGTH+1];
\r
1336 RETAILMSG (MSGSTATE, (L"YAFFS::MoveFile\r\n"));
\r
1340 oldParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsOldFileName,oldName,YFSD_NAME_LENGTH);
\r
1341 newParent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsNewFileName,newName,YFSD_NAME_LENGTH);
\r
1343 if(oldParent && yfsd_NameIsValid(oldName) && newParent && yfsd_NameIsValid(newName))
\r
1345 result = yaffs_RenameObject(oldParent,oldName,newParent,newName);
\r
1348 SetLastError(ERROR_FILE_NOT_FOUND);
\r
1351 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsNewFileName);
\r
1354 objIsDir = (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY);
\r
1355 attribs = yfsd_GetObjectWinAttributes(obj);
\r
1356 objSize = yaffs_GetObjectFileLength(obj);
\r
1357 mtime[0] = obj->win_mtime[0];
\r
1358 mtime[1] = obj->win_mtime[1];
\r
1363 SetLastError(ERROR_PATH_NOT_FOUND);
\r
1366 yfsd_UnlockYAFFS();
\r
1369 if(result && pVolume->shellFunction)
\r
1371 FILECHANGEINFO fc;
\r
1372 WCHAR fpn1[YFSD_FULL_PATH_NAME_SIZE];
\r
1373 WCHAR fpn2[YFSD_FULL_PATH_NAME_SIZE];
\r
1375 fc.cbSize = sizeof(FILECHANGEINFO);
\r
1376 fc.wEventId = objIsDir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM;
\r
1377 fc.uFlags = SHCNF_PATH;
\r
1378 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn1,YFSD_FULL_PATH_NAME_SIZE,pwsOldFileName);
\r
1379 fc.dwItem2 = (DWORD)yfsd_FullPathName(pVolume,fpn2,YFSD_FULL_PATH_NAME_SIZE,pwsNewFileName);
\r
1380 fc.dwAttributes = attribs;
\r
1381 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
\r
1382 fc.nFileSize = objSize;
\r
1384 pVolume->shellFunction(&fc);
\r
1385 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
1387 yfsd_ShellDirectoryChanged(pVolume,fpn1);
\r
1388 yfsd_ShellDirectoryChanged(pVolume,fpn2);
\r
1392 return result ? TRUE : FALSE;
\r
1396 BOOL YFSD_DeleteAndRenameFileW(PVOLUME pVolume, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName )
\r
1398 //slf021104c begin
\r
1402 RETAILMSG (MSGSTATE, (L"YAFFS::DeleteAndRename\r\n"));
\r
1404 //slf021104c begin
\r
1405 if (fSuccess = YFSD_DeleteFileW(pVolume, pwsOldFileName))
\r
1406 fSuccess = YFSD_MoveFileW(pVolume, pwsNewFileName, pwsOldFileName);
\r
1412 BOOL YFSD_GetDiskFreeSpaceW( PVOLUME pVolume, PCWSTR pwsPathName, PDWORD pSectorsPerCluster,PDWORD pBytesPerSector, PDWORD pFreeClusters, PDWORD pClusters )
\r
1417 RETAILMSG (MSGSTATE, (L"YAFFS::GetFreeSpace\r\n"));
\r
1420 nChunks = yaffs_GetNumberOfFreeChunks(&pVolume->dev);
\r
1421 yfsd_UnlockYAFFS();
\r
1425 // Let's pretentd our clusters are the same size as eraseable blocks...
\r
1426 *pBytesPerSector = 512;
\r
1427 *pSectorsPerCluster =32;
\r
1428 *pFreeClusters = nChunks/32;
\r
1429 *pClusters = pVolume->dev.endBlock - pVolume->dev.startBlock + 1;
\r
1432 return (nChunks >= 0)? TRUE : FALSE;
\r
1438 void YFSD_Notify(PVOLUME pVolume, DWORD dwFlags )
\r
1440 // Flags can be one of:
\r
1441 // FSNOTIFY_POWER_ON: no action required
\r
1442 // FSNOTIFY_POWER_OFF: flush all files
\r
1443 // FSNOTIFY_DEVICE_ON: no action required
\r
1445 RETAILMSG (MSGSTATE, (L"YAFFS::Notify\r\n"));
\r
1446 if(dwFlags == FSNOTIFY_POWER_OFF)
\r
1448 yfsd_FlushAllFiles();
\r
1454 BOOL YFSD_RegisterFileSystemFunction(PVOLUME pVolume,SHELLFILECHANGEFUNC_t pfn )
\r
1456 RETAILMSG (MSGSTATE, (L"YAFFS::RegisterFileSysFunction\r\n"));
\r
1458 pVolume->shellFunction = pfn;
\r
1467 int iMatch(const char a, const char b)
\r
1469 if (a == '?' || b == '?')
\r
1471 return (toupper(a) == toupper(b));
\r
1474 void pString(const char *inp)
\r
1476 while (*inp) RETAILMSG(1, (L"%c", *inp++));
\r
1479 int regularMatch(const char *regexp, const char *str)
\r
1481 // pString(regexp);
\r
1482 // RETAILMSG(1, (L" "));
\r
1484 // RETAILMSG(1, (L"\r\n"));
\r
1486 if (*regexp == 0 && *str == 0)
\r
1488 //RETAILMSG(1, (L"Match!\r\n"));
\r
1491 if (*regexp == '*')
\r
1494 if (*regexp == 0) // end of the expression is a *, we must match
\r
1496 //RETAILMSG(1, (L"Match!\r\n"));
\r
1499 while (!iMatch(*regexp, *str)) // throw away chars from str until we match
\r
1501 if (*str == 0) // if we're not at the end
\r
1503 // if we have .* left to match, but the str is finished then match it OK
\r
1504 if (regexp[0] == '.' && regexp[1] == '*')
\r
1506 //RETAILMSG(1, (L"Match!\r\n"));
\r
1511 // the extension failed the match
\r
1512 //RETAILMSG(1, (L"No Match!\r\n"));
\r
1518 // right now we should either eat more characters, or try to match
\r
1519 return (regularMatch(regexp, str) || regularMatch(--regexp, ++str));
\r
1521 // compare chars until we hit another *, or we fail
\r
1522 while (iMatch(*regexp, *str))
\r
1524 if (*regexp == 0 && *str == 0)
\r
1526 //RETAILMSG(1, (L"Match!\r\n"));
\r
1533 if (*regexp == 0 && *str == 0)
\r
1535 //RETAILMSG(1, (L"Match!\r\n"));
\r
1539 if (*regexp == '*')
\r
1540 return regularMatch(regexp, str);
\r
1542 //RETAILMSG(1, (L"No Match!\r\n"));
\r
1547 void yfsd_DeleteFinder(PSEARCH pSearch)
\r
1549 if(pSearch->foundObjects) //If we found some objects we must clean up the cached linked list.
\r
1551 yaffs_FoundObject *it;
\r
1552 yaffs_FoundObject *temp;
\r
1554 it = pSearch->foundObjects;
\r
1564 pSearch->foundObjects = NULL;
\r
1567 pSearch->dir->inUse--;
\r
1571 BOOL yfsd_ObjectAlreadyFound(PSEARCH pSearch, yaffs_Object *l)
\r
1573 //Iterate through the current list of objs already found and return true if already exists.
\r
1574 //If the object hasn't already been found then add it to the list (SIDE-EFFECT alert) and return false.
\r
1575 BOOL found = FALSE;
\r
1577 yaffs_FoundObject *it;
\r
1578 it = pSearch->foundObjects;
\r
1581 while(it->next != NULL) //iterate through singly linked list.
\r
1593 //Add the item to the list.
\r
1594 //'it' will currently be pointing to the last of the list nodes. i.e node->next == NULL
\r
1595 it->next = malloc(sizeof(yaffs_FoundObject));
\r
1596 it->next->next = NULL;
\r
1597 it->next->obj = 0;
\r
1607 BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
\r
1610 struct list_head *i;
\r
1615 char name[YAFFS_MAX_NAME_LENGTH+1];
\r
1617 if(!pSearch->foundObjects)
\r
1619 pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
\r
1620 pSearch->foundObjects->next = NULL;
\r
1621 pSearch->foundObjects->obj = 0;
\r
1628 list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
\r
1631 l = list_entry(i, yaffs_Object,siblings);
\r
1633 yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
\r
1635 if(regularMatch(pSearch->pattern,name))
\r
1637 if(!yfsd_ObjectAlreadyFound(pSearch, l))//pos == pSearch->currentPos)
\r
1642 //pSearch->currentPos++;
\r
1644 // fill out find data
\r
1646 pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
\r
1648 yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
\r
1649 yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
\r
1650 yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
\r
1652 pfd->nFileSizeHigh = 0;
\r
1653 pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
\r
1654 pfd->dwOID = (CEOID)(INVALID_HANDLE_VALUE); // wtf is this???
\r
1656 MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
\r
1658 RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
\r
1659 pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
\r
1660 l->variant.fileVariant.scannedFileSize));
\r
1671 yfsd_UnlockYAFFS();
\r
1676 SetLastError(ERROR_NO_MORE_FILES);
\r
1684 BOOL yfsd_DoFindFile(PSEARCH pSearch, PWIN32_FIND_DATAW pfd)
\r
1687 struct list_head *i;
\r
1691 char name[YAFFS_MAX_NAME_LENGTH+1];
\r
1693 if(!pSearch->foundObjects)
\r
1695 pSearch->foundObjects = malloc(sizeof(yaffs_FoundObject));
\r
1696 pSearch->foundObjects->next = NULL;
\r
1697 pSearch->foundObjects->obj = 0;
\r
1703 list_for_each(i,&pSearch->dir->variant.directoryVariant.children)
\r
1706 l = list_entry(i, yaffs_Object,siblings);
\r
1707 if(!yfsd_ObjectAlreadyFound(pSearch,l))
\r
1709 // Only look at things we have not looked at already
\r
1710 yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
\r
1712 if(regularMatch(pSearch->pattern,name))
\r
1715 // fill out find data
\r
1717 pfd->dwFileAttributes = yfsd_GetObjectWinAttributes(l);
\r
1719 yfsd_U32sToWinFileTime(l->win_ctime,&pfd->ftCreationTime);
\r
1720 yfsd_U32sToWinFileTime(l->win_atime,&pfd->ftLastAccessTime);
\r
1721 yfsd_U32sToWinFileTime(l->win_mtime,&pfd->ftLastWriteTime);
\r
1723 pfd->nFileSizeHigh = 0;
\r
1724 pfd->nFileSizeLow = yaffs_GetObjectFileLength(l);
\r
1725 pfd->dwOID = (CEOID)(INVALID_HANDLE_VALUE); // wtf is this???
\r
1727 MultiByteToWideChar(CP_ACP,0,name,-1,pfd->cFileName,YFSD_NAME_LENGTH);
\r
1729 RETAILMSG(MSGSTATE,(L"File %s id %d header %d nDataChunks %d scannedLength %d\r\n",
\r
1730 pfd->cFileName,l->objectId, l->chunkId, l->nDataChunks,
\r
1731 l->variant.fileVariant.scannedFileSize));
\r
1741 yfsd_UnlockYAFFS();
\r
1746 SetLastError(ERROR_NO_MORE_FILES);
\r
1753 HANDLE YFSD_FindFirstFileW(PVOLUME pVolume, HANDLE hProc,PCWSTR pwsFileSpec, PWIN32_FIND_DATAW pfd )
\r
1756 // Create a search context, register it, and do the first search
\r
1759 HANDLE h = INVALID_HANDLE_VALUE;
\r
1762 RETAILMSG (MSGSTATE, (L"YAFFS::FindFirst\r\n"));
\r
1764 pSearch = malloc(sizeof(yfsd_WinFind));
\r
1767 SetLastError(ERROR_OUTOFMEMORY);
\r
1774 pSearch->foundObjects = NULL; //pSearch->currentPos = 0;
\r
1775 pSearch->dir = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileSpec,pSearch->pattern,YFSD_NAME_LENGTH);
\r
1778 pSearch->dir->inUse++;
\r
1784 SetLastError(ERROR_PATH_NOT_FOUND);
\r
1788 yfsd_UnlockYAFFS();
\r
1794 found = yfsd_DoFindFile(pSearch,pfd);
\r
1798 h = FSDMGR_CreateSearchHandle(pVolume->mgrVolume,hProc,pSearch);
\r
1799 if(h == INVALID_HANDLE_VALUE)
\r
1801 SetLastError(ERROR_NO_MORE_SEARCH_HANDLES);
\r
1806 SetLastError(ERROR_FILE_NOT_FOUND);
\r
1809 if(h == INVALID_HANDLE_VALUE)
\r
1811 yfsd_DeleteFinder(pSearch);
\r
1820 BOOL YFSD_FindNextFileW(PSEARCH pSearch, PWIN32_FIND_DATAW pfd )
\r
1822 RETAILMSG (MSGSTATE, (L"YAFFS::FindNext\r\n"));
\r
1827 return yfsd_DoFindFile(pSearch,pfd);
\r
1830 BOOL YFSD_FindClose( PSEARCH pSearch )
\r
1832 RETAILMSG (MSGSTATE, (L"YAFFS::FindClose\r\n"));
\r
1837 yfsd_DeleteFinder(pSearch);
\r
1842 HANDLE YFSD_CreateFileW(
\r
1845 PCWSTR pwsFileName,
\r
1847 DWORD dwShareMode,
\r
1848 PSECURITY_ATTRIBUTES pSecurityAttributes, // ignore
\r
1850 DWORD dwFlagsAndAttributes,
\r
1851 HANDLE hTemplateFile ) // ignore
\r
1855 yaffs_Object *parent = NULL;
\r
1856 yaffs_Object *obj = NULL;
\r
1857 char name[YFSD_NAME_LENGTH+1];
\r
1859 yfsd_WinFile *f = NULL;
\r
1860 HANDLE handle = INVALID_HANDLE_VALUE;
\r
1861 unsigned modifiedTime[2];
\r
1864 BOOL writePermitted = (dwAccess & GENERIC_WRITE) ? TRUE : FALSE;
\r
1865 BOOL readPermitted = (dwAccess & GENERIC_READ) ? TRUE : FALSE;
\r
1866 BOOL shareRead = (dwShareMode & FILE_SHARE_READ) ? TRUE : FALSE;
\r
1867 BOOL shareWrite = (dwShareMode & FILE_SHARE_WRITE) ? TRUE : FALSE;
\r
1869 BOOL openRead, openWrite, openReadAllowed, openWriteAllowed;
\r
1871 BOOL fileCreated = FALSE;
\r
1873 BOOL fAlwaysCreateOnExistingFile = FALSE;
\r
1874 BOOL fTruncateExistingFile = FALSE;
\r
1877 mode = dwFlagsAndAttributes & 0x00FFFFFF; // ding off the flags
\r
1878 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile (%s) flags %X mode %X\r\n", pwsFileName,dwFlagsAndAttributes,mode));
\r
1879 if(writePermitted)
\r
1881 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write permitted\r\n"));
\r
1885 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile write not permitted\r\n"));
\r
1888 if(!yfsd_CheckValidAttributes(mode))
\r
1890 SetLastError(ERROR_INVALID_PARAMETER);
\r
1897 parent = yfsd_FindDirectoryByWinPath(&pVolume->dev,pwsFileName,name,YFSD_NAME_LENGTH);
\r
1900 if(parent && yfsd_NameIsValid(name))
\r
1903 //slf021220b begin Fix still more bugs in CreateFile.
\r
1904 // Get the object for this file if it exists (only once).
\r
1905 obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
\r
1906 //slf021220b end Fix still more bugs in CreateFile.
\r
1907 if(dwCreate == CREATE_NEW)
\r
1909 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in CREATE_NEW\r\n"));
\r
1911 //slf021101c begin
\r
1912 //slf021220b begin Fix still more bugs in CreateFile.
\r
1913 // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
\r
1914 //slf021220b end Fix still more bugs in CreateFile.
\r
1917 obj = yaffs_MknodFile(parent,name,mode,0,0);
\r
1919 SetLastError(ERROR_DISK_FULL);
\r
1920 fileCreated = TRUE;
\r
1922 //slf021220b begin Fix still more bugs in CreateFile.
\r
1923 else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
\r
1926 SetLastError(ERROR_ALREADY_EXISTS);
\r
1928 //slf021220b end Fix still more bugs in CreateFile.
\r
1932 //slf021220b begin Fix still more bugs in CreateFile.
\r
1933 //Match CE FAT error return SetLastError(ERROR_ALREADY_EXISTS);
\r
1934 SetLastError(ERROR_FILE_EXISTS);
\r
1935 //slf021220b begin Fix still more bugs in CreateFile.
\r
1939 else if( dwCreate == OPEN_ALWAYS)
\r
1941 //slf021220b begin Fix still more bugs in CreateFile.
\r
1942 // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
\r
1943 //slf021220b end Fix still more bugs in CreateFile.
\r
1946 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file in OPEN_ALWAYS\r\n"));
\r
1947 obj = yaffs_MknodFile(parent,name,mode,0,0);
\r
1949 SetLastError(ERROR_DISK_FULL);
\r
1950 fileCreated = TRUE;
\r
1953 //slf021220b begin Fix still more bugs in CreateFile.
\r
1954 else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
\r
1957 SetLastError(ERROR_ACCESS_DENIED);
\r
1959 //slf021220b end Fix still more bugs in CreateFile.
\r
1962 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening existing file in OPEN_ALWAYS\r\n"));
\r
1965 else if(dwCreate == OPEN_EXISTING)
\r
1967 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in OPEN_EXISTING\r\n"));
\r
1968 //slf021220b begin Fix still more bugs in CreateFile.
\r
1969 // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
\r
1970 //slf021220b end Fix still more bugs in CreateFile.
\r
1972 SetLastError(ERROR_FILE_NOT_FOUND);
\r
1973 //slf021220b begin Fix still more bugs in CreateFile.
\r
1974 //slf021101c begin
\r
1976 // if (yfsd_GetObjectWinAttributes(obj) & FILE_ATTRIBUTE_DIRECTORY)
\r
1978 // SetLastError(ERROR_ACCESS_DENIED);
\r
1982 else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
\r
1984 SetLastError(ERROR_ACCESS_DENIED);
\r
1987 //slf021220b end Fix still more bugs in CreateFile.
\r
1989 else if(dwCreate == TRUNCATE_EXISTING)
\r
1991 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile opening file in TRUNCATE_EXISTING\r\n"));
\r
1992 //slf021220b begin Fix still more bugs in CreateFile.
\r
1993 // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
\r
1995 if (!writePermitted || (obj && (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)))
\r
1998 SetLastError(ERROR_ACCESS_DENIED);
\r
2001 //slf021220b end Fix still more bugs in CreateFile.
\r
2003 // Indicate that file is to be truncated. This will happen later on assuming
\r
2004 // that a sharing violation does not occur and that we can get a file handle.
\r
2005 fTruncateExistingFile = TRUE;
\r
2009 SetLastError(ERROR_FILE_NOT_FOUND);
\r
2012 else if(dwCreate == CREATE_ALWAYS)
\r
2014 //slf021220b begin Fix still more bugs in CreateFile.
\r
2015 // got above. obj = yfsd_FindObjectByWinPath(&pVolume->dev,pwsFileName);
\r
2016 //slf021220b end Fix still more bugs in CreateFile.
\r
2020 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile creating file parent %X, name %a in CREATE_ALWAYS\r\n",parent,name));
\r
2021 obj = yaffs_MknodFile(parent,name,mode,0,0);
\r
2023 SetLastError(ERROR_DISK_FULL);
\r
2024 fileCreated = TRUE;
\r
2026 //slf021220b begin Fix still more bugs in CreateFile.
\r
2027 else if (obj->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
\r
2030 SetLastError(ERROR_ACCESS_DENIED);
\r
2032 //slf021220b end Fix still more bugs in CreateFile.
\r
2035 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile in CREATE_ALWAYS (already exists)\r\n"));
\r
2036 // Indicate that file is to be recreated. This will happen later on assuming
\r
2037 // that a sharing violation does not occur and that we can get a file handle.
\r
2038 fAlwaysCreateOnExistingFile = TRUE;
\r
2043 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile called with unknown flags %x\r\n", dwCreate));
\r
2044 SetLastError(ERROR_INVALID_PARAMETER);
\r
2049 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile unable to get parent node\r\n"));
\r
2050 SetLastError(ERROR_PATH_NOT_FOUND);
\r
2057 openRead = openWrite =0;
\r
2058 openReadAllowed = openWriteAllowed = 1;
\r
2060 for(i = 0; i < MAX_WIN_FILE; i++)
\r
2062 p = &yfsd_winFile[i];
\r
2066 if (p->readPermitted) openRead = 1;
\r
2067 if (p->writePermitted) openWrite = 1;
\r
2068 if (!p->shareRead) openReadAllowed = 0;
\r
2069 if (!p->shareWrite) openWriteAllowed = 0;
\r
2074 // Now we test if the share works out.
\r
2076 if((openRead && !shareRead) || // already open for read, but we are not prepared to share it for read
\r
2077 (openWrite && !shareWrite) || // already open for write, but we are not prepared to share it for write
\r
2078 (!openReadAllowed && readPermitted) || // already open with read sharing not permitted
\r
2079 (!openWriteAllowed && writePermitted)) // same... write
\r
2081 //slf021220c begin Fix error code for new sharing mode check code.
\r
2082 SetLastError(ERROR_SHARING_VIOLATION);
\r
2083 //slf021220c end Fix error code for new sharing mode check code.
\r
2091 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an object\r\n"));
\r
2092 f = yfsd_GetWinFile();
\r
2096 RETAILMSG (MSGSTATE, (L"YAFFS::Creatfile - no object\r\n"));
\r
2102 handle = FSDMGR_CreateFileHandle(pVolume->mgrVolume,hProc,f);
\r
2104 if(handle != INVALID_HANDLE_VALUE)
\r
2106 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have an fsdmgr handle\r\n"));
\r
2108 if (fTruncateExistingFile)
\r
2110 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - TRUNCATE_EXISTING - truncating existing file\r\n"));
\r
2111 yaffs_ResizeFile(obj,0);
\r
2114 if (fAlwaysCreateOnExistingFile)
\r
2116 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - CREATE_ALWAYS - zapping existing file\r\n"));
\r
2117 obj->st_mode = mode;
\r
2119 yaffs_ResizeFile(obj,0);
\r
2120 yaffs_FlushFile(obj,1);
\r
2125 f->writePermitted = writePermitted;
\r
2126 //slf021220d begin oops typo.
\r
2127 f->readPermitted = readPermitted;
\r
2128 //slf021220d end oops typo.
\r
2129 f->shareRead= shareRead;
\r
2130 f->shareWrite = shareWrite;
\r
2131 f->myVolume = pVolume;
\r
2134 modifiedTime[0] = obj->win_mtime[0];
\r
2135 modifiedTime[1] = obj->win_mtime[1];
\r
2136 objSize = yaffs_GetObjectFileLength(obj);
\r
2137 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - file size %d\r\n",objSize));
\r
2141 yfsd_PutWinFile(f);
\r
2142 RETAILMSG (MSGSTATE, (L"YAFFS::CreateFile - we have no fsdmgr handle\r\n"));
\r
2147 yfsd_UnlockYAFFS();
\r
2149 if(handle != INVALID_HANDLE_VALUE &&
\r
2151 pVolume->shellFunction)
\r
2153 FILECHANGEINFO fc;
\r
2154 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
2156 fc.cbSize = sizeof(FILECHANGEINFO);
\r
2157 fc.wEventId = SHCNE_CREATE;
\r
2158 fc.uFlags = SHCNF_PATH;
\r
2159 fc.dwItem1 = (DWORD)yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
\r
2161 fc.dwAttributes = mode;
\r
2162 yfsd_U32sToWinFileTime(modifiedTime,&fc.ftModified);
\r
2163 fc.nFileSize = objSize;
\r
2165 pVolume->shellFunction(&fc);
\r
2166 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
2168 yfsd_ShellDirectoryChanged(pVolume,fpn);
\r
2171 if(handle != INVALID_HANDLE_VALUE && (fileCreated || writePermitted))
\r
2173 // Remember the name
\r
2175 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
2178 yfsd_FullPathName(pVolume,fpn,YFSD_FULL_PATH_NAME_SIZE,pwsFileName);
\r
2179 slen = wcslen(fpn);
\r
2180 f->fullName = malloc((slen+1)* sizeof(WCHAR));
\r
2183 wcscpy(f->fullName,fpn);
\r
2193 BOOL yfsd_DoReadFile(
\r
2202 yaffs_Object *obj = NULL;
\r
2211 RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile pcbRead was NULL. naughty.\r\n"));
\r
2214 RETAILMSG (MSGSTATE, (L"YAFFS::DoReadFile %d bytes\r\n",cbRead));
\r
2216 if(!pFile || !pFile->obj)
\r
2218 SetLastError(ERROR_INVALID_HANDLE);
\r
2224 if(yaffs_GetObjectFileLength(obj) > pFile->offset)
\r
2226 maxRead = yaffs_GetObjectFileLength(obj) - pFile->offset;
\r
2233 if(cbRead > maxRead)
\r
2240 nread = yaffs_ReadDataFromFile(obj,pBuffer,pFile->offset,cbRead);
\r
2243 pFile->offset += nread;
\r
2255 *pcbRead = maxRead;
\r
2260 return nread < 0? FALSE : TRUE;
\r
2264 BOOL YFSD_ReadFile(
\r
2269 OVERLAPPED *pOverlapped ) //ignore
\r
2273 RETAILMSG (MSGSTATE, (L"YAFFS::ReadFile\r\n"));
\r
2275 if(!pFile || !pFile->obj)
\r
2277 SetLastError(ERROR_INVALID_HANDLE);
\r
2283 result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
\r
2285 yfsd_UnlockYAFFS();
\r
2290 BOOL YFSD_ReadFileWithSeek(
\r
2295 OVERLAPPED *pOverlapped,
\r
2296 DWORD dwLowOffset,
\r
2297 DWORD dwHighOffset )
\r
2300 DWORD rememberedOffset;
\r
2302 RETAILMSG (MSGSTATE, (L"YAFFS::ReadFileWithSeek %d bytes at %d high %d pcbRead %X\r\n",cbRead,dwLowOffset,dwHighOffset,pcbRead));
\r
2304 // To determine if paging is supported, the kernel calls this with all parameters except pFile
\r
2306 if(!pBuffer && !cbRead && !pcbRead && !pOverlapped && !dwLowOffset && !dwHighOffset)
\r
2308 return TRUE; // paging suppported
\r
2309 //return FALSE; // paging not supported
\r
2312 if(!pFile || !pFile->obj)
\r
2314 SetLastError(ERROR_INVALID_HANDLE);
\r
2320 rememberedOffset = pFile->offset;
\r
2322 pFile->offset = dwLowOffset;
\r
2323 // ignore high offset for now
\r
2325 result = yfsd_DoReadFile(pFile,pBuffer,cbRead,pcbRead);
\r
2327 //pFile->offset = rememberedOffset;
\r
2329 yfsd_UnlockYAFFS();
\r
2337 BOOL yfsd_DoWriteFile(
\r
2341 PDWORD pcbWritten)
\r
2344 yaffs_Object *obj = NULL;
\r
2346 RETAILMSG (MSGSTATE, (L"YAFFS::DoWriteFile size %d\r\n",cbWrite));
\r
2348 if(!pFile || !pFile->obj)
\r
2350 SetLastError(ERROR_INVALID_HANDLE);
\r
2354 if(!pFile->writePermitted)
\r
2357 SetLastError(ERROR_ACCESS_DENIED);
\r
2366 nwritten = yaffs_WriteDataToFile(obj,pBuffer,pFile->offset,cbWrite);
\r
2369 pFile->offset += nwritten;
\r
2370 *pcbWritten = nwritten;
\r
2372 if(nwritten != cbWrite)
\r
2374 SetLastError(ERROR_DISK_FULL);
\r
2378 return nwritten != cbWrite? FALSE : TRUE;
\r
2382 BOOL YFSD_WriteFile(
\r
2386 PDWORD pcbWritten,
\r
2387 OVERLAPPED *pOverlapped )
\r
2392 RETAILMSG (MSGSTATE, (L"YAFFS::WriteFile\r\n"));
\r
2394 result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
\r
2396 yfsd_UnlockYAFFS();
\r
2401 BOOL YFSD_WriteFileWithSeek(
\r
2405 PDWORD pcbWritten,
\r
2406 OVERLAPPED *pOverlapped,
\r
2407 DWORD dwLowOffset,
\r
2408 DWORD dwHighOffset )
\r
2411 DWORD rememberedOffset;
\r
2412 RETAILMSG (MSGSTATE, (L"YAFFS::WriteFileWithSeek %d bytes at %d,%d pcbWritten %X\r\n",cbWrite,dwHighOffset,dwLowOffset,pcbWritten));
\r
2416 if(!pFile || !pFile->obj)
\r
2418 SetLastError(ERROR_INVALID_HANDLE);
\r
2424 rememberedOffset = pFile->offset;
\r
2426 pFile->offset = dwLowOffset;
\r
2427 // ignore high offset for now
\r
2429 result = yfsd_DoWriteFile(pFile,pBuffer,cbWrite,pcbWritten);
\r
2431 //pFile->offset = rememberedOffset;
\r
2433 yfsd_UnlockYAFFS();
\r
2438 DWORD YFSD_SetFilePointer(
\r
2440 LONG lDistanceToMove,
\r
2441 PLONG pDistanceToMoveHigh,
\r
2442 DWORD dwMoveMethod )
\r
2444 // ignore high offset for now
\r
2446 DWORD offset = 0xFFFFFFFF;
\r
2449 int seekNegative = 0;
\r
2452 if(!pFile || !pFile->obj)
\r
2454 SetLastError(ERROR_INVALID_HANDLE);
\r
2461 oldPos = pFile->offset;
\r
2463 if(dwMoveMethod == FILE_BEGIN)
\r
2465 if(lDistanceToMove >= 0)
\r
2467 offset = pFile->offset = lDistanceToMove;
\r
2474 else if(dwMoveMethod == FILE_END)
\r
2476 fileSize = yaffs_GetObjectFileLength(pFile->obj);
\r
2477 if(fileSize >= 0 &&
\r
2478 (fileSize + lDistanceToMove) >= 0)
\r
2480 offset = pFile->offset = fileSize + lDistanceToMove;
\r
2487 else if(dwMoveMethod == FILE_CURRENT)
\r
2489 if(pFile->offset + lDistanceToMove >= 0)
\r
2491 offset = pFile->offset = pFile->offset + lDistanceToMove;
\r
2501 SetLastError(ERROR_NEGATIVE_SEEK);
\r
2505 yfsd_UnlockYAFFS();
\r
2507 RETAILMSG (MSGSTATE, (L"YAFFS::SetFilePtr method %d distance %d high %X oldpos %d newpos %d\r\n",
\r
2508 dwMoveMethod,lDistanceToMove,pDistanceToMoveHigh,oldPos,offset));
\r
2514 DWORD YFSD_GetFileSize(
\r
2516 PDWORD pFileSizeHigh )
\r
2520 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileSize high %X\r\n",pFileSizeHigh));
\r
2523 if(!pFile || !pFile->obj)
\r
2525 SetLastError(ERROR_INVALID_HANDLE);
\r
2531 fileSize = yaffs_GetObjectFileLength(pFile->obj);
\r
2533 yfsd_UnlockYAFFS();
\r
2535 *pFileSizeHigh = 0;
\r
2542 BOOL YFSD_GetFileInformationByHandle(
\r
2544 PBY_HANDLE_FILE_INFORMATION pFileInfo )
\r
2546 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileInfoByHandle\r\n"));
\r
2548 if(!pFile || !pFile->obj || !pFileInfo)
\r
2550 SetLastError(ERROR_INVALID_HANDLE);
\r
2556 pFileInfo->dwFileAttributes = yfsd_GetObjectWinAttributes(pFile->obj);
\r
2557 yfsd_U32sToWinFileTime(pFile->obj->win_ctime,&pFileInfo->ftCreationTime);
\r
2558 yfsd_U32sToWinFileTime(pFile->obj->win_atime,&pFileInfo->ftLastAccessTime);
\r
2559 yfsd_U32sToWinFileTime(pFile->obj->win_mtime,&pFileInfo->ftLastWriteTime);
\r
2560 pFileInfo->dwVolumeSerialNumber = 0; //todo is this OK?
\r
2561 pFileInfo->nFileSizeHigh = 0;
\r
2562 pFileInfo->nFileSizeLow = yaffs_GetObjectFileLength(pFile->obj);
\r
2563 pFileInfo->nNumberOfLinks = 1; // only primary link supported like FAT
\r
2564 pFileInfo->nFileIndexHigh = 0;
\r
2565 pFileInfo->nFileIndexLow = pFile->obj->objectId;
\r
2566 pFileInfo->dwOID = (CEOID)(INVALID_HANDLE_VALUE);
\r
2568 yfsd_UnlockYAFFS();
\r
2573 BOOL YFSD_FlushFileBuffers(PFILE pFile )
\r
2575 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
2576 int nameExists = 0;
\r
2577 yfsd_Volume *vol = NULL;
\r
2578 DWORD attribs = 0;
\r
2579 DWORD objSize = 0;
\r
2583 RETAILMSG (MSGSTATE, (L"YAFFS::FlushFileBuffers\r\n"));
\r
2585 if(!pFile || !pFile->obj)
\r
2587 SetLastError(ERROR_INVALID_HANDLE);
\r
2593 yaffs_FlushFile(pFile->obj,1);
\r
2594 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
\r
2595 objSize = yaffs_GetObjectFileLength(pFile->obj);
\r
2596 mtime[0] = pFile->obj->win_mtime[0];
\r
2597 mtime[1] = pFile->obj->win_mtime[1];
\r
2598 if(pFile->fullName)
\r
2600 wcscpy(fpn,pFile->fullName);
\r
2603 vol = pFile->myVolume;
\r
2605 yfsd_UnlockYAFFS();
\r
2607 if(vol && vol->shellFunction && nameExists)
\r
2609 FILECHANGEINFO fc;
\r
2611 fc.cbSize = sizeof(FILECHANGEINFO);
\r
2612 fc.wEventId = SHCNE_UPDATEITEM;
\r
2613 fc.uFlags = SHCNF_PATH;
\r
2614 fc.dwItem1 = (DWORD)fpn;
\r
2616 fc.dwAttributes = attribs;
\r
2617 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
\r
2618 fc.nFileSize = objSize;
\r
2620 vol->shellFunction(&fc);
\r
2621 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
2622 //yfsd_ShellDirectoryChanged(vol,fpn);
\r
2629 BOOL YFSD_GetFileTime(
\r
2631 FILETIME *pCreation,
\r
2632 FILETIME *pLastAccess,
\r
2633 FILETIME *pLastWrite )
\r
2636 RETAILMSG (MSGSTATE, (L"YAFFS::GetFileTime\r\n"));
\r
2637 if(!pFile || !pFile->obj)
\r
2639 SetLastError(ERROR_INVALID_HANDLE);
\r
2645 if(pCreation) yfsd_U32sToWinFileTime(pFile->obj->win_ctime,pCreation);
\r
2646 if(pLastAccess) yfsd_U32sToWinFileTime(pFile->obj->win_atime,pLastAccess);
\r
2647 if(pLastWrite) yfsd_U32sToWinFileTime(pFile->obj->win_mtime,pLastWrite);
\r
2649 yfsd_UnlockYAFFS();
\r
2654 BOOL YFSD_SetFileTime(
\r
2656 CONST FILETIME *pCreation,
\r
2657 CONST FILETIME *pLastAccess,
\r
2658 CONST FILETIME *pLastWrite )
\r
2660 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
2661 int nameExists = 0;
\r
2662 int result = FALSE;
\r
2663 yfsd_Volume *vol = NULL;
\r
2664 DWORD attribs = 0;
\r
2665 DWORD objSize = 0;
\r
2669 RETAILMSG (MSGSTATE, (L"YAFFS::SetFileTime\r\n"));
\r
2671 if(!pFile || !pFile->obj)
\r
2673 SetLastError(ERROR_INVALID_HANDLE);
\r
2682 yfsd_WinFileTimeToU32s(pCreation,pFile->obj->win_ctime);
\r
2683 pFile->obj->dirty = 1;
\r
2687 yfsd_WinFileTimeToU32s(pLastAccess,pFile->obj->win_atime);
\r
2688 pFile->obj->dirty = 1;
\r
2692 yfsd_WinFileTimeToU32s(pLastWrite,pFile->obj->win_mtime);
\r
2693 pFile->obj->dirty = 1;
\r
2695 if(pCreation || pLastAccess || pLastWrite)
\r
2697 result = yaffs_FlushFile(pFile->obj,0);
\r
2702 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
\r
2703 objSize = yaffs_GetObjectFileLength(pFile->obj);
\r
2704 mtime[0] = pFile->obj->win_mtime[0];
\r
2705 mtime[1] = pFile->obj->win_mtime[1];
\r
2706 if(pFile->fullName)
\r
2708 wcscpy(fpn,pFile->fullName);
\r
2711 vol = pFile->myVolume;
\r
2714 yfsd_UnlockYAFFS();
\r
2716 // Call shell function
\r
2717 if(nameExists && result && vol && vol->shellFunction)
\r
2719 FILECHANGEINFO fc;
\r
2721 fc.cbSize = sizeof(FILECHANGEINFO);
\r
2722 fc.wEventId = SHCNE_UPDATEITEM;
\r
2723 fc.uFlags = SHCNF_PATH;
\r
2724 fc.dwItem1 = (DWORD)fpn;
\r
2726 fc.dwAttributes = attribs;
\r
2727 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
\r
2728 fc.nFileSize = objSize;
\r
2730 vol->shellFunction(&fc);
\r
2731 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
2732 //yfsd_ShellDirectoryChanged(vol,fpn);
\r
2738 BOOL YFSD_SetEndOfFile(
\r
2742 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
2743 int nameExists = 0;
\r
2744 yfsd_Volume *vol = NULL;
\r
2745 DWORD attribs = 0;
\r
2746 DWORD objSize = 0;
\r
2748 static unsigned char zeros[512];
\r
2751 BOOL retVal = FALSE;
\r
2753 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF\r\n"));
\r
2755 if(!pFile || !pFile->obj)
\r
2757 SetLastError(ERROR_INVALID_HANDLE);
\r
2762 result = yaffs_ResizeFile(pFile->obj,pFile->offset);
\r
2764 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF resizing to %d, result %d\r\n",pFile->offset,result));
\r
2766 // Resize only works if we're shortening the file.
\r
2767 // If the result is shorter than the offset, then we need to write zeros....
\r
2769 if(result != pFile->offset)
\r
2771 if(result < pFile->offset)
\r
2774 int nBytes = pFile->offset - result;
\r
2775 int thisWriteSize;
\r
2779 memset(zeros,0,512);
\r
2781 pFile->offset = result;
\r
2782 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF expanding file by %d bytes\r\n",nBytes));
\r
2783 while(nBytes > 0 && ok)
\r
2785 thisWriteSize = (nBytes > 512) ? 512 : nBytes;
\r
2787 ok = yfsd_DoWriteFile(pFile,zeros,thisWriteSize,&written);
\r
2788 if(written != thisWriteSize)
\r
2793 nBytes -= thisWriteSize;
\r
2801 SetLastError(ERROR_ACCESS_DENIED);
\r
2811 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
\r
2812 objSize = yaffs_GetObjectFileLength(pFile->obj);
\r
2813 mtime[0] = pFile->obj->win_mtime[0];
\r
2814 mtime[1] = pFile->obj->win_mtime[1];
\r
2815 if(pFile->fullName)
\r
2817 wcscpy(fpn,pFile->fullName);
\r
2820 vol = pFile->myVolume;
\r
2824 yfsd_UnlockYAFFS();
\r
2826 if(nameExists && retVal && vol && vol->shellFunction)
\r
2828 FILECHANGEINFO fc;
\r
2830 fc.cbSize = sizeof(FILECHANGEINFO);
\r
2831 fc.wEventId = SHCNE_UPDATEITEM;
\r
2832 fc.uFlags = SHCNF_PATH;
\r
2833 fc.dwItem1 = (DWORD)fpn;
\r
2835 fc.dwAttributes = attribs;
\r
2836 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
\r
2837 fc.nFileSize = objSize;
\r
2839 vol->shellFunction(&fc);
\r
2840 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
2841 //yfsd_ShellDirectoryChanged(vol,fpn);
\r
2844 RETAILMSG (MSGSTATE, (L"YAFFS::SetEOF file size %d\r\n",yaffs_GetObjectFileLength(pFile->obj)));
\r
2851 BOOL YFSD_DeviceIoControl(
\r
2853 DWORD dwIoControlCode,
\r
2855 DWORD nInBufSize,
\r
2857 DWORD nOutBufSize,
\r
2858 PDWORD pBytesReturned,
\r
2859 OVERLAPPED *pOverlapped )
\r
2861 RETAILMSG (MSGSTATE, (L"YAFFS::DeviceIoControl\r\n"));
\r
2866 BOOL YFSD_CloseFile( PFILE pFile )
\r
2868 WCHAR fpn[YFSD_FULL_PATH_NAME_SIZE];
\r
2869 int nameExists = 0;
\r
2870 yfsd_Volume *vol = NULL;
\r
2871 DWORD attribs = 0;
\r
2872 DWORD objSize = 0;
\r
2875 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile %X\r\n",pFile));
\r
2881 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null pFile\r\n"));
\r
2887 pFile->obj->inUse--;
\r
2888 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj\r\n"));
\r
2889 yaffs_FlushFile(pFile->obj,1);
\r
2890 attribs = yfsd_GetObjectWinAttributes(pFile->obj);
\r
2891 objSize = yaffs_GetObjectFileLength(pFile->obj);
\r
2892 mtime[0] = pFile->obj->win_mtime[0];
\r
2893 mtime[1] = pFile->obj->win_mtime[1];
\r
2894 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile on obj done, size is %d\r\n",objSize));
\r
2895 if(pFile->fullName)
\r
2897 wcscpy(fpn,pFile->fullName);
\r
2900 vol = pFile->myVolume;
\r
2901 yfsd_PutWinFile(pFile);
\r
2905 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile null obj\r\n"));
\r
2909 yfsd_UnlockYAFFS();
\r
2912 if(nameExists && vol && vol->shellFunction)
\r
2914 FILECHANGEINFO fc;
\r
2916 fc.cbSize = sizeof(FILECHANGEINFO);
\r
2917 fc.wEventId = SHCNE_UPDATEITEM;
\r
2918 fc.uFlags = SHCNF_PATH;
\r
2919 fc.dwItem1 = (DWORD)fpn;
\r
2921 fc.dwAttributes = attribs;
\r
2922 yfsd_U32sToWinFileTime(mtime,&fc.ftModified);
\r
2923 fc.nFileSize = objSize;
\r
2925 vol->shellFunction(&fc);
\r
2926 RETAILMSG (MSGSTATE, (L"YAFFS::shell function called\r\n"));
\r
2927 //yfsd_ShellDirectoryChanged(vol,fpn);
\r
2932 RETAILMSG (MSGSTATE, (L"YAFFS::CloseFile done\r\n"));
\r
2939 BOOL YFSD_CloseVolume(PVOLUME pVolume )
\r
2941 RETAILMSG (MSGSTATE, (L"YAFFS::CloseVolume\r\n"));
\r
2942 yfsd_FlushAllFiles();
\r