~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/libs/xpcom18a4/xpcom/io/nsLocalFileOS2.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
4
 *
 
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/
 
9
 *
 
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
 
13
 * License.
 
14
 *
 
15
 * The Original Code is Mozilla Communicator client code, released
 
16
 * March 31, 1998.
 
17
 *
 
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.
 
22
 *
 
23
 * Contributor(s):
 
24
 *   Henry Sobotka <sobotka@axess.com>
 
25
 *   IBM Corp.
 
26
 *
 
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.
 
38
 *
 
39
 * ***** END LICENSE BLOCK ***** */
 
40
 
 
41
 
 
42
#include "nsCOMPtr.h"
 
43
#include "nsMemory.h"
 
44
 
 
45
#include "nsLocalFile.h"
 
46
#include "nsNativeCharsetUtils.h"
 
47
 
 
48
#include "nsISimpleEnumerator.h"
 
49
#include "nsIComponentManager.h"
 
50
#include "prtypes.h"
 
51
#include "prio.h"
 
52
 
 
53
#include <ctype.h>    // needed for toupper
 
54
#include <string.h>
 
55
 
 
56
#include "nsXPIDLString.h"
 
57
#include "nsReadableUtils.h"
 
58
#include "prproces.h"
 
59
#include "prthread.h"
 
60
 
 
61
 
 
62
static unsigned char* PR_CALLBACK
 
63
_mbschr( const unsigned char* stringToSearch, int charToSearchFor);
 
64
extern unsigned char*
 
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);
 
69
 
 
70
#include <unistd.h>
 
71
#include <io.h>
 
72
 
 
73
 
 
74
static nsresult ConvertOS2Error(int err)
 
75
{
 
76
    nsresult rv;
 
77
    
 
78
    switch (err)
 
79
    {
 
80
        case ERROR_FILE_NOT_FOUND:
 
81
        case ERROR_PATH_NOT_FOUND:
 
82
        case ERROR_INVALID_DRIVE:
 
83
            rv = NS_ERROR_FILE_NOT_FOUND;
 
84
            break;
 
85
        case ERROR_ACCESS_DENIED:
 
86
        case ERROR_NOT_SAME_DEVICE:
 
87
            rv = NS_ERROR_FILE_ACCESS_DENIED;
 
88
            break;
 
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;
 
94
            break;
 
95
        case ERROR_CURRENT_DIRECTORY:
 
96
            rv = NS_ERROR_FILE_DIR_NOT_EMPTY;
 
97
            break;
 
98
        case ERROR_WRITE_PROTECT:
 
99
            rv = NS_ERROR_FILE_READ_ONLY;
 
100
            break;
 
101
        case ERROR_HANDLE_DISK_FULL:
 
102
            rv = NS_ERROR_FILE_TOO_BIG;
 
103
            break;
 
104
        case ERROR_FILE_EXISTS:
 
105
        case ERROR_ALREADY_EXISTS:
 
106
        case ERROR_CANNOT_MAKE:
 
107
            rv = NS_ERROR_FILE_ALREADY_EXISTS;
 
108
            break;
 
109
        case 0:
 
110
            rv = NS_OK;
 
111
        default:    
 
112
            rv = NS_ERROR_FAILURE;
 
113
    }
 
114
    return rv;
 
115
}
 
116
 
 
117
static void
 
118
myLL_L2II(PRInt64 result, PRInt32 *hi, PRInt32 *lo )
 
119
{
 
120
    PRInt64 a64, b64;  // probably could have been done with 
 
121
                       // only one PRInt64, but these are macros, 
 
122
                       // and I am a wimp.
 
123
    
 
124
    // shift the hi word to the low word, then push it into a long.
 
125
    LL_SHR(a64, result, 32);
 
126
    LL_L2I(*hi, a64);
 
127
 
 
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);
 
131
    LL_L2I(*lo, a64);
 
132
}
 
133
 
 
134
 
 
135
class nsDirEnumerator : public nsISimpleEnumerator
 
136
{
 
137
    public:
 
138
 
 
139
        NS_DECL_ISUPPORTS
 
140
 
 
141
        nsDirEnumerator() : mDir(nsnull) 
 
142
        {
 
143
        }
 
144
 
 
145
        nsresult Init(nsILocalFile* parent) 
 
146
        {
 
147
            nsCAutoString filepath;
 
148
            parent->GetNativeTarget(filepath);
 
149
        
 
150
            if (filepath.IsEmpty())
 
151
            {
 
152
                parent->GetNativePath(filepath);
 
153
            }
 
154
            
 
155
            if (filepath.IsEmpty())
 
156
            {
 
157
                return NS_ERROR_UNEXPECTED;
 
158
            }
 
159
 
 
160
            mDir = PR_OpenDir(filepath.get());
 
161
            if (mDir == nsnull)    // not a directory?
 
162
                return NS_ERROR_FAILURE;
 
163
 
 
164
            mParent          = parent;    
 
165
            return NS_OK;
 
166
        }
 
167
 
 
168
        NS_IMETHOD HasMoreElements(PRBool *result) 
 
169
        {
 
170
            nsresult rv;
 
171
            if (mNext == nsnull && mDir) 
 
172
            {
 
173
                PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH);
 
174
                if (entry == nsnull) 
 
175
                {
 
176
                    // end of dir entries
 
177
 
 
178
                    PRStatus status = PR_CloseDir(mDir);
 
179
                    if (status != PR_SUCCESS)
 
180
                        return NS_ERROR_FAILURE;
 
181
                    mDir = nsnull;
 
182
 
 
183
                    *result = PR_FALSE;
 
184
                    return NS_OK;
 
185
                }
 
186
 
 
187
                nsCOMPtr<nsIFile> file;
 
188
                rv = mParent->Clone(getter_AddRefs(file));
 
189
                if (NS_FAILED(rv)) 
 
190
                    return rv;
 
191
                
 
192
                rv = file->AppendNative(nsDependentCString(entry->name));
 
193
                if (NS_FAILED(rv)) 
 
194
                    return rv;
 
195
                
 
196
                // make sure the thing exists.  If it does, try the next one.
 
197
                PRBool exists;
 
198
                rv = file->Exists(&exists);
 
199
                if (NS_FAILED(rv) || !exists) 
 
200
                {
 
201
                    return HasMoreElements(result); 
 
202
                }
 
203
                
 
204
                mNext = do_QueryInterface(file);
 
205
            }
 
206
            *result = mNext != nsnull;
 
207
            return NS_OK;
 
208
        }
 
209
 
 
210
        NS_IMETHOD GetNext(nsISupports **result) 
 
211
        {
 
212
            nsresult rv;
 
213
            PRBool hasMore;
 
214
            rv = HasMoreElements(&hasMore);
 
215
            if (NS_FAILED(rv)) return rv;
 
216
 
 
217
            *result = mNext;        // might return nsnull
 
218
            NS_IF_ADDREF(*result);
 
219
            
 
220
            mNext = nsnull;
 
221
            return NS_OK;
 
222
        }
 
223
 
 
224
    private:
 
225
        ~nsDirEnumerator() 
 
226
        {
 
227
            if (mDir) 
 
228
            {
 
229
                PRStatus status = PR_CloseDir(mDir);
 
230
                NS_ASSERTION(status == PR_SUCCESS, "close failed");
 
231
            }
 
232
        }
 
233
 
 
234
    protected:
 
235
        PRDir*                  mDir;
 
236
        nsCOMPtr<nsILocalFile>  mParent;
 
237
        nsCOMPtr<nsILocalFile>  mNext;
 
238
};
 
239
 
 
240
NS_IMPL_ISUPPORTS1(nsDirEnumerator, nsISimpleEnumerator)
 
