1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Mozilla Public License Version
6
* 1.1 (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/MPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is Mozilla Communicator client code, released
18
* The Initial Developer of the Original Code is
19
* Netscape Communications Corporation.
20
* Portions created by the Initial Developer are Copyright (C) 1998-2000
21
* the Initial Developer. All Rights Reserved.
24
* Henry Sobotka <sobotka@axess.com>
27
* Alternatively, the contents of this file may be used under the terms of
28
* either of the GNU General Public License Version 2 or later (the "GPL"),
29
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30
* in which case the provisions of the GPL or the LGPL are applicable instead
31
* of those above. If you wish to allow use of your version of this file only
32
* under the terms of either the GPL or the LGPL, and not to allow others to
33
* use your version of this file under the terms of the MPL, indicate your
34
* decision by deleting the provisions above and replace them with the notice
35
* and other provisions required by the GPL or the LGPL. If you do not delete
36
* the provisions above, a recipient may use your version of this file under
37
* the terms of any one of the MPL, the GPL or the LGPL.
39
* ***** END LICENSE BLOCK ***** */
45
#include "nsLocalFile.h"
46
#include "nsNativeCharsetUtils.h"
48
#include "nsISimpleEnumerator.h"
49
#include "nsIComponentManager.h"
53
#include <ctype.h> // needed for toupper
56
#include "nsXPIDLString.h"
57
#include "nsReadableUtils.h"
62
static unsigned char* PR_CALLBACK
63
_mbschr( const unsigned char* stringToSearch, int charToSearchFor);
65
_mbsrchr( const unsigned char* stringToSearch, int charToSearchFor);
66
static nsresult PR_CALLBACK
67
CreateDirectoryA( PSZ path, PEAOP2 ppEABuf);
68
static int isleadbyte(int c);
74
static nsresult ConvertOS2Error(int err)
80
case ERROR_FILE_NOT_FOUND:
81
case ERROR_PATH_NOT_FOUND:
82
case ERROR_INVALID_DRIVE:
83
rv = NS_ERROR_FILE_NOT_FOUND;
85
case ERROR_ACCESS_DENIED:
86
case ERROR_NOT_SAME_DEVICE:
87
rv = NS_ERROR_FILE_ACCESS_DENIED;
89
case ERROR_NOT_ENOUGH_MEMORY:
90
case ERROR_INVALID_BLOCK:
91
case ERROR_INVALID_HANDLE:
92
case ERROR_ARENA_TRASHED:
93
rv = NS_ERROR_OUT_OF_MEMORY;
95
case ERROR_CURRENT_DIRECTORY:
96
rv = NS_ERROR_FILE_DIR_NOT_EMPTY;
98
case ERROR_WRITE_PROTECT:
99
rv = NS_ERROR_FILE_READ_ONLY;
101
case ERROR_HANDLE_DISK_FULL:
102
rv = NS_ERROR_FILE_TOO_BIG;
104
case ERROR_FILE_EXISTS:
105
case ERROR_ALREADY_EXISTS:
106
case ERROR_CANNOT_MAKE:
107
rv = NS_ERROR_FILE_ALREADY_EXISTS;
112
rv = NS_ERROR_FAILURE;
118
myLL_L2II(PRInt64 result, PRInt32 *hi, PRInt32 *lo )
120
PRInt64 a64, b64; // probably could have been done with
121
// only one PRInt64, but these are macros,
124
// shift the hi word to the low word, then push it into a long.
125
LL_SHR(a64, result, 32);
128
// shift the low word to the hi word first, then shift it back.
129
LL_SHL(b64, result, 32);
130
LL_SHR(a64, b64, 32);
135
class nsDirEnumerator : public nsISimpleEnumerator
141
nsDirEnumerator() : mDir(nsnull)
145
nsresult Init(nsILocalFile* parent)
147
nsCAutoString filepath;
148
parent->GetNativeTarget(filepath);
150
if (filepath.IsEmpty())
152
parent->GetNativePath(filepath);
155
if (filepath.IsEmpty())
157
return NS_ERROR_UNEXPECTED;
160
mDir = PR_OpenDir(filepath.get());
161
if (mDir == nsnull) // not a directory?
162
return NS_ERROR_FAILURE;
168
NS_IMETHOD HasMoreElements(PRBool *result)
171
if (mNext == nsnull && mDir)
173
PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH);
176
// end of dir entries
178
PRStatus status = PR_CloseDir(mDir);
179
if (status != PR_SUCCESS)
180
return NS_ERROR_FAILURE;
187
nsCOMPtr<nsIFile> file;
188
rv = mParent->Clone(getter_AddRefs(file));
192
rv = file->AppendNative(nsDependentCString(entry->name));
196
// make sure the thing exists. If it does, try the next one.
198
rv = file->Exists(&exists);
199
if (NS_FAILED(rv) || !exists)
201
return HasMoreElements(result);
204
mNext = do_QueryInterface(file);
206
*result = mNext != nsnull;
210
NS_IMETHOD GetNext(nsISupports **result)
214
rv = HasMoreElements(&hasMore);
215
if (NS_FAILED(rv)) return rv;
217
*result = mNext; // might return nsnull
218
NS_IF_ADDREF(*result);
229
PRStatus status = PR_CloseDir(mDir);
230
NS_ASSERTION(status == PR_SUCCESS, "close failed");
236
nsCOMPtr<nsILocalFile> mParent;
237
nsCOMPtr<nsILocalFile> mNext;
240
NS_IMPL_ISUPPORTS1(nsDirEnumerator, nsISimpleEnumerator)
243
nsLocalFile::nsLocalFile()
248
nsLocalFile::nsLocalFile(const nsLocalFile& other)
249
: mDirty(other.mDirty)
250
, mWorkingPath(other.mWorkingPath)
251
, mFileInfo64(other.mFileInfo64)
255
/* nsISupports interface implementation. */
256
NS_IMPL_THREADSAFE_ISUPPORTS2(nsLocalFile, nsILocalFile, nsIFile)
259
nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
261
NS_ENSURE_ARG_POINTER(aInstancePtr);
262
NS_ENSURE_NO_AGGREGATION(outer);
264
nsLocalFile* inst = new nsLocalFile();
266
return NS_ERROR_OUT_OF_MEMORY;
268
nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
277
// This function resets any cached information about the file.
279
nsLocalFile::MakeDirty()
291
const char* workingFilePath = mWorkingPath.get();
292
const char* nsprPath = workingFilePath;
294
if (mWorkingPath.Length() == 2 && mWorkingPath.CharAt(1) == ':') {
295
temp[0] = workingFilePath[0];
296
temp[1] = workingFilePath[1];
302
DosError(FERR_DISABLEHARDERR);
303
PRStatus status = PR_GetFileInfo64(nsprPath, &mFileInfo64);
304
DosError(FERR_ENABLEHARDERR);
305
if ( status == PR_SUCCESS )
308
return NS_ERROR_FILE_NOT_FOUND;
312
nsLocalFile::Clone(nsIFile **file)
314
// Just copy-construct ourselves
315
*file = new nsLocalFile(*this);
317
return NS_ERROR_OUT_OF_MEMORY;
325
nsLocalFile::InitWithNativePath(const nsACString &filePath)
329
nsACString::const_iterator begin, end;
330
filePath.BeginReading(begin);
331
filePath.EndReading(end);
333
// input string must not be empty
335
return NS_ERROR_FAILURE;
337
char firstChar = *begin;
338
char secondChar = *(++begin);
340
// just do a sanity check. if it has any forward slashes, it is not a Native path
341
// on windows. Also, it must have a colon at after the first char.
346
if ( ( (secondChar == ':') && !FindCharInReadable('/', begin, end) ) || // normal path
347
( (firstChar == '\\') && (secondChar == '\\') ) ) // network path
349
// This is a native path
350
path = ToNewCString(filePath);
351
pathLen = filePath.Length();
355
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
357
// kill any trailing '\' provided it isn't the second char of DBCS
358
PRInt32 len = pathLen - 1;
359
if (path[len] == '\\' && !::isleadbyte(path[len-1]))
365
mWorkingPath.Adopt(path, pathLen);
370
nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
372
nsresult rv = Stat();
373
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
376
*_retval = PR_Open(mWorkingPath.get(), flags, mode);
381
return NS_ErrorAccordingToNSPR();
386
nsLocalFile::OpenANSIFileDesc(const char *mode, FILE * *_retval)
388
nsresult rv = Stat();
389
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
392
*_retval = fopen(mWorkingPath.get(), mode);
397
return NS_ERROR_FAILURE;
403
nsLocalFile::Create(PRUint32 type, PRUint32 attributes)
405
if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
406
return NS_ERROR_FILE_UNKNOWN_TYPE;
408
nsresult rv = Stat();
409
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
412
// create nested directories to target
413
unsigned char* slash = _mbschr((const unsigned char*) mWorkingPath.get(), '\\');
418
// skip the first '\\'
420
slash = _mbschr(slash, '\\');
426
rv = CreateDirectoryA(NS_CONST_CAST(char*, mWorkingPath.get()), NULL);
428
rv = ConvertOS2Error(rv);
429
if (rv != NS_ERROR_FILE_ALREADY_EXISTS) return rv;
433
slash = _mbschr(slash, '\\');
437
if (type == NORMAL_FILE_TYPE)
439
PRFileDesc* file = PR_Open(mWorkingPath.get(), PR_RDONLY | PR_CREATE_FILE | PR_APPEND | PR_EXCL, attributes);
440
if (!file) return NS_ERROR_FILE_ALREADY_EXISTS;
446
if (type == DIRECTORY_TYPE)
448
rv = CreateDirectoryA(NS_CONST_CAST(char*, mWorkingPath.get()), NULL);
450
return ConvertOS2Error(rv);
455
return NS_ERROR_FILE_UNKNOWN_TYPE;
459
nsLocalFile::AppendNative(const nsACString &node)
464
// Append only one component. Check for subdirs.
465
// XXX can we avoid the PromiseFlatCString call?
466
if (_mbschr((const unsigned char*) PromiseFlatCString(node).get(), '\\') != nsnull)
467
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
469
return AppendRelativeNativePath(node);
473
nsLocalFile::AppendRelativeNativePath(const nsACString &node)
475
// Cannot start with a / or have .. or have / anywhere
476
nsACString::const_iterator begin, end;
477
node.BeginReading(begin);
478
node.EndReading(end);
479
if (node.IsEmpty() || FindCharInReadable('/', begin, end))
481
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
484
mWorkingPath.Append(NS_LITERAL_CSTRING("\\") + node);
489
nsLocalFile::Normalize()
495
nsLocalFile::GetNativeLeafName(nsACString &aLeafName)
497
aLeafName.Truncate();
499
const char* temp = mWorkingPath.get();
501
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
503
const char* leaf = (const char*) _mbsrchr((const unsigned char*) temp, '\\');
505
// if the working path is just a node without any lashes.
511
aLeafName.Assign(leaf);
516
nsLocalFile::SetNativeLeafName(const nsACString &aLeafName)
520
const unsigned char* temp = (const unsigned char*) mWorkingPath.get();
522
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
524
// cannot use nsCString::RFindChar() due to 0x5c problem
525
PRInt32 offset = (PRInt32) (_mbsrchr(temp, '\\') - temp);
528
mWorkingPath.Truncate(offset+1);
530
mWorkingPath.Append(aLeafName);
537
nsLocalFile::GetNativePath(nsACString &_retval)
539
_retval = mWorkingPath;
544
nsLocalFile::CopySingleFile(nsIFile *sourceFile, nsIFile *destParent, const nsACString &newName, PRBool move)
547
nsCAutoString filePath;
549
nsCAutoString destPath;
550
destParent->GetNativeTarget(destPath);
552
destPath.Append("\\");
554
if (newName.IsEmpty())
556
nsCAutoString aFileName;
557
sourceFile->GetNativeLeafName(aFileName);
558
destPath.Append(aFileName);
562
destPath.Append(newName);
565
rv = sourceFile->GetNativePath(filePath);
570
APIRET rc = NO_ERROR;
574
rc = DosMove(filePath.get(), (PSZ)NS_CONST_CAST(char*, destPath.get()));
577
if (!move || rc == ERROR_NOT_SAME_DEVICE || rc == ERROR_ACCESS_DENIED) {
578
/* will get an error if the destination and source files aren't on the
579
* same drive. "MoveFile()" on Windows will go ahead and move the
580
* file without error, so we need to do the same IBM-AKR
583
rc = DosCopy(filePath.get(), (PSZ)NS_CONST_CAST(char*, destPath.get()), DCPY_EXISTING);
584
if (rc == ERROR_TOO_MANY_OPEN_FILES) {
588
rc2 = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
589
if (rc2 != NO_ERROR) {
593
} while (rc == ERROR_TOO_MANY_OPEN_FILES);
596
if (rc == 65) { // NETWORK_ACCESS_DENIED
597
CHAR achProgram[CCHMAXPATH]; // buffer for program name, parameters
598
RESULTCODES rescResults; // buffer for results of dosexecpgm
600
strcpy(achProgram, "CMD.EXE /C ");
601
strcat(achProgram, """COPY ");
602
strcat(achProgram, filePath.get());
603
strcat(achProgram, " ");
604
strcat(achProgram, (PSZ)NS_CONST_CAST(char*, destPath.get()));
605
strcat(achProgram, """");
606
achProgram[strlen(achProgram) + 1] = '\0';
607
achProgram[7] = '\0';
609
EXEC_SYNC, achProgram, (PSZ)NULL,
610
&rescResults, achProgram);
611
rc = 0; // Assume it worked
614
/* moving the file is supposed to act like a rename, so delete the
615
* original file if we got this far without error
617
if( move && (rc == NO_ERROR) )
619
DosDelete( filePath.get() );
621
} /* !move or ERROR */
624
rv = ConvertOS2Error(rc);
631
nsLocalFile::CopyMove(nsIFile *aParentDir, const nsACString &newName, PRBool move)
633
nsCOMPtr<nsIFile> newParentDir = aParentDir;
635
nsresult rv = Stat();
641
// no parent was specified. We must rename.
643
if (newName.IsEmpty())
644
return NS_ERROR_INVALID_ARG;
646
rv = GetParent(getter_AddRefs(newParentDir));
652
return NS_ERROR_FILE_DESTINATION_NOT_DIR;
654
// make sure it exists and is a directory. Create it if not there.
656
newParentDir->Exists(&exists);
657
if (exists == PR_FALSE)
659
rv = newParentDir->Create(DIRECTORY_TYPE, 0644); // TODO, what permissions should we use
666
newParentDir->IsDirectory(&isDir);
667
if (isDir == PR_FALSE)
669
return NS_ERROR_FILE_DESTINATION_NOT_DIR;
673
// check to see if we are a directory, if so enumerate it.
680
rv = CopySingleFile(this, newParentDir, newName, move);
686
// create a new target destination in the new parentDir;
687
nsCOMPtr<nsIFile> target;
688
rv = newParentDir->Clone(getter_AddRefs(target));
693
nsCAutoString allocatedNewName;
694
if (newName.IsEmpty())
696
GetNativeLeafName(allocatedNewName);// this should be the leaf name of the
700
allocatedNewName = newName;
703
rv = target->AppendNative(allocatedNewName);
707
allocatedNewName.Truncate();
709
target->Create(DIRECTORY_TYPE, 0644); // TODO, what permissions should we use
713
nsDirEnumerator* dirEnum = new nsDirEnumerator();
715
return NS_ERROR_OUT_OF_MEMORY;
717
rv = dirEnum->Init(this);
719
nsCOMPtr<nsISimpleEnumerator> iterator = do_QueryInterface(dirEnum);
722
iterator->HasMoreElements(&more);
725
nsCOMPtr<nsISupports> item;
726
nsCOMPtr<nsIFile> file;
727
iterator->GetNext(getter_AddRefs(item));
728
file = do_QueryInterface(item);
729
PRBool isDir, isLink;
731
file->IsDirectory(&isDir);
735
rv = file->MoveToNative(target, nsCString());
739
rv = file->CopyToNative(target, nsCString());
742
iterator->HasMoreElements(&more);
744
// we've finished moving all the children of this directory
745
// in the new directory. so now delete the directory
746
// note, we don't need to do a recursive delete.
747
// MoveTo() is recursive. At this point,
748
// we've already moved the children of the current folder
749
// to the new location. nothing should be left in the folder.
752
rv = Remove(PR_FALSE);
753
NS_ENSURE_SUCCESS(rv,rv);
758
// If we moved, we want to adjust this.
763
nsCAutoString newParentPath;
764
newParentDir->GetNativePath(newParentPath);
766
if (newParentPath.IsEmpty())
767
return NS_ERROR_FAILURE;
769
if (newName.IsEmpty())
771
nsCAutoString aFileName;
772
GetNativeLeafName(aFileName);
774
InitWithNativePath(newParentPath);
775
AppendNative(aFileName);
779
InitWithNativePath(newParentPath);
780
AppendNative(newName);
788
nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString &newName)
790
return CopyMove(newParentDir, newName, PR_FALSE);
794
nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString &newName)
796
return CopyMove(newParentDir, newName, PR_FALSE);
800
nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString &newName)
802
return CopyMove(newParentDir, newName, PR_TRUE);
806
nsLocalFile::Load(PRLibrary * *_retval)
809
nsresult rv = IsFile(&isFile);
815
return NS_ERROR_FILE_IS_DIRECTORY;
817
*_retval = PR_LoadLibrary(mWorkingPath.get());
822
return NS_ERROR_NULL_POINTER;
826
nsLocalFile::Remove(PRBool recursive)
830
nsresult rv = IsDirectory(&isDir);
834
const char *filePath = mWorkingPath.get();
840
nsDirEnumerator* dirEnum = new nsDirEnumerator();
841
if (dirEnum == nsnull)
842
return NS_ERROR_OUT_OF_MEMORY;
844
rv = dirEnum->Init(this);
846
nsCOMPtr<nsISimpleEnumerator> iterator = do_QueryInterface(dirEnum);
849
iterator->HasMoreElements(&more);
852
nsCOMPtr<nsISupports> item;
853
nsCOMPtr<nsIFile> file;
854
iterator->GetNext(getter_AddRefs(item));
855
file = do_QueryInterface(item);
857
file->Remove(recursive);
859
iterator->HasMoreElements(&more);
862
rv = rmdir(filePath) == -1 ? NSRESULT_FOR_ERRNO() : NS_OK;
866
rv = remove(filePath) == -1 ? NSRESULT_FOR_ERRNO() : NS_OK;
874
nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
876
NS_ENSURE_ARG(aLastModifiedTime);
878
*aLastModifiedTime = 0;
880
nsresult rv = Stat();
885
// microseconds -> milliseconds
886
*aLastModifiedTime = mFileInfo64.modifyTime / PR_USEC_PER_MSEC;
892
nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTime)
894
return NS_ERROR_NOT_IMPLEMENTED;
899
nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
901
return nsLocalFile::SetModDate(aLastModifiedTime);
906
nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTime)
908
return NS_ERROR_NOT_IMPLEMENTED;
912
nsLocalFile::SetModDate(PRInt64 aLastModifiedTime)
914
nsresult rv = Stat();
919
const char *filePath = mWorkingPath.get();
922
FILESTATUS3 pathInfo;
924
rv = DosQueryPathInfo(filePath,
925
FIL_STANDARD, // Level 1 info
931
rv = ConvertOS2Error(rv);
935
// PR_ExplodeTime expects usecs...
936
PR_ExplodeTime(aLastModifiedTime * PR_USEC_PER_MSEC, PR_LocalTimeParameters, &pret);
937
/* fdateLastWrite.year is based off of 1980 */
938
if (pret.tm_year >= 1980)
939
pathInfo.fdateLastWrite.year = pret.tm_year-1980;
941
pathInfo.fdateLastWrite.year = pret.tm_year;
942
pathInfo.fdateLastWrite.month = pret.tm_month + 1; // Convert start offset -- Win32: Jan=1; NSPR: Jan=0
943
// ???? OS2TODO st.wDayOfWeek = pret.tm_wday;
944
pathInfo.fdateLastWrite.day = pret.tm_mday;
945
pathInfo.ftimeLastWrite.hours = pret.tm_hour;
946
pathInfo.ftimeLastWrite.minutes = pret.tm_min;
947
pathInfo.ftimeLastWrite.twosecs = pret.tm_sec / 2; // adjust for twosecs?
948
// ??? OS2TODO st.wMilliseconds = pret.tm_usec/1000;
950
rv = DosSetPathInfo(filePath,
951
FIL_STANDARD, // Level 1 info
964
nsLocalFile::GetPermissions(PRUint32 *aPermissions)
966
nsresult rv = Stat();
971
const char *filePath = mWorkingPath.get();
978
nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
980
return NS_ERROR_NOT_IMPLEMENTED;
985
nsLocalFile::SetPermissions(PRUint32 aPermissions)
987
nsresult rv = Stat();
992
const char *filePath = mWorkingPath.get();
993
if( chmod(filePath, aPermissions) == -1 )
994
return NS_ERROR_FAILURE;
1000
nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions)
1002
return NS_ERROR_NOT_IMPLEMENTED;
1007
nsLocalFile::GetFileSize(PRInt64 *aFileSize)
1009
NS_ENSURE_ARG(aFileSize);
1013
nsresult rv = Stat();
1019
*aFileSize = mFileInfo64.size;
1025
nsLocalFile::SetFileSize(PRInt64 aFileSize)
1028
nsresult rv = Stat();
1033
const char *filePath = mWorkingPath.get();
1040
rc = DosOpen(filePath,
1045
OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
1046
OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
1052
return NS_ERROR_FAILURE;
1055
// Seek to new, desired end of file
1057
myLL_L2II(aFileSize, &hi, &lo );
1059
rc = DosSetFileSize(hFile, lo);
1071
return NS_ERROR_FAILURE;
1075
nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize)
1077
return NS_ERROR_NOT_IMPLEMENTED;
1081
nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
1083
NS_ENSURE_ARG(aDiskSpaceAvailable);
1085
ULONG ulDriveNo = toupper(mWorkingPath.CharAt(0)) + 1 - 'A';
1086
FSALLOCATE fsAllocate;
1087
APIRET rc = DosQueryFSInfo(ulDriveNo,
1090
sizeof(fsAllocate));
1093
return NS_ERROR_FAILURE;
1095
*aDiskSpaceAvailable = fsAllocate.cUnitAvail;
1096
*aDiskSpaceAvailable *= fsAllocate.cSectorUnit;
1097
*aDiskSpaceAvailable *= fsAllocate.cbSector;
1103
nsLocalFile::GetParent(nsIFile * *aParent)
1105
NS_ENSURE_ARG_POINTER(aParent);
1107
nsCAutoString parentPath(mWorkingPath);
1109
// cannot use nsCString::RFindChar() due to 0x5c problem
1110
PRInt32 offset = (PRInt32) (_mbsrchr((const unsigned char *) parentPath.get(), '\\')
1111
- (const unsigned char *) parentPath.get());
1113
return NS_ERROR_FILE_UNRECOGNIZED_PATH;
1115
parentPath.Truncate(offset);
1117
nsCOMPtr<nsILocalFile> localFile;
1118
nsresult rv = NS_NewNativeLocalFile(parentPath, PR_TRUE, getter_AddRefs(localFile));
1120
if(NS_SUCCEEDED(rv) && localFile)
1122
return CallQueryInterface(localFile, aParent);
1128
nsLocalFile::Exists(PRBool *_retval)
1130
NS_ENSURE_ARG(_retval);
1133
*_retval = NS_SUCCEEDED(Stat());
1139
nsLocalFile::IsWritable(PRBool *_retval)
1141
NS_ENSURE_ARG(_retval);
1142
*_retval = PR_FALSE;
1144
nsresult rv = Stat();
1149
const char *workingFilePath = mWorkingPath.get();
1152
FILESTATUS3 pathInfo;
1154
rc = DosQueryPathInfo(workingFilePath,
1155
FIL_STANDARD, // Level 1 info
1161
rc = ConvertOS2Error(rc);
1165
*_retval = !((pathInfo.attrFile & FILE_READONLY) != 0);
1171
nsLocalFile::IsReadable(PRBool *_retval)
1173
NS_ENSURE_ARG(_retval);
1174
*_retval = PR_FALSE;
1176
nsresult rv = Stat();
1186
nsLocalFile::IsExecutable(PRBool *_retval)
1188
NS_ENSURE_ARG(_retval);
1189
*_retval = PR_FALSE;
1191
nsresult rv = Stat();
1196
GetNativeTarget(path);
1198
const char* leaf = (const char*) _mbsrchr((const unsigned char*) path.get(), '\\');
1200
if ( (strstr(leaf, ".bat") != nsnull) ||
1201
(strstr(leaf, ".exe") != nsnull) ||
1202
(strstr(leaf, ".cmd") != nsnull) ||
1203
(strstr(leaf, ".com") != nsnull) ) {
1206
*_retval = PR_FALSE;
1214
nsLocalFile::IsDirectory(PRBool *_retval)
1216
NS_ENSURE_ARG(_retval);
1217
*_retval = PR_FALSE;
1219
nsresult rv = Stat();
1224
*_retval = (mFileInfo64.type == PR_FILE_DIRECTORY);
1230
nsLocalFile::IsFile(PRBool *_retval)
1232
NS_ENSURE_ARG(_retval);
1233
*_retval = PR_FALSE;
1235
nsresult rv = Stat();
1240
*_retval = (mFileInfo64.type == PR_FILE_FILE);
1245
nsLocalFile::IsHidden(PRBool *_retval)
1247
NS_ENSURE_ARG(_retval);
1248
*_retval = PR_FALSE;
1250
nsresult rv = Stat();
1255
const char *workingFilePath = mWorkingPath.get();
1258
FILESTATUS3 pathInfo;
1260
rc = DosQueryPathInfo(workingFilePath,
1261
FIL_STANDARD, // Level 1 info
1267
rc = ConvertOS2Error(rc);
1271
*_retval = ((pathInfo.attrFile & FILE_HIDDEN) != 0);
1278
nsLocalFile::IsSymlink(PRBool *_retval)
1280
NS_ENSURE_ARG_POINTER(_retval);
1281
// No Symlinks on OS/2
1282
*_retval = PR_FALSE;
1288
nsLocalFile::IsSpecial(PRBool *_retval)
1290
NS_ENSURE_ARG(_retval);
1291
*_retval = PR_FALSE;
1293
nsresult rv = Stat();
1298
const char *workingFilePath = mWorkingPath.get();
1301
FILESTATUS3 pathInfo;
1303
rc = DosQueryPathInfo(workingFilePath,
1304
FIL_STANDARD, // Level 1 info
1310
rc = ConvertOS2Error(rc);
1314
*_retval = ((pathInfo.attrFile & FILE_SYSTEM) != 0);
1320
nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
1322
NS_ENSURE_ARG(inFile);
1323
NS_ENSURE_ARG(_retval);
1324
*_retval = PR_FALSE;
1326
nsCAutoString inFilePath;
1327
inFile->GetNativePath(inFilePath);
1329
*_retval = inFilePath.Equals(mWorkingPath);
1334
nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
1336
*_retval = PR_FALSE;
1338
nsCAutoString myFilePath;
1339
if ( NS_FAILED(GetNativeTarget(myFilePath)))
1340
GetNativePath(myFilePath);
1342
PRInt32 myFilePathLen = myFilePath.Length();
1344
nsCAutoString inFilePath;
1345
if ( NS_FAILED(inFile->GetNativeTarget(inFilePath)))
1346
inFile->GetNativePath(inFilePath);
1348
if ( strnicmp( myFilePath.get(), inFilePath.get(), myFilePathLen) == 0)
1350
// now make sure that the |inFile|'s path has a trailing
1353
if (inFilePath[myFilePathLen] == '\\')
1364
nsLocalFile::GetNativeTarget(nsACString &_retval)
1366
_retval = mWorkingPath;
1370
/* attribute PRBool followLinks; */
1372
nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
1374
*aFollowLinks = PR_TRUE;
1378
nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
1384
nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator * *entries)
1391
rv = IsDirectory(&isDir);
1395
return NS_ERROR_FILE_NOT_DIRECTORY;
1397
nsDirEnumerator* dirEnum = new nsDirEnumerator();
1398
if (dirEnum == nsnull)
1399
return NS_ERROR_OUT_OF_MEMORY;
1401
rv = dirEnum->Init(this);
1404
NS_RELEASE(dirEnum);
1413
nsLocalFile::GetPersistentDescriptor(nsACString &aPersistentDescriptor)
1415
return GetNativePath(aPersistentDescriptor);
1419
nsLocalFile::SetPersistentDescriptor(const nsACString &aPersistentDescriptor)
1421
return InitWithNativePath(aPersistentDescriptor);
1424
#ifndef OPEN_DEFAULT
1425
#define OPEN_DEFAULT 0
1426
#define OPEN_CONTENTS 1
1431
nsLocalFile::Reveal()
1433
PRBool isDirectory = PR_FALSE;
1436
IsDirectory(&isDirectory);
1439
GetNativePath(path);
1443
nsCOMPtr<nsIFile> parent;
1444
GetParent(getter_AddRefs(parent));
1446
parent->GetNativePath(path);
1449
HOBJECT hobject = WinQueryObject(path.get());
1450
WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
1451
WinOpenObject( hobject, OPEN_CONTENTS, TRUE);
1453
// we don't care if it succeeded or failed.
1459
nsLocalFile::Launch()
1461
HOBJECT hobject = WinQueryObject(mWorkingPath.get());
1462
WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
1463
WinOpenObject( hobject, OPEN_DEFAULT, TRUE);
1465
// we don't care if it succeeded or failed.
1470
NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result)
1472
nsLocalFile* file = new nsLocalFile();
1474
return NS_ERROR_OUT_OF_MEMORY;
1477
if (!path.IsEmpty()) {
1478
nsresult rv = file->InitWithNativePath(path);
1479
if (NS_FAILED(rv)) {
1489
// Locates the first occurrence of charToSearchFor in the stringToSearch
1490
static unsigned char* PR_CALLBACK
1491
_mbschr( const unsigned char* stringToSearch, int charToSearchFor)
1493
const unsigned char* p = stringToSearch;
1495
if (*p == charToSearchFor)
1497
p = (const unsigned char*)WinNextChar(0,0,0,(char*)p);
1498
} while (*p); /* enddo */
1499
// Result is p or NULL
1500
return *p ? (unsigned char*)p : NULL;
1503
// Locates last occurence of charToSearchFor in the stringToSearch
1504
extern unsigned char*
1505
_mbsrchr( const unsigned char* stringToSearch, int charToSearchFor)
1507
int length = strlen((const char*)stringToSearch);
1508
const unsigned char* p = stringToSearch+length;
1510
if (*p == charToSearchFor)
1512
p = (const unsigned char*)WinPrevChar(0,0,0,(char*)stringToSearch,(char*)p);
1513
} while (p > stringToSearch); /* enddo */
1514
// Result is p or NULL
1515
return (*p == charToSearchFor) ? (unsigned char*)p : NULL;
1518
// Implement equivalent of Win32 CreateDirectoryA
1519
static nsresult PR_CALLBACK
1520
CreateDirectoryA( PSZ path, PEAOP2 ppEABuf)
1524
FILESTATUS3 pathInfo;
1526
rc = DosCreateDir( path, ppEABuf );
1527
if (rc != NO_ERROR) {
1528
rv = ConvertOS2Error(rc);
1530
// Check if directory already exists and if so, reflect that in the return value
1531
rc = DosQueryPathInfo(path,
1532
FIL_STANDARD, // Level 1 info
1536
rv = ERROR_FILE_EXISTS;
1544
static int isleadbyte(int c)
1546
static BOOL bDBCSFilled=FALSE;
1547
static BYTE DBCSInfo[12] = { 0 }; /* According to the Control Program Guide&Ref,
1548
12 bytes is sufficient */
1550
BOOL retval = FALSE;
1552
if( !bDBCSFilled ) {
1553
COUNTRYCODE ctrycodeInfo = { 0 };
1554
APIRET rc = NO_ERROR;
1555
ctrycodeInfo.country = 0; /* Current Country */
1556
ctrycodeInfo.codepage = 0; /* Current Codepage */
1558
rc = DosQueryDBCSEnv( sizeof( DBCSInfo ),
1561
if( rc != NO_ERROR ) {
1562
/* we had an error, do something? */
1569
/* DBCSInfo returned by DosQueryDBCSEnv is terminated with two '0' bytes in a row */
1570
while(( *curr != 0 ) && ( *(curr+1) != 0)) {
1571
if(( c >= *curr ) && ( c <= *(curr+1) )) {
1582
nsLocalFile::InitWithPath(const nsAString &filePath)
1584
if (filePath.IsEmpty())
1585
return InitWithNativePath(nsCString());
1588
nsresult rv = NS_CopyUnicodeToNative(filePath, tmp);
1590
if (NS_SUCCEEDED(rv))
1591
return InitWithNativePath(tmp);
1597
nsLocalFile::Append(const nsAString &node)
1603
nsresult rv = NS_CopyUnicodeToNative(node, tmp);
1605
if (NS_SUCCEEDED(rv))
1606
return AppendNative(tmp);
1612
nsLocalFile::AppendRelativePath(const nsAString &node)
1618
nsresult rv = NS_CopyUnicodeToNative(node, tmp);
1620
if (NS_SUCCEEDED(rv))
1621
return AppendRelativeNativePath(tmp);
1627
nsLocalFile::GetLeafName(nsAString &aLeafName)
1630
nsresult rv = GetNativeLeafName(tmp);
1632
if (NS_SUCCEEDED(rv))
1633
rv = NS_CopyNativeToUnicode(tmp, aLeafName);
1639
nsLocalFile::SetLeafName(const nsAString &aLeafName)
1641
if (aLeafName.IsEmpty())
1642
return SetNativeLeafName(nsCString());
1645
nsresult rv = NS_CopyUnicodeToNative(aLeafName, tmp);
1647
if (NS_SUCCEEDED(rv))
1648
return SetNativeLeafName(tmp);
1654
nsLocalFile::GetPath(nsAString &_retval)
1656
return NS_CopyNativeToUnicode(mWorkingPath, _retval);
1660
nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName)
1662
if (newName.IsEmpty())
1663
return CopyToNative(newParentDir, nsCString());
1666
nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
1668
if (NS_SUCCEEDED(rv))
1669
return CopyToNative(newParentDir, tmp);
1675
nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newName)
1677
if (newName.IsEmpty())
1678
return CopyToFollowingLinksNative(newParentDir, nsCString());
1681
nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
1683
if (NS_SUCCEEDED(rv))
1684
return CopyToFollowingLinksNative(newParentDir, tmp);
1690
nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName)
1692
if (newName.IsEmpty())
1693
return MoveToNative(newParentDir, nsCString());
1696
nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
1698
if (NS_SUCCEEDED(rv))
1699
return MoveToNative(newParentDir, tmp);
1705
nsLocalFile::GetTarget(nsAString &_retval)
1708
nsresult rv = GetNativeTarget(tmp);
1710
if (NS_SUCCEEDED(rv))
1711
rv = NS_CopyNativeToUnicode(tmp, _retval);
1717
NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
1720
nsresult rv = NS_CopyUnicodeToNative(path, buf);
1721
if (NS_FAILED(rv)) {
1725
return NS_NewNativeLocalFile(buf, followLinks, result);
1728
//----------------------------------------------------------------------------
1729
// global init/shutdown
1730
//----------------------------------------------------------------------------
1733
nsLocalFile::GlobalInit()
1738
nsLocalFile::GlobalShutdown()