1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 the Netscape Portable Runtime (NSPR).
17
* The Initial Developer of the Original Code is
18
* Netscape Communications Corporation.
19
* Portions created by the Initial Developer are Copyright (C) 1998-2000
20
* the Initial Developer. All Rights Reserved.
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
39
#include <sys/types.h>
42
#include <sys/locking.h>
46
** Sleep this many milliseconds on each I/O operation
47
** to cause an intentional thread switch.
49
#define _PR_MD_WIN16_DELAY 1
53
** PR_MD_RegisterW16StdioCallbacks() -- Register Win16 stdio callback functions
55
** This public function call is unique to Win16.
56
** ... Sigh ... So much for platform independence.
58
** To get stdio to work from a command line executable, the stdio stream
59
** calls must be issued from the .EXE file; calling them from the .DLL
60
** sends the output to the bit-bucket. Therefore, the .EXE wanting to
61
** do stdio to the console window (must be built as a "quickwin" application)
62
** must have the wrapper functions defined in this module statically linked
65
** There appears to be nothing you can do to get stdio to work from a
66
** Win16 GUI application. Oh Well!
69
PRStdinRead _pr_md_read_stdin = 0;
70
PRStdoutWrite _pr_md_write_stdout = 0;
71
PRStderrWrite _pr_md_write_stderr = 0;
74
PR_MD_RegisterW16StdioCallbacks( PRStdinRead inReadf, PRStdoutWrite outWritef, PRStderrWrite errWritef )
76
_pr_md_write_stdout = outWritef;
77
_pr_md_write_stderr = errWritef;
78
_pr_md_read_stdin = inReadf;
81
} /* end PR_MD_RegisterW16StdioCallbacks() */
85
** _PR_MD_OPEN() -- Open a file
87
** Returns: a fileHandle or -1
92
_PR_MD_OPEN(const char *name, PRIntn osflags, int mode)
95
int access = O_BINARY;
100
** Map NSPR open flags to os open flags
102
if (osflags & PR_RDONLY )
104
if (osflags & PR_WRONLY )
106
if (osflags & PR_RDWR )
108
if (osflags & PR_CREATE_FILE )
113
if (osflags & PR_TRUNCATE)
115
if (osflags & PR_APPEND)
123
file = (PRInt32) sopen( name, access, SH_DENYNO, rights );
124
if ( -1 == (PRInt32)file )
126
_PR_MD_MAP_OPEN_ERROR( errno );
128
PR_Sleep( _PR_MD_WIN16_DELAY );
133
** _PR_MD_READ() - Read something
135
** Returns: bytes read or -1
139
_PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
143
if ( (PR_GetDescType(fd) == PR_DESC_FILE) &&
144
( fd->secret->md.osfd == PR_StandardInput ) &&
145
( _pr_md_write_stdout ))
147
rv = (*_pr_md_read_stdin)( buf, len);
151
rv = read( fd->secret->md.osfd, buf, len );
156
_PR_MD_MAP_READ_ERROR( errno );
159
PR_Sleep( _PR_MD_WIN16_DELAY );
164
** _PR_MD_WRITE() - Write something
166
** Returns: bytes written or -1
168
** Note: for file handles 1 and 2 (stdout and stderr)
169
** call the Win16 NSPR stdio callback functions, if they are
174
_PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len)
178
if ( (PR_GetDescType(fd) == PR_DESC_FILE))
180
switch ( fd->secret->md.osfd )
182
case PR_StandardOutput :
183
if ( _pr_md_write_stdout )
184
rv = (*_pr_md_write_stdout)( (void *)buf, len);
186
rv = len; /* fake success */
189
case PR_StandardError :
190
if ( _pr_md_write_stderr )
191
rv = (*_pr_md_write_stderr)( (void *)buf, len);
193
rv = len; /* fake success */
197
rv = write( fd->secret->md.osfd, buf, len );
200
_PR_MD_MAP_WRITE_ERROR( errno );
207
rv = write( fd->secret->md.osfd, buf, len );
210
_PR_MD_MAP_WRITE_ERROR( errno );
214
PR_Sleep( _PR_MD_WIN16_DELAY );
216
} /* --- end _PR_MD_WRITE() --- */
219
** _PR_MD_LSEEK() - Seek to position in a file
221
** Note: 'whence' maps directly to PR_...
227
_PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, int whence)
231
rv = lseek( fd->secret->md.osfd, offset, whence );
234
_PR_MD_MAP_LSEEK_ERROR( errno );
237
PR_Sleep( _PR_MD_WIN16_DELAY );
242
** _PR_MD_LSEEK64() -- Seek to position in file, 64bit offset.
246
_PR_MD_LSEEK64( PRFileDesc *fd, PRInt64 offset, int whence )
250
LL_SHR(test, offset, 32);
251
if (!LL_IS_ZERO(test))
253
PR_SetError(PR_FILE_TOO_BIG_ERROR, 0);
258
rv = _PR_MD_LSEEK(fd, off, whence);
261
} /* end _PR_MD_LSEEK64() */
264
** _PR_MD_FSYNC() - Flush file buffers.
271
_PR_MD_FSYNC(PRFileDesc *fd)
275
rv = (PRInt32) fsync( fd->secret->md.osfd );
278
_PR_MD_MAP_FSYNC_ERROR( errno );
280
PR_Sleep( _PR_MD_WIN16_DELAY );
285
** _PR_MD_CLOSE() - Close an open file handle
292
_PR_MD_CLOSE_FILE(PRInt32 osfd)
296
rv = (PRInt32) close( osfd );
299
_PR_MD_MAP_CLOSE_ERROR( errno );
301
PR_Sleep( _PR_MD_WIN16_DELAY );
303
} /* --- end _MD_CloseFile() --- */
306
/* --- DIR IO ------------------------------------------------------------ */
307
#define GetFileFromDIR(d) (d)->d_entry.cFileName
310
** FlipSlashes() - Make forward slashes ('/') into backslashes
316
void FlipSlashes(char *cp, int len)
320
cp[0] = PR_DIRECTORY_SEPARATOR;
328
** _PR_MD_OPEN_DIR() - Open a Directory.
335
_PR_MD_OPEN_DIR(_MDDir *d, const char *name)
337
d->dir = opendir( name );
339
if ( d->dir == NULL )
341
_PR_MD_MAP_OPENDIR_ERROR( errno );
342
return( PR_FAILURE );
344
PR_Sleep( _PR_MD_WIN16_DELAY );
345
return( PR_SUCCESS );
350
** _PR_MD_READ_DIR() - read next directory entry
355
_PR_MD_READ_DIR(_MDDir *d, PRIntn flags)
362
de = readdir( d->dir );
364
_PR_MD_MAP_READDIR_ERROR( errno);
367
if ((flags & PR_SKIP_DOT) &&
368
(de->d_name[0] == '.') && (de->d_name[1] == 0))
370
if ((flags & PR_SKIP_DOT_DOT) &&
371
(de->d_name[0] == '.') && (de->d_name[1] == '.') &&
372
(de->d_name[2] == 0))
376
PR_Sleep( _PR_MD_WIN16_DELAY );
381
** _PR_MD_CLOSE_DIR() - Close a directory.
386
_PR_MD_CLOSE_DIR(_MDDir *d)
392
rv = closedir( d->dir );
395
_PR_MD_MAP_CLOSEDIR_ERROR( errno );
398
PR_Sleep( _PR_MD_WIN16_DELAY );
404
** _PR_MD_DELETE() - Delete a file.
411
_PR_MD_DELETE(const char *name)
415
rv = (PRInt32) remove( name );
418
_PR_MD_MAP_DELETE_ERROR( errno );
420
PR_Sleep( _PR_MD_WIN16_DELAY );
426
** _PR_MD_STAT() - Get file attributes by filename
433
_PR_MD_STAT(const char *fn, struct stat *info)
437
rv = _stat(fn, (struct _stat *)info);
440
_PR_MD_MAP_STAT_ERROR( errno );
442
PR_Sleep( _PR_MD_WIN16_DELAY );
447
** _PR_MD_GETFILEINFO() - Get file attributes by filename
454
_PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info)
459
if ( (rv = _stat(fn, &sb)) == 0 ) {
461
if (S_IFREG & sb.st_mode)
462
info->type = PR_FILE_FILE ;
463
else if (S_IFDIR & sb.st_mode)
464
info->type = PR_FILE_DIRECTORY;
466
info->type = PR_FILE_OTHER;
467
info->size = sb.st_size;
468
LL_I2L(info->modifyTime, sb.st_mtime);
469
LL_I2L(info->creationTime, sb.st_ctime);
474
_PR_MD_MAP_STAT_ERROR( errno );
476
PR_Sleep( _PR_MD_WIN16_DELAY );
481
_PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info)
485
PRInt32 rv = _PR_MD_GETFILEINFO(fn, &info32);
488
info->type = info32.type;
489
info->modifyTime = info32.modifyTime;
490
info->creationTime = info32.creationTime;
491
LL_I2L(info->size, info32.size);
497
** _PR_MD_GETOPENFILEINFO() - Get file attributes from an open file handle
504
_PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info)
507
PRInt32 rv = PR_SUCCESS;
509
rv = fstat( fd->secret->md.osfd, &statBuf );
512
if (statBuf.st_mode & S_IFREG )
513
info->type = PR_FILE_FILE;
514
else if ( statBuf.st_mode & S_IFDIR )
515
info->type = PR_FILE_DIRECTORY;
517
info->type = PR_FILE_OTHER;
518
info->size = statBuf.st_size;
519
LL_I2L(info->modifyTime, statBuf.st_mtime);
520
LL_I2L(info->creationTime, statBuf.st_ctime);
525
_PR_MD_MAP_FSTAT_ERROR( errno );
527
PR_Sleep( _PR_MD_WIN16_DELAY );
532
_PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info)
536
PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, &info32);
539
info->type = info32.type;
540
info->modifyTime = info32.modifyTime;
541
info->creationTime = info32.creationTime;
542
LL_I2L(info->size, info32.size);
548
** _PR_MD_RENAME() - Rename a file
555
_PR_MD_RENAME(const char *from, const char *to)
559
rv = rename( from, to );
562
_PR_MD_MAP_RENAME_ERROR( errno );
564
PR_Sleep( _PR_MD_WIN16_DELAY );
569
** _PR_MD_ACCESS() - Return file acesss attribute.
576
_PR_MD_ACCESS(const char *name, PRIntn how)
581
if ( how & PR_ACCESS_WRITE_OK )
583
if ( how & PR_ACCESS_READ_OK )
586
rv = (PRInt32) access( name, mode );
589
_PR_MD_MAP_ACCESS_ERROR( errno );
591
PR_Sleep( _PR_MD_WIN16_DELAY );
596
** _PR_MD_MKDIR() - Make a directory
603
_PR_MD_MKDIR(const char *name, PRIntn mode)
610
PR_Sleep( _PR_MD_WIN16_DELAY );
615
_PR_MD_MAP_MKDIR_ERROR( errno );
616
PR_Sleep( _PR_MD_WIN16_DELAY );
622
** _PR_MD_RMDIR() - Delete a directory
629
_PR_MD_RMDIR(const char *name)
633
rv = (PRInt32) rmdir( name );
636
_PR_MD_MAP_RMDIR_ERROR( errno );
638
PR_Sleep( _PR_MD_WIN16_DELAY );
643
** _PR_MD_LOCKFILE() - Lock a file.
645
** The _locking() call locks relative to the current file pointer.
646
** This function is required to lock all of the file, so,
647
** 1. Seek to the beginning of the file, preserving the original position.
648
** 2. Lock the file, pausing if it is locked by someone else, and
650
** 3. Re-position to the original position in the file.
652
** For unlocking, a similar protocol of positioning is required.
656
_PR_MD_LOCKFILE(PRInt32 f)
658
PRInt32 rv = PR_SUCCESS; /* What we return to our caller */
659
long seekOrigin; /* original position in file */
660
PRInt32 rc; /* what the system call returns to us */
663
** Seek to beginning of file, saving original position.
665
seekOrigin = lseek( f, 0l, SEEK_SET );
668
_PR_MD_MAP_LSEEK_ERROR( errno );
669
return( PR_FAILURE );
673
** Attempt to lock the file.
674
** If someone else has it, Sleep-a-while and try again.
676
for( rc = -1; rc != 0; )
678
rc = _locking( f, _LK_NBLCK , 0x7fffffff );
681
if ( errno == EACCES )
688
_PR_MD_MAP_LOCKF_ERROR( errno );
696
** Now that the file is locked, re-position to
697
** the original file position.
700
rc = lseek( f, seekOrigin, SEEK_SET );
703
_PR_MD_MAP_LSEEK_ERROR( errno );
706
PR_Sleep( _PR_MD_WIN16_DELAY );
708
} /* end _PR_MD_LOCKFILE() */
711
** _PR_MD_TLOCKFILE() - Test and Lock file.
713
** The _locking() call locks relative to the current file pointer.
714
** This function is required to lock all of the file, so,
715
** 1. Seek to the beginning of the file, preserving the original position.
716
** 2. Attempt to Lock the file.
717
** If the file is locked by someone else, try NO MORE.
718
** 3. Re-position to the original position in the file.
720
** See the discussion of _PR_MD_LOCKFILE
725
_PR_MD_TLOCKFILE(PRInt32 f)
727
PRInt32 rv = PR_SUCCESS; /* What we return */
728
long seekOrigin; /* original position in file */
729
PRInt32 rc; /* return value from system call */
732
** Seek to beginning of file, saving original position.
734
seekOrigin = lseek( f, 0l, SEEK_SET );
737
_PR_MD_MAP_LSEEK_ERROR( errno );
738
return( PR_FAILURE );
742
** Attempt to lock the file. One ping; one ping only, Vasily.
743
** If someone else has it, Reposition and return failure.
745
rc = _locking( f, _LK_NBLCK , 0x7fffffff );
748
if ( errno != EACCES )
749
_PR_MD_MAP_LOCKF_ERROR( errno );
754
** Now that the file is locked, maybe, re-position to
755
** the original file position.
757
rc = lseek( f, seekOrigin, SEEK_SET );
760
_PR_MD_MAP_LSEEK_ERROR( errno );
764
PR_Sleep( _PR_MD_WIN16_DELAY );
766
} /* end _PR_MD_TLOCKFILE() */
770
** _PR_MD_UNLOCKFILE() - Unlock a file.
772
** See the discussion of _PR_MD_LOCKFILE
776
_PR_MD_UNLOCKFILE(PRInt32 f)
778
PRInt32 rv = PR_SUCCESS; /* What we return */
779
long seekOrigin; /* original position in file */
780
PRInt32 rc; /* return value from system call */
783
** Seek to beginning of file, saving original position.
785
seekOrigin = lseek( f, 0l, SEEK_SET );
788
_PR_MD_MAP_LSEEK_ERROR( errno );
789
return( PR_FAILURE );
795
rc = _locking( f, _LK_UNLCK , 0x7fffffff );
798
_PR_MD_MAP_LOCKF_ERROR( errno );
803
** Now that the file is unlocked, re-position to
804
** the original file position.
806
rc = lseek( f, seekOrigin, SEEK_SET );
809
_PR_MD_MAP_LSEEK_ERROR( errno );
812
PR_Sleep( _PR_MD_WIN16_DELAY );
814
} /* end _PR_MD_UNLOCKFILE() */
817
** PR_Stat() -- Return status on a file
819
** This is a hack! ... See BugSplat: 98516
820
** Basically, this hack takes a name and stat buffer as input.
821
** The input stat buffer is presumed to be a Microsoft stat buffer.
822
** The functions does a Watcom stat() then maps the result to
823
** the MS stat buffer. ...
826
PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf)
829
_MDMSStat *mssb = (_MDMSStat*) buf; /* this is Microsoft's stat buffer */
830
struct stat statBuf; /* this is Watcom's stat buffer */
832
/* First, get Watcom's idea of stat
833
** then reformat it into a Microsoft idea of stat
835
rv = (PRInt32) _stat( name, &statBuf);
838
mssb->st_dev = statBuf.st_dev;
839
mssb->st_ino = statBuf.st_ino; /* not used, really */
840
mssb->st_mode = statBuf.st_mode;
841
mssb->st_nlink = 1; /* always 1, says MS */
842
mssb->st_uid = statBuf.st_uid;
843
mssb->st_gid = statBuf.st_gid;
844
mssb->st_rdev = statBuf.st_rdev; /* please Gh0d! Let these be the same */
845
mssb->st_size = statBuf.st_size;
846
mssb->st_atime = statBuf.st_atime;
847
mssb->st_mtime = statBuf.st_mtime;
848
mssb->st_ctime = statBuf.st_ctime;
851
} /* end PR_Stat() */