241
 
 
242
 
 
243
nsLocalFile::nsLocalFile()
 
244
{
 
245
    MakeDirty();
 
246
}
 
247
 
 
248
nsLocalFile::nsLocalFile(const nsLocalFile& other)
 
249
  : mDirty(other.mDirty)
 
250
  , mWorkingPath(other.mWorkingPath)
 
251
  , mFileInfo64(other.mFileInfo64)
 
252
{
 
253
}
 
254
 
 
255
/* nsISupports interface implementation. */
 
256
NS_IMPL_THREADSAFE_ISUPPORTS2(nsLocalFile, nsILocalFile, nsIFile)
 
257
 
 
258
NS_METHOD
 
259
nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
 
260
{
 
261
    NS_ENSURE_ARG_POINTER(aInstancePtr);
 
262
    NS_ENSURE_NO_AGGREGATION(outer);
 
263
 
 
264
    nsLocalFile* inst = new nsLocalFile();
 
265
    if (inst == NULL)
 
266
        return NS_ERROR_OUT_OF_MEMORY;
 
267
    
 
268
    nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
 
269
    if (NS_FAILED(rv))
 
270
    {
 
271
        delete inst;
 
272
        return rv;
 
273
    }
 
274
    return NS_OK;
 
275
}
 
276
 
 
277
// This function resets any cached information about the file.
 
278
void
 
279
nsLocalFile::MakeDirty()
 
280
{
 
281
    mDirty       = PR_TRUE;
 
282
}
 
283
 
 
284
nsresult
 
285
nsLocalFile::Stat()
 
286
{
 
287
    if (!mDirty)
 
288
        return NS_OK;
 
289
 
 
290
    char temp[4];
 
291
    const char* workingFilePath = mWorkingPath.get();
 
292
    const char* nsprPath = workingFilePath;
 
293
 
 
294
    if (mWorkingPath.Length() == 2 && mWorkingPath.CharAt(1) == ':') {
 
295
        temp[0] = workingFilePath[0];
 
296
        temp[1] = workingFilePath[1];
 
297
        temp[2] = '\\';
 
298
        temp[3] = '\0';
 
299
        nsprPath = temp;
 
300
    }
 
301
 
 
302
    DosError(FERR_DISABLEHARDERR);
 
303
    PRStatus status = PR_GetFileInfo64(nsprPath, &mFileInfo64);
 
304
    DosError(FERR_ENABLEHARDERR);
 
305
    if ( status == PR_SUCCESS )
 
306
        return NS_OK;
 
307
 
 
308
    return NS_ERROR_FILE_NOT_FOUND;
 
309
}
 
310
 
 
311
NS_IMETHODIMP  
 
312
nsLocalFile::Clone(nsIFile **file)
 
313
{
 
314
    // Just copy-construct ourselves
 
315
    *file = new nsLocalFile(*this);
 
316
    if (!*file)
 
317
      return NS_ERROR_OUT_OF_MEMORY;
 
318
 
 
319
    NS_ADDREF(*file);
 
320
    
 
321
    return NS_OK;
 
322
}
 
323
 
 
324
NS_IMETHODIMP  
 
325
nsLocalFile::InitWithNativePath(const nsACString &filePath)
 
326
{
 
327
    MakeDirty();
 
328
 
 
329
    nsACString::const_iterator begin, end;
 
330
    filePath.BeginReading(begin);
 
331
    filePath.EndReading(end);
 
332
 
 
333
    // input string must not be empty
 
334
    if (begin == end)
 
335
        return NS_ERROR_FAILURE;
 
336
 
 
337
    char firstChar = *begin;
 
338
    char secondChar = *(++begin);
 
339
    
 
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.
 
342
    
 
343
    char *path = nsnull;
 
344
    PRInt32 pathLen = 0;
 
345
 
 
346
    if ( ( (secondChar == ':') && !FindCharInReadable('/', begin, end) ) ||  // normal path
 
347
         ( (firstChar == '\\') && (secondChar == '\\') ) )  // network path
 
348
    {
 
349
        // This is a native path
 
350
        path = ToNewCString(filePath);
 
351
        pathLen = filePath.Length();
 
352
    }
 
353
 
 
354
    if (path == nsnull)
 
355
        return NS_ERROR_FILE_UNRECOGNIZED_PATH;
 
356
 
 
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]))
 
360
    {
 
361
        path[len] = '\0';
 
362
        pathLen = len;
 
363
    }
 
364
    
 
365
    mWorkingPath.Adopt(path, pathLen);
 
366
    return NS_OK;
 
367
}
 
368
 
 
369
NS_IMETHODIMP  
 
370
nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
 
371
{
 
372
    nsresult rv = Stat();
 
373
    if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
 
374
        return rv; 
 
375
   
 
376
    *_retval = PR_Open(mWorkingPath.get(), flags, mode);
 
377
    
 
378
    if (*_retval)
 
379
        return NS_OK;
 
380
 
 
381
    return NS_ErrorAccordingToNSPR();
 
382
}
 
383
 
 
384
 
 
385
NS_IMETHODIMP  
 
386
nsLocalFile::OpenANSIFileDesc(const char *mode, FILE * *_retval)
 
387
{
 
388
    nsresult rv = Stat();
 
389
    if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
 
390
        return rv; 
 
391
   
 
392
    *_retval = fopen(mWorkingPath.get(), mode);
 
393
    
 
394
    if (*_retval)
 
395
        return NS_OK;
 
396
 
 
397
    return NS_ERROR_FAILURE;
 
398
}
 
399
 
 
400
 
 
401
 
 
402
NS_IMETHODIMP  
 
403
nsLocalFile::Create(PRUint32 type, PRUint32 attributes)
 
404
 
405
    if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
 
406
        return NS_ERROR_FILE_UNKNOWN_TYPE;
 
407
 
 
408
    nsresult rv = Stat();
 
409
    if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND)
 
410
        return rv;  
 
411
    
 
412
   // create nested directories to target
 
413
    unsigned char* slash = _mbschr((const unsigned char*) mWorkingPath.get(), '\\');
 
414
 
 
415
 
 
416
    if (slash)
 
417
    {
 
418
        // skip the first '\\'
 
419
        ++slash;
 
420
        slash = _mbschr(slash, '\\');
 
421
    
 
422
        while (slash)
 
423
        {
 
424
            *slash = '\0';
 
425
            
 
426
                rv = CreateDirectoryA(NS_CONST_CAST(char*, mWorkingPath.get()), NULL);
 
427
                if (rv) {
 
428
                    rv = ConvertOS2Error(rv);
 
429
                    if (rv != NS_ERROR_FILE_ALREADY_EXISTS) return rv;
 
430
                }
 
431
                *slash = '\\';
 
432
                ++slash;
 
433
                slash = _mbschr(slash, '\\');
 
434
        }
 
435
    }
 
436
 
 
437
    if (type == NORMAL_FILE_TYPE)
 
438
    {
 
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;
 
441
          
 
442
        PR_Close(file);
 
443
        return NS_OK;
 
444
    }
 
445
 
 
446
    if (type == DIRECTORY_TYPE)
 
447
    {
 
448
        rv = CreateDirectoryA(NS_CONST_CAST(char*, mWorkingPath.get()), NULL);
 
449
        if (rv) 
 
450
            return ConvertOS2Error(rv);
 
451
        else 
 
452
            return NS_OK;
 
453
    }
 
454
 
 
455
    return NS_ERROR_FILE_UNKNOWN_TYPE;
 
456
}
 
457
    
 
458
NS_IMETHODIMP  
 
459
nsLocalFile::AppendNative(const nsACString &node)
 
460
{
 
461
    if (node.IsEmpty())
 
462
        return NS_OK;
 
463
 
 
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;
 
468
 
 
469
    return AppendRelativeNativePath(node);
 
470
}
 
471
 
 
472
NS_IMETHODIMP  
 
473
nsLocalFile::AppendRelativeNativePath(const nsACString &node)
 
474
{
 
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))
 
480
    {
 
481
        return NS_ERROR_FILE_UNRECOGNIZED_PATH;
 
482
    }
 
483
    MakeDirty();
 
484
    mWorkingPath.Append(NS_LITERAL_CSTRING("\\") + node);
 
485
    return NS_OK;
 
486
}
 
487
 
 
488
NS_IMETHODIMP
 
489
nsLocalFile::Normalize()
 
490
{
 
491
    return NS_OK;
 
492
}
 
493
 
 
494
NS_IMETHODIMP  
 
495
nsLocalFile::GetNativeLeafName(nsACString &aLeafName)
 
496
{
 
497
    aLeafName.Truncate();
 
498
 
 
499
    const char* temp = mWorkingPath.get();
 
500
    if(temp == nsnull)
 
501
        return NS_ERROR_FILE_UNRECOGNIZED_PATH;
 
502
 
 
503
    const char* leaf = (const char*) _mbsrchr((const unsigned char*) temp, '\\');
 
504
    
 
505
    // if the working path is just a node without any lashes.
 
506
    if (leaf == nsnull)
 
507
        leaf = temp;
 
508
    else
 
509
        leaf++;
 
510
 
 
511
    aLeafName.Assign(leaf);
 
512
    return NS_OK;
 
513
}
 
514
 
 
515
NS_IMETHODIMP  
 
516
nsLocalFile::SetNativeLeafName(const nsACString &aLeafName)
 
517
{
 
518
    MakeDirty();
 
519
    
 
520
    const unsigned char* temp = (const unsigned char*) mWorkingPath.get();
 
521
    if(temp == nsnull)
 
522
        return NS_ERROR_FILE_UNRECOGNIZED_PATH;
 
523
 
 
524
    // cannot use nsCString::RFindChar() due to 0x5c problem
 
525
    PRInt32 offset = (PRInt32) (_mbsrchr(temp, '\\') - temp);
 
526
    if (offset)
 
527
    {
 
528
        mWorkingPath.Truncate(offset+1);
 
529
    }
 
530
    mWorkingPath.Append(aLeafName);
 
531
 
 
532
    return NS_OK;
 
533
}
 
534
 
 
535
 
 
536
NS_IMETHODIMP  
 
537
nsLocalFile::GetNativePath(nsACString &_retval)
 
538
{
 
539
    _retval = mWorkingPath;
 
540
    return NS_OK;
 
541
}
 
542
 
 
543
nsresult
 
544
nsLocalFile::CopySingleFile(nsIFile *sourceFile, nsIFile *destParent, const nsACString &newName, PRBool move)
 
545
{
 
546
    nsresult rv;
 
547
    nsCAutoString filePath;
 
548
 
 
549
    nsCAutoString destPath;
 
550
    destParent->GetNativeTarget(destPath);  
 
551
 
 
552
    destPath.Append("\\");
 
553
 
 
554
    if (newName.IsEmpty())
 
555
    {
 
556
        nsCAutoString aFileName;
 
557
        sourceFile->GetNativeLeafName(aFileName);
 
558
        destPath.Append(aFileName);
 
559
    }
 
560
    else
 
561
    {
 
562
        destPath.Append(newName);
 
563
    }
 
564
           
 
565
    rv = sourceFile->GetNativePath(filePath);
 
566
    
 
567
    if (NS_FAILED(rv))
 
568
        return rv;
 
569
 
 
570
    APIRET rc = NO_ERROR;
 
571
 
 
572
    if( move )
 
573
    {
 
574
        rc = DosMove(filePath.get(), (PSZ)NS_CONST_CAST(char*, destPath.get()));
 
575
    }
 
576
 
 
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
 
581
         */
 
582
        do {
 
583
          rc = DosCopy(filePath.get(), (PSZ)NS_CONST_CAST(char*, destPath.get()), DCPY_EXISTING);
 
584
          if (rc == ERROR_TOO_MANY_OPEN_FILES) {
 
585
              ULONG CurMaxFH = 0;
 
586
              LONG ReqCount = 20;
 
587
              APIRET rc2;
 
588
              rc2 = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
 
589
              if (rc2 != NO_ERROR) {
 
590
                break;
 
591
              }
 
592
          }
 
593
        } while (rc == ERROR_TOO_MANY_OPEN_FILES);
 
594
 
 
595
        /* WSOD2 HACK */
 
596
        if (rc == 65) { // NETWORK_ACCESS_DENIED
 
597
          CHAR         achProgram[CCHMAXPATH];  // buffer for program name, parameters
 
598
          RESULTCODES  rescResults;             // buffer for results of dosexecpgm
 
599
 
 
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';
 
608
          DosExecPgm(NULL, 0,
 
609
                     EXEC_SYNC, achProgram, (PSZ)NULL,
 
610
                     &rescResults, achProgram);
 
611
          rc = 0; // Assume it worked
 
612
 
 
613
        } /* rc == 65 */
 
614
        /* moving the file is supposed to act like a rename, so delete the
 
615
         * original file if we got this far without error
 
616
         */
 
617
        if( move && (rc == NO_ERROR) )
 
618
        {
 
619
          DosDelete( filePath.get() );
 
620
        }
 
621
    } /* !move or ERROR */
 
622
    
 
623
    if (rc)
 
624
        rv = ConvertOS2Error(rc);
 
625
 
 
626
    return rv;
 
627
}
 
628
 
 
629
 
 
630
nsresult
 
631
nsLocalFile::CopyMove(nsIFile *aParentDir, const nsACString &newName, PRBool move)
 
632
{
 
633
    nsCOMPtr<nsIFile> newParentDir = aParentDir;
 
634
 
 
635
    nsresult rv  = Stat();
 
636
    if (NS_FAILED(rv))
 
637
        return rv;
 
638
 
 
639
    if (!newParentDir)
 
640
    {
 
641
        // no parent was specified.  We must rename.
 
642
        
 
643
        if (newName.IsEmpty())
 
644
            return NS_ERROR_INVALID_ARG;
 
645
 
 
646
        rv = GetParent(getter_AddRefs(newParentDir));
 
647
        if (NS_FAILED(rv))
 
648
            return rv;
 
649
    }
 
650
 
 
651
    if (!newParentDir)
 
652
        return NS_ERROR_FILE_DESTINATION_NOT_DIR;
 
653
    
 
654
    // make sure it exists and is a directory.  Create it if not there.
 
655
    PRBool exists;
 
656
    newParentDir->Exists(&exists);
 
657
    if (exists == PR_FALSE)
 
658
    {
 
659
        rv = newParentDir->Create(DIRECTORY_TYPE, 0644);  // TODO, what permissions should we use
 
660
        if (NS_FAILED(rv))
 
661
            return rv;
 
662
    }
 
663
    else
 
664
    {
 
665
        PRBool isDir;
 
666
        newParentDir->IsDirectory(&isDir);
 
667
        if (isDir == PR_FALSE)
 
668
        {
 
669
            return NS_ERROR_FILE_DESTINATION_NOT_DIR;
 
670
        }
 
671
    }
 
672
 
 
673
    // check to see if we are a directory, if so enumerate it.
 
674
 
 
675
    PRBool isDir;
 
676
    IsDirectory(&isDir);
 
677
 
 
678
    if (!isDir)
 
679
    {
 
680
        rv = CopySingleFile(this, newParentDir, newName, move);
 
681
        if (NS_FAILED(rv))
 
682
            return rv;
 
683
    }
 
684
    else
 
685
    {
 
686
        // create a new target destination in the new parentDir;
 
687
        nsCOMPtr<nsIFile> target;
 
688
        rv = newParentDir->Clone(getter_AddRefs(target));
 
689
        
 
690
        if (NS_FAILED(rv)) 
 
691
            return rv;
 
692
        
 
693
        nsCAutoString allocatedNewName;
 
694
        if (newName.IsEmpty())
 
695
        {
 
696
            GetNativeLeafName(allocatedNewName);// this should be the leaf name of the 
 
697
        }
 
698
        else
 
699
        {
 
700
            allocatedNewName = newName;
 
701
        }
 
702
        
 
703
        rv = target->AppendNative(allocatedNewName);
 
704
        if (NS_FAILED(rv)) 
 
705
            return rv;
 
706
 
 
707
        allocatedNewName.Truncate();
 
708
 
 
709
        target->Create(DIRECTORY_TYPE, 0644);  // TODO, what permissions should we use
 
710
        if (NS_FAILED(rv))
 
711
            return rv;
 
712
        
 
713
        nsDirEnumerator* dirEnum = new nsDirEnumerator();
 
714
        if (!dirEnum)
 
715
            return NS_ERROR_OUT_OF_MEMORY;
 
716
        
 
717
        rv = dirEnum->Init(this);
 
718
 
 
719
        nsCOMPtr<nsISimpleEnumerator> iterator = do_QueryInterface(dirEnum);
 
720
 
 
721
        PRBool more;
 
722
        iterator->HasMoreElements(&more);
 
723
        while (more)
 
724
        {
 
725
            nsCOMPtr<nsISupports> item;
 
726
            nsCOMPtr<nsIFile> file;
 
727
            iterator->GetNext(getter_AddRefs(item));
 
728
            file = do_QueryInterface(item);
 
729
            PRBool isDir, isLink;
 
730
            
 
731
            file->IsDirectory(&isDir);
 
732
 
 
733
            if (move)
 
734
            {
 
735
                rv = file->MoveToNative(target, nsCString());
 
736
            }
 
737
            else
 
738
            {   
 
739
                rv = file->CopyToNative(target, nsCString());
 
740
            }
 
741
                    
 
742
            iterator->HasMoreElements(&more);
 
743
        }
 
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.
 
750
        if (move)
 
751
        {
 
752
          rv = Remove(PR_FALSE);
 
753
          NS_ENSURE_SUCCESS(rv,rv);
 
754
        }
 
755
    }
 
756
    
 
757
 
 
758
    // If we moved, we want to adjust this.
 
759
    if (move)
 
760
    {
 
761
        MakeDirty();
 
762
        
 
763
        nsCAutoString newParentPath;
 
764
        newParentDir->GetNativePath(newParentPath);
 
765
        
 
766
        if (newParentPath.IsEmpty())
 
767
            return NS_ERROR_FAILURE;
 
768
 
 
769
        if (newName.IsEmpty())
 
770
        {
 
771
            nsCAutoString aFileName;
 
772
            GetNativeLeafName(aFileName);
 
773
            
 
774
            InitWithNativePath(newParentPath);
 
775
            AppendNative(aFileName); 
 
776
        }
 
777
        else
 
778
        {
 
779
            InitWithNativePath(newParentPath);
 
780
            AppendNative(newName);
 
781
        }
 
782
    }
 
783
        
 
784
    return NS_OK;
 
785
}
 
786
 
 
787
NS_IMETHODIMP  
 
788
nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString &newName)
 
789
{
 
790
    return CopyMove(newParentDir, newName, PR_FALSE);
 
791
}
 
792
 
 
793
NS_IMETHODIMP  
 
794
nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString &newName)
 
795
{
 
796
    return CopyMove(newParentDir, newName, PR_FALSE);
 
797
}
 
798
 
 
799
NS_IMETHODIMP  
 
800
nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString &newName)
 
801
{
 
802
    return CopyMove(newParentDir, newName, PR_TRUE);
 
803
}
 
804
 
 
805
NS_IMETHODIMP  
 
806
nsLocalFile::Load(PRLibrary * *_retval)
 
807
{
 
808
    PRBool isFile;
 
809
    nsresult rv = IsFile(&isFile);
 
810
 
 
811
    if (NS_FAILED(rv))
 
812
        return rv;
 
813
    
 
814
    if (! isFile)
 
815
        return NS_ERROR_FILE_IS_DIRECTORY;
 
816
 
 
817
    *_retval =  PR_LoadLibrary(mWorkingPath.get());
 
818
    
 
819
    if (*_retval)
 
820
        return NS_OK;
 
821
 
 
822
    return NS_ERROR_NULL_POINTER;
 
823
}
 
824
 
 
825
NS_IMETHODIMP  
 
826
nsLocalFile::Remove(PRBool recursive)
 
827
{
 
828
    PRBool isDir;
 
829
    
 
830
    nsresult rv = IsDirectory(&isDir);
 
831
    if (NS_FAILED(rv))
 
832
        return rv;
 
833
 
 
834
    const char *filePath = mWorkingPath.get();
 
835
 
 
836
    if (isDir)
 
837
    {
 
838
        if (recursive)
 
839
        {
 
840
            nsDirEnumerator* dirEnum = new nsDirEnumerator();
 
841
            if (dirEnum == nsnull)
 
842
                return NS_ERROR_OUT_OF_MEMORY;
 
843
        
 
844
            rv = dirEnum->Init(this);
 
845
 
 
846
            nsCOMPtr<nsISimpleEnumerator> iterator = do_QueryInterface(dirEnum);
 
847
        
 
848
            PRBool more;
 
849
            iterator->HasMoreElements(&more);
 
850
            while (more)
 
851
            {
 
852
                nsCOMPtr<nsISupports> item;
 
853
                nsCOMPtr<nsIFile> file;
 
854
                iterator->GetNext(getter_AddRefs(item));
 
855
                file = do_QueryInterface(item);
 
856
    
 
857
                file->Remove(recursive);
 
858
                
 
859
                iterator->HasMoreElements(&more);
 
860
            }
 
861
        }
 
862
        rv = rmdir(filePath) == -1 ? NSRESULT_FOR_ERRNO() : NS_OK;
 
863
    }
 
864
    else
 
865
    {
 
866
        rv = remove(filePath) == -1 ? NSRESULT_FOR_ERRNO() : NS_OK;
 
867
    }
 
868
    
 
869
    MakeDirty();
 
870
    return rv;
 
871
}
 
872
 
 
873
NS_IMETHODIMP  
 
874
nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
 
875
{
 
876
    NS_ENSURE_ARG(aLastModifiedTime);
 
877
    
 
878
    *aLastModifiedTime = 0;
 
879
 
 
880
    nsresult rv = Stat();
 
881
    
 
882
    if (NS_FAILED(rv))
 
883
        return rv;
 
884
    
 
885
    // microseconds -> milliseconds
 
886
    *aLastModifiedTime = mFileInfo64.modifyTime / PR_USEC_PER_MSEC;
 
887
    return NS_OK;
 
888
}
 
889
 
 
890
 
 
891
NS_IMETHODIMP  
 
892
nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTime)
 
893
{
 
894
    return NS_ERROR_NOT_IMPLEMENTED;
 
895
}
 
896
 
 
897
 
 
898
NS_IMETHODIMP  
 
899
nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
 
900
{
 
901
    return nsLocalFile::SetModDate(aLastModifiedTime);
 
902
}
 
903
 
 
904
 
 
905
NS_IMETHODIMP  
 
906
nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTime)
 
907
{
 
908
    return NS_ERROR_NOT_IMPLEMENTED;
 
909
}
 
910
 
 
911
nsresult
 
912
nsLocalFile::SetModDate(PRInt64 aLastModifiedTime)
 
913
{
 
914
    nsresult rv = Stat();
 
915
    
 
916
    if (NS_FAILED(rv))
 
917
        return rv;
 
918
    
 
919
    const char *filePath = mWorkingPath.get();
 
920
    
 
921
    PRExplodedTime pret;
 
922
    FILESTATUS3 pathInfo;
 
923
 
 
924
    rv = DosQueryPathInfo(filePath, 
 
925
                                    FIL_STANDARD,             // Level 1 info
 
926
                                    &pathInfo, 
 
927
                                    sizeof(pathInfo));
 
928
 
 
929
    if (NS_FAILED(rv))
 
930
    {
 
931
       rv = ConvertOS2Error(rv);
 
932
       return rv;
 
933
    }
 
934
    
 
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;
 
940
    else
 
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;
 
949
 
 
950
    rv = DosSetPathInfo(filePath, 
 
951
                                 FIL_STANDARD,             // Level 1 info
 
952
                                 &pathInfo, 
 
953
                                 sizeof(pathInfo),
 
954
                                 0UL);
 
955
                               
 
956
    if (NS_FAILED(rv))
 
957
       return rv;
 
958
 
 
959
    MakeDirty();
 
960
    return rv;
 
961
}
 
962
 
 
963
NS_IMETHODIMP  
 
964
nsLocalFile::GetPermissions(PRUint32 *aPermissions)
 
965
{
 
966
    nsresult rv = Stat();
 
967
    
 
968
    if (NS_FAILED(rv))
 
969
        return rv;
 
970
    
 
971
    const char *filePath = mWorkingPath.get();
 
972
 
 
973
 
 
974
    return NS_OK;
 
975
}
 
976
 
 
977
NS_IMETHODIMP  
 
978
nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
 
979
{
 
980
    return NS_ERROR_NOT_IMPLEMENTED;
 
981
}
 
982
 
 
983
 
 
984
NS_IMETHODIMP  
 
985
nsLocalFile::SetPermissions(PRUint32 aPermissions)
 
986
{
 
987
    nsresult rv = Stat();
 
988
    
 
989
    if (NS_FAILED(rv))
 
990
        return rv;
 
991
    
 
992
    const char *filePath = mWorkingPath.get();
 
993
    if( chmod(filePath, aPermissions) == -1 )
 
994
        return NS_ERROR_FAILURE;
 
995
        
 
996
    return NS_OK;
 
997
}
 
998
 
 
999
NS_IMETHODIMP  
 
1000
nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissions)
 
1001
{
 
1002
    return NS_ERROR_NOT_IMPLEMENTED;
 
1003
}
 
1004
 
 
1005
 
 
1006
NS_IMETHODIMP  
 
1007
nsLocalFile::GetFileSize(PRInt64 *aFileSize)
 
1008
{
 
1009
    NS_ENSURE_ARG(aFileSize);
 
1010
    
 
1011
    *aFileSize = 0;
 
1012
 
 
1013
    nsresult rv = Stat();
 
1014
    
 
1015
    if (NS_FAILED(rv))
 
1016
        return rv;
 
1017
    
 
1018
 
 
1019
    *aFileSize = mFileInfo64.size;
 
1020
    return NS_OK;
 
1021
}
 
1022
 
 
1023
 
 
1024
NS_IMETHODIMP  
 
1025
nsLocalFile::SetFileSize(PRInt64 aFileSize)
 
1026
{
 
1027
 
 
1028
    nsresult rv = Stat();
 
1029
    
 
1030
    if (NS_FAILED(rv))
 
1031
        return rv;
 
1032
    
 
1033
    const char *filePath = mWorkingPath.get();
 
1034
 
 
1035
 
 
1036
    APIRET rc;
 
1037
    HFILE hFile;
 
1038
    ULONG actionTaken;
 
1039
 
 
1040
    rc = DosOpen(filePath,
 
1041
                       &hFile,
 
1042
                       &actionTaken,
 
1043
                       0,                 
 
1044
                       FILE_NORMAL,
 
1045
                       OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
 
1046
                       OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE,
 
1047
                       NULL);
 
1048
 
 
1049
    if (rc != NO_ERROR)
 
1050
    {
 
1051
        MakeDirty();
 
1052
        return NS_ERROR_FAILURE;
 
1053
    }
 
1054
   
 
1055
    // Seek to new, desired end of file
 
1056
    PRInt32 hi, lo;
 
1057
    myLL_L2II(aFileSize, &hi, &lo );
 
1058
 
 
1059
    rc = DosSetFileSize(hFile, lo);
 
1060
    if (rc == NO_ERROR) 
 
1061
       DosClose(hFile);
 
1062
    else
 
1063
       goto error; 
 
1064
 
 
1065
    MakeDirty();
 
1066
    return NS_OK;
 
1067
 
 
1068
 error:
 
1069
    MakeDirty();
 
1070
    DosClose(hFile);
 
1071
    return NS_ERROR_FAILURE;
 
1072
}
 
1073
 
 
1074
NS_IMETHODIMP  
 
1075
nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSize)
 
1076
{
 
1077
    return NS_ERROR_NOT_IMPLEMENTED;
 
1078
}
 
1079
 
 
1080
NS_IMETHODIMP  
 
1081
nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
 
1082
{
 
1083
    NS_ENSURE_ARG(aDiskSpaceAvailable);
 
1084
    
 
1085
    ULONG ulDriveNo = toupper(mWorkingPath.CharAt(0)) + 1 - 'A';
 
1086
    FSALLOCATE fsAllocate;
 
1087
    APIRET rc = DosQueryFSInfo(ulDriveNo,
 
1088
                               FSIL_ALLOC,
 
1089
                               &fsAllocate,
 
1090
                               sizeof(fsAllocate));
 
1091
 
 
1092
    if (rc != NO_ERROR)
 
1093
       return NS_ERROR_FAILURE;
 
1094
 
 
1095
    *aDiskSpaceAvailable = fsAllocate.cUnitAvail;
 
1096
    *aDiskSpaceAvailable *= fsAllocate.cSectorUnit;
 
1097
    *aDiskSpaceAvailable *= fsAllocate.cbSector;
 
1098
 
 
1099
    return NS_OK;
 
1100
}
 
1101
 
 
1102
NS_IMETHODIMP  
 
1103
nsLocalFile::GetParent(nsIFile * *aParent)
 
1104
{
 
1105
    NS_ENSURE_ARG_POINTER(aParent);
 
1106
 
 
1107
    nsCAutoString parentPath(mWorkingPath);
 
1108
 
 
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());
 
1112
    if (offset < 0)
 
1113
        return NS_ERROR_FILE_UNRECOGNIZED_PATH;
 
1114
 
 
1115
    parentPath.Truncate(offset);
 
1116
 
 
1117
    nsCOMPtr<nsILocalFile> localFile;
 
1118
    nsresult rv =  NS_NewNativeLocalFile(parentPath, PR_TRUE, getter_AddRefs(localFile));
 
1119
    
 
1120
    if(NS_SUCCEEDED(rv) && localFile)
 
1121
    {
 
1122
        return CallQueryInterface(localFile, aParent);
 
1123
    }
 
1124
    return rv;
 
1125
}
 
1126
 
 
1127
NS_IMETHODIMP  
 
1128
nsLocalFile::Exists(PRBool *_retval)
 
1129
{
 
1130
    NS_ENSURE_ARG(_retval);
 
1131
 
 
1132
    MakeDirty();
 
1133
    *_retval = NS_SUCCEEDED(Stat());
 
1134
 
 
1135
    return NS_OK;
 
1136
}
 
1137
 
 
1138
NS_IMETHODIMP  
 
1139
nsLocalFile::IsWritable(PRBool *_retval)
 
1140
{
 
1141
    NS_ENSURE_ARG(_retval);
 
1142
    *_retval = PR_FALSE;
 
1143
   
 
1144
    nsresult rv = Stat();
 
1145
    
 
1146
    if (NS_FAILED(rv))
 
1147
        return rv;  
 
1148
    
 
1149
    const char *workingFilePath = mWorkingPath.get();
 
1150
 
 
1151
    APIRET rc;
 
1152
    FILESTATUS3 pathInfo;
 
1153
 
 
1154
    rc = DosQueryPathInfo(workingFilePath, 
 
1155
                                    FIL_STANDARD,             // Level 1 info
 
1156
                                    &pathInfo, 
 
1157
                                    sizeof(pathInfo));
 
1158
                               
 
1159
    if (rc != NO_ERROR) 
 
1160
    {
 
1161
       rc = ConvertOS2Error(rc);
 
1162
       return rc;
 
1163
    }
 
1164
 
 
1165
    *_retval =  !((pathInfo.attrFile & FILE_READONLY)  != 0); 
 
1166
 
 
1167
    return NS_OK;
 
1168
}
 
1169
 
 
1170
NS_IMETHODIMP  
 
1171
nsLocalFile::IsReadable(PRBool *_retval)
 
1172
{
 
1173
    NS_ENSURE_ARG(_retval);
 
1174
    *_retval = PR_FALSE;
 
1175
 
 
1176
    nsresult rv = Stat();
 
1177
    if (NS_FAILED(rv))
 
1178
        return rv;
 
1179
 
 
1180
    *_retval = PR_TRUE;
 
1181
    return NS_OK;
 
1182
}
 
1183
 
 
1184
 
 
1185
NS_IMETHODIMP  
 
1186
nsLocalFile::IsExecutable(PRBool *_retval)
 
1187
{
 
1188
    NS_ENSURE_ARG(_retval);
 
1189
    *_retval = PR_FALSE;
 
1190
 
 
1191
    nsresult rv = Stat();
 
1192
    if (NS_FAILED(rv))
 
1193
        return rv;
 
1194
 
 
1195
    nsCAutoString path;
 
1196
    GetNativeTarget(path);
 
1197
 
 
1198
    const char* leaf = (const char*) _mbsrchr((const unsigned char*) path.get(), '\\');
 
1199
 
 
1200
    if ( (strstr(leaf, ".bat") != nsnull) ||
 
1201
         (strstr(leaf, ".exe") != nsnull) ||
 
1202
         (strstr(leaf, ".cmd") != nsnull) ||
 
1203
         (strstr(leaf, ".com") != nsnull) ) {
 
1204
        *_retval = PR_TRUE;
 
1205
    } else {
 
1206
        *_retval = PR_FALSE;
 
1207
    }
 
1208
    
 
1209
    return NS_OK;
 
1210
}
 
1211
 
 
1212
 
 
1213
NS_IMETHODIMP  
 
1214
nsLocalFile::IsDirectory(PRBool *_retval)
 
1215
{
 
1216
    NS_ENSURE_ARG(_retval);
 
1217
    *_retval = PR_FALSE;
 
1218
 
 
1219
    nsresult rv = Stat();
 
1220
    
 
1221
    if (NS_FAILED(rv))
 
1222
        return rv;
 
1223
 
 
1224
    *_retval = (mFileInfo64.type == PR_FILE_DIRECTORY); 
 
1225
 
 
1226
    return NS_OK;
 
1227
}
 
1228
 
 
1229
NS_IMETHODIMP  
 
1230
nsLocalFile::IsFile(PRBool *_retval)
 
1231
{
 
1232
    NS_ENSURE_ARG(_retval);
 
1233
    *_retval = PR_FALSE;
 
1234
 
 
1235
    nsresult rv = Stat();
 
1236
    
 
1237
    if (NS_FAILED(rv))
 
1238
        return rv;
 
1239
 
 
1240
    *_retval = (mFileInfo64.type == PR_FILE_FILE); 
 
1241
    return rv;
 
1242
}
 
1243
 
 
1244
NS_IMETHODIMP  
 
1245
nsLocalFile::IsHidden(PRBool *_retval)
 
1246
{
 
1247
    NS_ENSURE_ARG(_retval);
 
1248
    *_retval = PR_FALSE;
 
1249
 
 
1250
    nsresult rv = Stat();
 
1251
    
 
1252
    if (NS_FAILED(rv))
 
1253
        return rv;
 
1254
    
 
1255
    const char *workingFilePath = mWorkingPath.get();
 
1256
 
 
1257
    APIRET rc;
 
1258
    FILESTATUS3 pathInfo;
 
1259
 
 
1260
    rc = DosQueryPathInfo(workingFilePath, 
 
1261
                                    FIL_STANDARD,             // Level 1 info
 
1262
                                    &pathInfo, 
 
1263
                                    sizeof(pathInfo));
 
1264
                               
 
1265
    if (rc != NO_ERROR) 
 
1266
    {
 
1267
       rc = ConvertOS2Error(rc);
 
1268
       return rc;
 
1269
    }
 
1270
 
 
1271
    *_retval =  ((pathInfo.attrFile & FILE_HIDDEN)  != 0); 
 
1272
    
 
1273
    return NS_OK;
 
1274
}
 
1275
 
 
1276
 
 
1277
NS_IMETHODIMP  
 
1278
nsLocalFile::IsSymlink(PRBool *_retval)
 
1279
{
 
1280
    NS_ENSURE_ARG_POINTER(_retval);
 
1281
    // No Symlinks on OS/2
 
1282
    *_retval = PR_FALSE;
 
1283
 
 
1284
    return NS_OK;
 
1285
}
 
1286
 
 
1287
NS_IMETHODIMP  
 
1288
nsLocalFile::IsSpecial(PRBool *_retval)
 
1289
{
 
1290
    NS_ENSURE_ARG(_retval);
 
1291
    *_retval = PR_FALSE;
 
1292
 
 
1293
    nsresult rv = Stat();
 
1294
    
 
1295
    if (NS_FAILED(rv))
 
1296
        return rv;
 
1297
    
 
1298
    const char *workingFilePath = mWorkingPath.get();
 
1299
 
 
1300
    APIRET rc;
 
1301
    FILESTATUS3 pathInfo;
 
1302
 
 
1303
    rc = DosQueryPathInfo(workingFilePath, 
 
1304
                                    FIL_STANDARD,             // Level 1 info
 
1305
                                    &pathInfo, 
 
1306
                                    sizeof(pathInfo));
 
1307
                               
 
1308
    if (rc != NO_ERROR) 
 
1309
    {
 
1310
       rc = ConvertOS2Error(rc);
 
1311
       return rc;
 
1312
    } 
 
1313
 
 
1314
    *_retval =  ((pathInfo.attrFile & FILE_SYSTEM)  != 0); 
 
1315
 
 
1316
    return NS_OK;
 
1317
}
 
1318
 
 
1319
NS_IMETHODIMP
 
1320
nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
 
1321
{
 
1322
    NS_ENSURE_ARG(inFile);
 
1323
    NS_ENSURE_ARG(_retval);
 
1324
    *_retval = PR_FALSE;
 
1325
 
 
1326
    nsCAutoString inFilePath;
 
1327
    inFile->GetNativePath(inFilePath);
 
1328
    
 
1329
    *_retval = inFilePath.Equals(mWorkingPath);
 
1330
    return NS_OK;
 
1331
}
 
1332
 
 
1333
NS_IMETHODIMP
 
1334
nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
 
1335
{
 
1336
    *_retval = PR_FALSE;
 
1337
       
 
1338
    nsCAutoString myFilePath;
 
1339
    if ( NS_FAILED(GetNativeTarget(myFilePath)))
 
1340
        GetNativePath(myFilePath);
 
1341
    
 
1342
    PRInt32 myFilePathLen = myFilePath.Length();
 
1343
    
 
1344
    nsCAutoString inFilePath;
 
1345
    if ( NS_FAILED(inFile->GetNativeTarget(inFilePath)))
 
1346
        inFile->GetNativePath(inFilePath);
 
1347
 
 
1348
    if ( strnicmp( myFilePath.get(), inFilePath.get(), myFilePathLen) == 0)
 
1349
    {
 
1350
        // now make sure that the |inFile|'s path has a trailing
 
1351
        // separator.
 
1352
 
 
1353
        if (inFilePath[myFilePathLen] == '\\')
 
1354
        {
 
1355
            *_retval = PR_TRUE;
 
1356
        }
 
1357
 
 
1358
    }
 
1359
        
 
1360
    return NS_OK;
 
1361
}
 
1362
 
 
1363
NS_IMETHODIMP
 
1364
nsLocalFile::GetNativeTarget(nsACString &_retval)
 
1365
{   
 
1366
    _retval = mWorkingPath;
 
1367
    return NS_OK;
 
1368
}
 
1369
 
 
1370
/* attribute PRBool followLinks; */
 
1371
NS_IMETHODIMP 
 
1372
nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
 
1373
{
 
1374
    *aFollowLinks = PR_TRUE;
 
1375
    return NS_OK;
 
1376
}
 
1377
NS_IMETHODIMP 
 
1378
nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
 
1379
{
 
1380
    return NS_OK;
 
1381
}
 
1382
 
 
1383
NS_IMETHODIMP
 
1384
nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator * *entries)
 
1385
{
 
1386
    nsresult rv;
 
1387
    
 
1388
    *entries = nsnull;
 
1389
 
 
1390
    PRBool isDir;
 
1391
    rv = IsDirectory(&isDir);
 
1392
    if (NS_FAILED(rv)) 
 
1393
        return rv;
 
1394
    if (!isDir)
 
1395
        return NS_ERROR_FILE_NOT_DIRECTORY;
 
1396
 
 
1397
    nsDirEnumerator* dirEnum = new nsDirEnumerator();
 
1398
    if (dirEnum == nsnull)
 
1399
        return NS_ERROR_OUT_OF_MEMORY;
 
1400
    NS_ADDREF(dirEnum);
 
1401
    rv = dirEnum->Init(this);
 
1402
    if (NS_FAILED(rv)) 
 
1403
    {
 
1404
        NS_RELEASE(dirEnum);
 
1405
        return rv;
 
1406
    }
 
1407
    
 
1408
    *entries = dirEnum;
 
1409
    return NS_OK;
 
1410
}
 
1411
 
 
1412
NS_IMETHODIMP
 
1413
nsLocalFile::GetPersistentDescriptor(nsACString &aPersistentDescriptor)
 
1414
{
 
1415
    return GetNativePath(aPersistentDescriptor);
 
1416
}
 
1417
 
 
1418
NS_IMETHODIMP
 
1419
nsLocalFile::SetPersistentDescriptor(const nsACString &aPersistentDescriptor)
 
1420
{
 
1421
   return InitWithNativePath(aPersistentDescriptor);   
 
1422
}
 
1423
 
 
1424
#ifndef OPEN_DEFAULT
 
1425
#define OPEN_DEFAULT       0
 
1426
#define OPEN_CONTENTS      1
 
1427
#endif
 
1428
 
 
1429
 
 
1430
NS_IMETHODIMP
 
1431
nsLocalFile::Reveal()
 
1432
{
 
1433
  PRBool isDirectory = PR_FALSE;
 
1434
  nsCAutoString path;
 
1435
 
 
1436
  IsDirectory(&isDirectory);
 
1437
  if (isDirectory)
 
1438
  {
 
1439
    GetNativePath(path);  
 
1440
  }
 
1441
  else
 
1442
  {
 
1443
    nsCOMPtr<nsIFile> parent;
 
1444
    GetParent(getter_AddRefs(parent));
 
1445
    if (parent)
 
1446
      parent->GetNativePath(path);  
 
1447
  }
 
1448
 
 
1449
  HOBJECT hobject = WinQueryObject(path.get());
 
1450
  WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
 
1451
  WinOpenObject( hobject, OPEN_CONTENTS, TRUE);
 
1452
 
 
1453
  // we don't care if it succeeded or failed.
 
1454
  return NS_OK;
 
1455
}
 
1456
 
 
1457
 
 
1458
NS_IMETHODIMP
 
1459
nsLocalFile::Launch()
 
1460
{
 
1461
  HOBJECT hobject = WinQueryObject(mWorkingPath.get());
 
1462
  WinSetFocus(HWND_DESKTOP, HWND_DESKTOP);
 
1463
  WinOpenObject( hobject, OPEN_DEFAULT, TRUE);
 
1464
 
 
1465
  // we don't care if it succeeded or failed.
 
1466
  return NS_OK;
 
1467
}
 
1468
 
 
1469
nsresult 
 
1470
NS_NewNativeLocalFile(const nsACString &path, PRBool followLinks, nsILocalFile* *result)
 
1471
{
 
1472
    nsLocalFile* file = new nsLocalFile();
 
1473
    if (file == nsnull)
 
1474
        return NS_ERROR_OUT_OF_MEMORY;
 
1475
    NS_ADDREF(file);
 
1476
 
 
1477
    if (!path.IsEmpty()) {
 
1478
        nsresult rv = file->InitWithNativePath(path);
 
1479
        if (NS_FAILED(rv)) {
 
1480
            NS_RELEASE(file);
 
1481
            return rv;
 
1482
        }
 
1483
    }
 
1484
 
 
1485
    *result = file;
 
1486
    return NS_OK;
 
1487
}
 
1488
 
 
1489
// Locates the first occurrence of charToSearchFor in the stringToSearch
 
1490
static unsigned char* PR_CALLBACK
 
1491
_mbschr( const unsigned char* stringToSearch, int charToSearchFor)
 
1492
{
 
1493
   const unsigned char* p = stringToSearch;
 
1494
   do {
 
1495
       if (*p == charToSearchFor)
 
1496
           break;
 
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;
 
1501
}
 
1502
 
 
1503
// Locates last occurence of charToSearchFor in the stringToSearch
 
1504
extern unsigned char*
 
1505
_mbsrchr( const unsigned char* stringToSearch, int charToSearchFor)
 
1506
{
 
1507
   int length = strlen((const char*)stringToSearch);
 
1508
   const unsigned char* p = stringToSearch+length;
 
1509
   do {
 
1510
       if (*p == charToSearchFor)
 
1511
           break;
 
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;
 
1516
}
 
1517
 
 
1518
// Implement equivalent of Win32 CreateDirectoryA
 
1519
static nsresult PR_CALLBACK
 
1520
CreateDirectoryA( PSZ path, PEAOP2 ppEABuf)
 
1521
{
 
1522
   APIRET rc;
 
1523
   nsresult rv;
 
1524
   FILESTATUS3 pathInfo;
 
1525
 
 
1526
   rc = DosCreateDir( path, ppEABuf );  
 
1527
   if (rc != NO_ERROR) { 
 
1528
      rv = ConvertOS2Error(rc);
 
1529
 
 
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
 
1533
                            &pathInfo, 
 
1534
                            sizeof(pathInfo));
 
1535
      if (rc == NO_ERROR) 
 
1536
         rv = ERROR_FILE_EXISTS;
 
1537
   } 
 
1538
   else 
 
1539
      rv = rc; 
 
1540
 
 
1541
   return rv;
 
1542
}
 
1543
 
 
1544
static int isleadbyte(int c)
 
1545
{
 
1546
  static BOOL bDBCSFilled=FALSE;
 
1547
  static BYTE DBCSInfo[12] = { 0 };  /* According to the Control Program Guide&Ref,
 
1548
                                             12 bytes is sufficient */
 
1549
  BYTE *curr;
 
1550
  BOOL retval = FALSE;
 
1551
 
 
1552
  if( !bDBCSFilled ) {
 
1553
    COUNTRYCODE ctrycodeInfo = { 0 };
 
1554
    APIRET rc = NO_ERROR;
 
1555
    ctrycodeInfo.country = 0;     /* Current Country */
 
1556
    ctrycodeInfo.codepage = 0;    /* Current Codepage */
 
1557
 
 
1558
    rc = DosQueryDBCSEnv( sizeof( DBCSInfo ),
 
1559
                          &ctrycodeInfo,
 
1560
                          DBCSInfo );
 
1561
    if( rc != NO_ERROR ) {
 
1562
      /* we had an error, do something? */
 
1563
      return FALSE;
 
1564
    }
 
1565
    bDBCSFilled=TRUE;
 
1566
  }
 
1567
 
 
1568
  curr = DBCSInfo;
 
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) )) {
 
1572
      retval=TRUE;
 
1573
      break;
 
1574
    }
 
1575
    curr+=2;
 
1576
  }
 
1577
 
 
1578
  return retval;
 
1579
}
 
1580
 
 
1581
NS_IMETHODIMP
 
1582
nsLocalFile::InitWithPath(const nsAString &filePath)
 
1583
{
 
1584
    if (filePath.IsEmpty())
 
1585
        return InitWithNativePath(nsCString());
 
1586
 
 
1587
    nsCAutoString tmp;
 
1588
    nsresult rv = NS_CopyUnicodeToNative(filePath, tmp);
 
1589
 
 
1590
    if (NS_SUCCEEDED(rv))
 
1591
        return InitWithNativePath(tmp);
 
1592
 
 
1593
    return rv;
 
1594
}
 
1595
 
 
1596
NS_IMETHODIMP
 
1597
nsLocalFile::Append(const nsAString &node)
 
1598
{
 
1599
    if (node.IsEmpty())
 
1600
        return NS_OK;
 
1601
 
 
1602
    nsCAutoString tmp;
 
1603
    nsresult rv = NS_CopyUnicodeToNative(node, tmp);
 
1604
 
 
1605
    if (NS_SUCCEEDED(rv))
 
1606
        return AppendNative(tmp);
 
1607
 
 
1608
    return rv;
 
1609
}
 
1610
 
 
1611
NS_IMETHODIMP
 
1612
nsLocalFile::AppendRelativePath(const nsAString &node)
 
1613
{
 
1614
    if (node.IsEmpty())
 
1615
        return NS_OK;
 
1616
 
 
1617
    nsCAutoString tmp;
 
1618
    nsresult rv = NS_CopyUnicodeToNative(node, tmp);
 
1619
 
 
1620
    if (NS_SUCCEEDED(rv))
 
1621
        return AppendRelativeNativePath(tmp);
 
1622
 
 
1623
    return rv;
 
1624
}
 
1625
 
 
1626
NS_IMETHODIMP
 
1627
nsLocalFile::GetLeafName(nsAString &aLeafName)
 
1628
{
 
1629
    nsCAutoString tmp;
 
1630
    nsresult rv = GetNativeLeafName(tmp);
 
1631
 
 
1632
    if (NS_SUCCEEDED(rv))
 
1633
        rv = NS_CopyNativeToUnicode(tmp, aLeafName);
 
1634
 
 
1635
    return rv;
 
1636
}
 
1637
 
 
1638
NS_IMETHODIMP
 
1639
nsLocalFile::SetLeafName(const nsAString &aLeafName)
 
1640
{
 
1641
    if (aLeafName.IsEmpty())
 
1642
        return SetNativeLeafName(nsCString());
 
1643
 
 
1644
    nsCAutoString tmp;
 
1645
    nsresult rv = NS_CopyUnicodeToNative(aLeafName, tmp);
 
1646
 
 
1647
    if (NS_SUCCEEDED(rv))
 
1648
        return SetNativeLeafName(tmp);
 
1649
 
 
1650
    return rv;
 
1651
}
 
1652
 
 
1653
NS_IMETHODIMP
 
1654
nsLocalFile::GetPath(nsAString &_retval)
 
1655
{
 
1656
    return NS_CopyNativeToUnicode(mWorkingPath, _retval);
 
1657
}
 
1658
 
 
1659
NS_IMETHODIMP
 
1660
nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString &newName)
 
1661
{
 
1662
    if (newName.IsEmpty())
 
1663
        return CopyToNative(newParentDir, nsCString());
 
1664
 
 
1665
    nsCAutoString tmp;
 
1666
    nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
 
1667
 
 
1668
    if (NS_SUCCEEDED(rv))
 
1669
        return CopyToNative(newParentDir, tmp);
 
1670
 
 
1671
    return rv;
 
1672
}
 
1673
 
 
1674
NS_IMETHODIMP
 
1675
nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString &newName)
 
1676
{
 
1677
    if (newName.IsEmpty())
 
1678
        return CopyToFollowingLinksNative(newParentDir, nsCString());
 
1679
 
 
1680
    nsCAutoString tmp;
 
1681
    nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
 
1682
 
 
1683
    if (NS_SUCCEEDED(rv))
 
1684
        return CopyToFollowingLinksNative(newParentDir, tmp);
 
1685
 
 
1686
    return rv;
 
1687
}
 
1688
 
 
1689
NS_IMETHODIMP
 
1690
nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString &newName)
 
1691
{
 
1692
    if (newName.IsEmpty())
 
1693
        return MoveToNative(newParentDir, nsCString());
 
1694
 
 
1695
    nsCAutoString tmp;
 
1696
    nsresult rv = NS_CopyUnicodeToNative(newName, tmp);
 
1697
 
 
1698
    if (NS_SUCCEEDED(rv))
 
1699
        return MoveToNative(newParentDir, tmp);
 
1700
 
 
1701
    return rv;
 
1702
}
 
1703
 
 
1704
NS_IMETHODIMP
 
1705
nsLocalFile::GetTarget(nsAString &_retval)
 
1706
{
 
1707
    nsCAutoString tmp;
 
1708
    nsresult rv = GetNativeTarget(tmp);
 
1709
 
 
1710
    if (NS_SUCCEEDED(rv))
 
1711
        rv = NS_CopyNativeToUnicode(tmp, _retval);
 
1712
 
 
1713
    return rv;
 
1714
}
 
1715
 
 
1716
nsresult
 
1717
NS_NewLocalFile(const nsAString &path, PRBool followLinks, nsILocalFile* *result)
 
1718
{
 
1719
    nsCAutoString buf;
 
1720
    nsresult rv = NS_CopyUnicodeToNative(path, buf);
 
1721
    if (NS_FAILED(rv)) {
 
1722
        *result = nsnull;
 
1723
        return rv;
 
1724
    }
 
1725
    return NS_NewNativeLocalFile(buf, followLinks, result);
 
1726
}
 
1727
 
 
1728
//----------------------------------------------------------------------------
 
1729
// global init/shutdown
 
1730
//----------------------------------------------------------------------------
 
1731
 
 
1732
void
 
1733
nsLocalFile::GlobalInit()
 
1734
{
 
1735
}
 
1736
 
 
1737
void
 
1738
nsLocalFile::GlobalShutdown()
 
1739
{
 
1740
}