Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* OS2 IO module
7 *
8 * Assumes synchronous I/O.
9 *
10 */
12 #include "primpl.h"
13 #include "prio.h"
14 #include <ctype.h>
15 #include <string.h>
16 #include <limits.h>
17 #include <dirent.h>
18 #include <fcntl.h>
19 #include <io.h>
21 struct _MDLock _pr_ioq_lock;
23 static PRBool isWSEB = PR_FALSE; /* whether we are using an OS/2 kernel that supports large files */
25 typedef APIRET (*DosOpenLType)(PSZ pszFileName, PHFILE pHf, PULONG pulAction,
26 LONGLONG cbFile, ULONG ulAttribute,
27 ULONG fsOpenFlags, ULONG fsOpenMode,
28 PEAOP2 peaop2);
30 typedef APIRET (*DosSetFileLocksLType)(HFILE hFile, PFILELOCKL pflUnlock,
31 PFILELOCKL pflLock, ULONG timeout,
32 ULONG flags);
34 typedef APIRET (*DosSetFilePtrLType)(HFILE hFile, LONGLONG ib, ULONG method,
35 PLONGLONG ibActual);
37 DosOpenLType myDosOpenL;
38 DosSetFileLocksLType myDosSetFileLocksL;
39 DosSetFilePtrLType myDosSetFilePtrL;
41 void
42 _PR_MD_INIT_IO()
43 {
44 APIRET rc;
45 HMODULE module;
47 sock_init();
49 rc = DosLoadModule(NULL, 0, "DOSCALL1", &module);
50 if (rc != NO_ERROR)
51 {
52 return;
53 }
54 rc = DosQueryProcAddr(module, 981, NULL, (PFN*) &myDosOpenL);
55 if (rc != NO_ERROR)
56 {
57 return;
58 }
59 rc = DosQueryProcAddr(module, 986, NULL, (PFN*) &myDosSetFileLocksL);
60 if (rc != NO_ERROR)
61 {
62 return;
63 }
64 rc = DosQueryProcAddr(module, 988, NULL, (PFN*) &myDosSetFilePtrL);
65 if (rc != NO_ERROR)
66 {
67 return;
68 }
69 isWSEB = PR_TRUE;
70 }
72 PRStatus
73 _PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks)
74 {
75 PRInt32 rv;
76 ULONG count;
78 PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ?
79 SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(ticks);
80 rv = DosWaitEventSem(thread->md.blocked_sema, msecs);
81 DosResetEventSem(thread->md.blocked_sema, &count);
82 switch(rv)
83 {
84 case NO_ERROR:
85 return PR_SUCCESS;
86 break;
87 case ERROR_TIMEOUT:
88 _PR_THREAD_LOCK(thread);
89 if (thread->state == _PR_IO_WAIT) {
90 ;
91 } else {
92 if (thread->wait.cvar != NULL) {
93 thread->wait.cvar = NULL;
94 _PR_THREAD_UNLOCK(thread);
95 } else {
96 /* The CVAR was notified just as the timeout
97 * occurred. This led to us being notified twice.
98 * call SemRequest() to clear the semaphore.
99 */
100 _PR_THREAD_UNLOCK(thread);
101 rv = DosWaitEventSem(thread->md.blocked_sema, 0);
102 DosResetEventSem(thread->md.blocked_sema, &count);
103 PR_ASSERT(rv == NO_ERROR);
104 }
105 }
106 return PR_SUCCESS;
107 break;
108 default:
109 break;
110 }
111 return PR_FAILURE;
112 }
113 PRStatus
114 _PR_MD_WAKEUP_WAITER(PRThread *thread)
115 {
116 if ( _PR_IS_NATIVE_THREAD(thread) )
117 {
118 if (DosPostEventSem(thread->md.blocked_sema) != NO_ERROR)
119 return PR_FAILURE;
120 else
121 return PR_SUCCESS;
122 }
123 }
126 /* --- FILE IO ----------------------------------------------------------- */
127 /*
128 * _PR_MD_OPEN() -- Open a file
129 *
130 * returns: a fileHandle
131 *
132 * The NSPR open flags (osflags) are translated into flags for OS/2
133 *
134 * Mode seems to be passed in as a unix style file permissions argument
135 * as in 0666, in the case of opening the logFile.
136 *
137 */
138 PRInt32
139 _PR_MD_OPEN(const char *name, PRIntn osflags, int mode)
140 {
141 HFILE file;
142 PRInt32 access = OPEN_SHARE_DENYNONE;
143 PRInt32 flags = 0L;
144 APIRET rc = 0;
145 PRUword actionTaken;
147 #ifdef MOZ_OS2_HIGH_MEMORY
148 /*
149 * All the pointer arguments (&file, &actionTaken and name) have to be in
150 * low memory for DosOpen to use them.
151 * The following moves name to low memory.
152 */
153 if ((ULONG)name >= 0x20000000)
154 {
155 size_t len = strlen(name) + 1;
156 char *copy = (char *)alloca(len);
157 memcpy(copy, name, len);
158 name = copy;
159 }
160 #endif
162 if (osflags & PR_SYNC) access |= OPEN_FLAGS_WRITE_THROUGH;
164 if (osflags & PR_RDONLY)
165 access |= OPEN_ACCESS_READONLY;
166 else if (osflags & PR_WRONLY)
167 access |= OPEN_ACCESS_WRITEONLY;
168 else if(osflags & PR_RDWR)
169 access |= OPEN_ACCESS_READWRITE;
171 if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL )
172 {
173 flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
174 }
175 else if (osflags & PR_CREATE_FILE)
176 {
177 if (osflags & PR_TRUNCATE)
178 flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
179 else
180 flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
181 }
182 else
183 {
184 if (osflags & PR_TRUNCATE)
185 flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
186 else
187 flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
188 }
190 do {
191 if (isWSEB)
192 {
193 rc = myDosOpenL((char*)name,
194 &file, /* file handle if successful */
195 &actionTaken, /* reason for failure */
196 0, /* initial size of new file */
197 FILE_NORMAL, /* file system attributes */
198 flags, /* Open flags */
199 access, /* Open mode and rights */
200 0); /* OS/2 Extended Attributes */
201 }
202 else
203 {
204 rc = DosOpen((char*)name,
205 &file, /* file handle if successful */
206 &actionTaken, /* reason for failure */
207 0, /* initial size of new file */
208 FILE_NORMAL, /* file system attributes */
209 flags, /* Open flags */
210 access, /* Open mode and rights */
211 0); /* OS/2 Extended Attributes */
212 };
213 if (rc == ERROR_TOO_MANY_OPEN_FILES) {
214 ULONG CurMaxFH = 0;
215 LONG ReqCount = 20;
216 APIRET rc2;
217 rc2 = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
218 if (rc2 != NO_ERROR) {
219 break;
220 }
221 }
222 } while (rc == ERROR_TOO_MANY_OPEN_FILES);
224 if (rc != NO_ERROR) {
225 _PR_MD_MAP_OPEN_ERROR(rc);
226 return -1;
227 }
229 return (PRInt32)file;
230 }
232 PRInt32
233 _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
234 {
235 ULONG bytes;
236 int rv;
238 rv = DosRead((HFILE)fd->secret->md.osfd,
239 (PVOID)buf,
240 len,
241 &bytes);
243 if (rv != NO_ERROR)
244 {
245 /* ERROR_HANDLE_EOF can only be returned by async io */
246 PR_ASSERT(rv != ERROR_HANDLE_EOF);
247 if (rv == ERROR_BROKEN_PIPE)
248 return 0;
249 else {
250 _PR_MD_MAP_READ_ERROR(rv);
251 return -1;
252 }
253 }
254 return (PRInt32)bytes;
255 }
257 PRInt32
258 _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len)
259 {
260 PRInt32 bytes;
261 int rv;
263 rv = DosWrite((HFILE)fd->secret->md.osfd,
264 (PVOID)buf,
265 len,
266 (PULONG)&bytes);
268 if (rv != NO_ERROR)
269 {
270 _PR_MD_MAP_WRITE_ERROR(rv);
271 return -1;
272 }
274 if (len != bytes) {
275 rv = ERROR_DISK_FULL;
276 _PR_MD_MAP_WRITE_ERROR(rv);
277 return -1;
278 }
280 return bytes;
281 } /* --- end _PR_MD_WRITE() --- */
283 PRInt32
284 _PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence)
285 {
286 PRInt32 rv;
287 PRUword newLocation;
289 rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, offset, whence, &newLocation);
291 if (rv != NO_ERROR) {
292 _PR_MD_MAP_LSEEK_ERROR(rv);
293 return -1;
294 } else
295 return newLocation;
296 }
298 PRInt64
299 _PR_MD_LSEEK64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence)
300 {
301 #ifdef NO_LONG_LONG
302 PRInt64 result;
303 PRInt32 rv, low = offset.lo, hi = offset.hi;
304 PRUword newLocation;
306 rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, low, whence, &newLocation);
307 rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, hi, FILE_CURRENT, &newLocation);
309 if (rv != NO_ERROR) {
310 _PR_MD_MAP_LSEEK_ERROR(rv);
311 hi = newLocation = -1;
312 }
314 result.lo = newLocation;
315 result.hi = hi;
316 return result;
318 #else
319 PRInt32 where, rc, lo = (PRInt32)offset, hi = (PRInt32)(offset >> 32);
320 PRUint64 rv;
321 PRUint32 newLocation, uhi;
322 PRUint64 newLocationL;
324 switch (whence)
325 {
326 case PR_SEEK_SET:
327 where = FILE_BEGIN;
328 break;
329 case PR_SEEK_CUR:
330 where = FILE_CURRENT;
331 break;
332 case PR_SEEK_END:
333 where = FILE_END;
334 break;
335 default:
336 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
337 return -1;
338 }
339 if (isWSEB)
340 {
341 rc = myDosSetFilePtrL((HFILE)fd->secret->md.osfd, offset, where, (PLONGLONG)&newLocationL);
342 }
343 else
344 {
345 rc = DosSetFilePtr((HFILE)fd->secret->md.osfd, lo, where, (PULONG)&newLocation);
346 }
348 if (rc != NO_ERROR) {
349 _PR_MD_MAP_LSEEK_ERROR(rc);
350 return -1;
351 }
353 if (isWSEB)
354 {
355 return newLocationL;
356 }
358 uhi = (PRUint32)hi;
359 PR_ASSERT((PRInt32)uhi >= 0);
360 rv = uhi;
361 PR_ASSERT((PRInt64)rv >= 0);
362 rv = (rv << 32);
363 PR_ASSERT((PRInt64)rv >= 0);
364 rv += newLocation;
365 PR_ASSERT((PRInt64)rv >= 0);
366 return (PRInt64)rv;
367 #endif
368 }
370 PRInt32
371 _PR_MD_FSYNC(PRFileDesc *fd)
372 {
373 PRInt32 rc = DosResetBuffer((HFILE)fd->secret->md.osfd);
375 if (rc != NO_ERROR) {
376 if (rc != ERROR_ACCESS_DENIED) {
377 _PR_MD_MAP_FSYNC_ERROR(rc);
378 return -1;
379 }
380 }
381 return 0;
382 }
384 PRInt32
385 _MD_CloseFile(PRInt32 osfd)
386 {
387 PRInt32 rv;
389 rv = DosClose((HFILE)osfd);
390 if (rv != NO_ERROR)
391 _PR_MD_MAP_CLOSE_ERROR(rv);
392 return rv;
393 }
396 /* --- DIR IO ------------------------------------------------------------ */
397 #define GetFileFromDIR(d) (isWSEB?(d)->d_entry.large.achName:(d)->d_entry.small.achName)
398 #define GetFileAttr(d) (isWSEB?(d)->d_entry.large.attrFile:(d)->d_entry.small.attrFile)
400 void FlipSlashes(char *cp, int len)
401 {
402 while (--len >= 0) {
403 if (cp[0] == '/') {
404 cp[0] = PR_DIRECTORY_SEPARATOR;
405 }
406 cp++;
407 }
408 }
410 /*
411 **
412 ** Local implementations of standard Unix RTL functions which are not provided
413 ** by the VAC RTL.
414 **
415 */
417 PRInt32
418 _PR_MD_CLOSE_DIR(_MDDir *d)
419 {
420 PRInt32 rc;
422 if ( d ) {
423 rc = DosFindClose(d->d_hdl);
424 if(rc == NO_ERROR){
425 d->magic = (PRUint32)-1;
426 return PR_SUCCESS;
427 } else {
428 _PR_MD_MAP_CLOSEDIR_ERROR(rc);
429 return PR_FAILURE;
430 }
431 }
432 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
433 return PR_FAILURE;
434 }
437 PRStatus
438 _PR_MD_OPEN_DIR(_MDDir *d, const char *name)
439 {
440 char filename[ CCHMAXPATH ];
441 PRUword numEntries, rc;
443 numEntries = 1;
445 PR_snprintf(filename, CCHMAXPATH, "%s%s%s",
446 name, PR_DIRECTORY_SEPARATOR_STR, "*.*");
447 FlipSlashes( filename, strlen(filename) );
449 d->d_hdl = HDIR_CREATE;
451 if (isWSEB)
452 {
453 rc = DosFindFirst( filename,
454 &d->d_hdl,
455 FILE_DIRECTORY | FILE_HIDDEN,
456 &(d->d_entry.large),
457 sizeof(d->d_entry.large),
458 &numEntries,
459 FIL_STANDARDL);
460 }
461 else
462 {
463 rc = DosFindFirst( filename,
464 &d->d_hdl,
465 FILE_DIRECTORY | FILE_HIDDEN,
466 &(d->d_entry.small),
467 sizeof(d->d_entry.small),
468 &numEntries,
469 FIL_STANDARD);
470 }
471 if ( rc != NO_ERROR ) {
472 _PR_MD_MAP_OPENDIR_ERROR(rc);
473 return PR_FAILURE;
474 }
475 d->firstEntry = PR_TRUE;
476 d->magic = _MD_MAGIC_DIR;
477 return PR_SUCCESS;
478 }
480 char *
481 _PR_MD_READ_DIR(_MDDir *d, PRIntn flags)
482 {
483 PRUword numFiles = 1;
484 BOOL rv;
485 char *fileName;
486 USHORT fileAttr;
488 if ( d ) {
489 while (1) {
490 if (d->firstEntry) {
491 d->firstEntry = PR_FALSE;
492 rv = NO_ERROR;
493 } else {
494 rv = DosFindNext(d->d_hdl,
495 &(d->d_entry),
496 sizeof(d->d_entry),
497 &numFiles);
498 }
499 if (rv != NO_ERROR) {
500 break;
501 }
502 fileName = GetFileFromDIR(d);
503 fileAttr = GetFileAttr(d);
504 if ( (flags & PR_SKIP_DOT) &&
505 (fileName[0] == '.') && (fileName[1] == '\0'))
506 continue;
507 if ( (flags & PR_SKIP_DOT_DOT) &&
508 (fileName[0] == '.') && (fileName[1] == '.') &&
509 (fileName[2] == '\0'))
510 continue;
511 /*
512 * XXX
513 * Is this the correct definition of a hidden file on OS/2?
514 */
515 if ((flags & PR_SKIP_NONE) && (fileAttr & FILE_HIDDEN))
516 return fileName;
517 else if ((flags & PR_SKIP_HIDDEN) && (fileAttr & FILE_HIDDEN))
518 continue;
519 return fileName;
520 }
521 PR_ASSERT(NO_ERROR != rv);
522 _PR_MD_MAP_READDIR_ERROR(rv);
523 return NULL;
524 }
525 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
526 return NULL;
527 }
529 PRInt32
530 _PR_MD_DELETE(const char *name)
531 {
532 PRInt32 rc = DosDelete((char*)name);
533 if(rc == NO_ERROR) {
534 return 0;
535 } else {
536 _PR_MD_MAP_DELETE_ERROR(rc);
537 return -1;
538 }
539 }
541 PRInt32
542 _PR_MD_STAT(const char *fn, struct stat *info)
543 {
544 PRInt32 rv;
545 char filename[CCHMAXPATH];
547 PR_snprintf(filename, CCHMAXPATH, "%s", fn);
548 FlipSlashes(filename, strlen(filename));
550 rv = _stat((char*)filename, info);
551 if (-1 == rv) {
552 /*
553 * Check for MSVC runtime library _stat() bug.
554 * (It's really a bug in FindFirstFile().)
555 * If a pathname ends in a backslash or slash,
556 * e.g., c:\temp\ or c:/temp/, _stat() will fail.
557 * Note: a pathname ending in a slash (e.g., c:/temp/)
558 * can be handled by _stat() on NT but not on Win95.
559 *
560 * We remove the backslash or slash at the end and
561 * try again.
562 *
563 * Not sure if this happens on OS/2 or not,
564 * but it doesn't hurt to be careful.
565 */
567 int len = strlen(fn);
568 if (len > 0 && len <= _MAX_PATH
569 && (fn[len - 1] == '\\' || fn[len - 1] == '/')) {
570 char newfn[_MAX_PATH + 1];
572 strcpy(newfn, fn);
573 newfn[len - 1] = '\0';
574 rv = _stat(newfn, info);
575 }
576 }
578 if (-1 == rv) {
579 _PR_MD_MAP_STAT_ERROR(errno);
580 }
581 return rv;
582 }
584 PRInt32
585 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info)
586 {
587 struct stat sb;
588 PRInt32 rv;
589 PRInt64 s, s2us;
591 if ( (rv = _PR_MD_STAT(fn, &sb)) == 0 ) {
592 if (info) {
593 if (S_IFREG & sb.st_mode)
594 info->type = PR_FILE_FILE ;
595 else if (S_IFDIR & sb.st_mode)
596 info->type = PR_FILE_DIRECTORY;
597 else
598 info->type = PR_FILE_OTHER;
599 info->size = sb.st_size;
600 LL_I2L(s2us, PR_USEC_PER_SEC);
601 LL_I2L(s, sb.st_mtime);
602 LL_MUL(s, s, s2us);
603 info->modifyTime = s;
604 LL_I2L(s, sb.st_ctime);
605 LL_MUL(s, s, s2us);
606 info->creationTime = s;
607 }
608 }
609 return rv;
610 }
612 PRInt32
613 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info)
614 {
615 PRFileInfo info32;
616 PRInt32 rv = _PR_MD_GETFILEINFO(fn, &info32);
617 if (rv != 0)
618 {
619 return rv;
620 }
621 info->type = info32.type;
622 LL_UI2L(info->size,info32.size);
623 info->modifyTime = info32.modifyTime;
624 info->creationTime = info32.creationTime;
626 if (isWSEB)
627 {
628 APIRET rc ;
629 FILESTATUS3L fstatus;
631 rc = DosQueryPathInfo(fn, FIL_STANDARDL, &fstatus, sizeof(fstatus));
633 if (NO_ERROR != rc)
634 {
635 _PR_MD_MAP_OPEN_ERROR(rc);
636 return -1;
637 }
639 if (! (fstatus.attrFile & FILE_DIRECTORY))
640 {
641 info->size = fstatus.cbFile;
642 }
643 }
645 return rv;
646 }
648 PRInt32
649 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info)
650 {
651 /* For once, the VAC compiler/library did a nice thing.
652 * The file handle used by the C runtime is the same one
653 * returned by the OS when you call DosOpen(). This means
654 * that you can take an OS HFILE and use it with C file
655 * functions. The only caveat is that you have to call
656 * _setmode() first to initialize some junk. This is
657 * immensely useful because I did not have a clue how to
658 * implement this function otherwise. The windows folks
659 * took the source from the Microsoft C library source, but
660 * IBM wasn't kind enough to ship the source with VAC.
661 * On second thought, the needed function could probably
662 * be gotten from the OS/2 GNU library source, but the
663 * point is now moot.
664 */
665 struct stat hinfo;
666 PRInt64 s, s2us;
668 _setmode(fd->secret->md.osfd, O_BINARY);
669 if(fstat((int)fd->secret->md.osfd, &hinfo) != NO_ERROR) {
670 _PR_MD_MAP_FSTAT_ERROR(errno);
671 return -1;
672 }
674 if (hinfo.st_mode & S_IFDIR)
675 info->type = PR_FILE_DIRECTORY;
676 else
677 info->type = PR_FILE_FILE;
679 info->size = hinfo.st_size;
680 LL_I2L(s2us, PR_USEC_PER_SEC);
681 LL_I2L(s, hinfo.st_mtime);
682 LL_MUL(s, s, s2us);
683 info->modifyTime = s;
684 LL_I2L(s, hinfo.st_ctime);
685 LL_MUL(s, s, s2us);
686 info->creationTime = s;
688 return 0;
689 }
691 PRInt32
692 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info)
693 {
694 PRFileInfo info32;
695 PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, &info32);
696 if (0 == rv)
697 {
698 info->type = info32.type;
699 LL_UI2L(info->size,info32.size);
701 info->modifyTime = info32.modifyTime;
702 info->creationTime = info32.creationTime;
703 }
705 if (isWSEB)
706 {
707 APIRET rc ;
708 FILESTATUS3L fstatus;
710 rc = DosQueryFileInfo(fd->secret->md.osfd, FIL_STANDARDL, &fstatus, sizeof(fstatus));
712 if (NO_ERROR != rc)
713 {
714 _PR_MD_MAP_OPEN_ERROR(rc);
715 return -1;
716 }
718 if (! (fstatus.attrFile & FILE_DIRECTORY))
719 {
720 info->size = fstatus.cbFile;
721 }
722 }
724 return rv;
725 }
728 PRInt32
729 _PR_MD_RENAME(const char *from, const char *to)
730 {
731 PRInt32 rc;
732 /* Does this work with dot-relative pathnames? */
733 if ( (rc = DosMove((char *)from, (char *)to)) == NO_ERROR) {
734 return 0;
735 } else {
736 _PR_MD_MAP_RENAME_ERROR(rc);
737 return -1;
738 }
739 }
741 PRInt32
742 _PR_MD_ACCESS(const char *name, PRAccessHow how)
743 {
744 PRInt32 rv;
745 switch (how) {
746 case PR_ACCESS_WRITE_OK:
747 rv = access(name, 02);
748 break;
749 case PR_ACCESS_READ_OK:
750 rv = access(name, 04);
751 break;
752 case PR_ACCESS_EXISTS:
753 return access(name, 00);
754 break;
755 default:
756 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
757 return -1;
758 }
759 if (rv < 0)
760 _PR_MD_MAP_ACCESS_ERROR(errno);
761 return rv;
762 }
764 PRInt32
765 _PR_MD_MKDIR(const char *name, PRIntn mode)
766 {
767 PRInt32 rc;
768 /* XXXMB - how to translate the "mode"??? */
769 if ((rc = DosCreateDir((char *)name, NULL))== NO_ERROR) {
770 return 0;
771 } else {
772 _PR_MD_MAP_MKDIR_ERROR(rc);
773 return -1;
774 }
775 }
777 PRInt32
778 _PR_MD_RMDIR(const char *name)
779 {
780 PRInt32 rc;
781 if ( (rc = DosDeleteDir((char *)name)) == NO_ERROR) {
782 return 0;
783 } else {
784 _PR_MD_MAP_RMDIR_ERROR(rc);
785 return -1;
786 }
787 }
789 PRStatus
790 _PR_MD_LOCKFILE(PRInt32 f)
791 {
792 PRInt32 rv;
793 FILELOCK lock, unlock;
794 FILELOCKL lockL, unlockL;
796 lock.lOffset = 0;
797 lockL.lOffset = 0;
798 lock.lRange = 0xffffffff;
799 lockL.lRange = 0xffffffffffffffff;
800 unlock.lOffset = 0;
801 unlock.lRange = 0;
802 unlockL.lOffset = 0;
803 unlockL.lRange = 0;
805 /*
806 * loop trying to DosSetFileLocks(),
807 * pause for a few miliseconds when can't get the lock
808 * and try again
809 */
810 for( rv = FALSE; rv == FALSE; /* do nothing */ )
811 {
812 if (isWSEB)
813 {
814 rv = myDosSetFileLocksL( (HFILE) f,
815 &unlockL, &lockL,
816 0, 0);
817 }
818 else
819 {
820 rv = DosSetFileLocks( (HFILE) f,
821 &unlock, &lock,
822 0, 0);
823 }
824 if ( rv != NO_ERROR )
825 {
826 DosSleep( 50 ); /* Sleep() a few milisecs and try again. */
827 }
828 } /* end for() */
829 return PR_SUCCESS;
830 } /* end _PR_MD_LOCKFILE() */
832 PRStatus
833 _PR_MD_TLOCKFILE(PRInt32 f)
834 {
835 return _PR_MD_LOCKFILE(f);
836 } /* end _PR_MD_TLOCKFILE() */
839 PRStatus
840 _PR_MD_UNLOCKFILE(PRInt32 f)
841 {
842 PRInt32 rv;
843 FILELOCK lock, unlock;
844 FILELOCKL lockL, unlockL;
846 lock.lOffset = 0;
847 lockL.lOffset = 0;
848 lock.lRange = 0;
849 lockL.lRange = 0;
850 unlock.lOffset = 0;
851 unlockL.lOffset = 0;
852 unlock.lRange = 0xffffffff;
853 unlockL.lRange = 0xffffffffffffffff;
855 if (isWSEB)
856 {
857 rv = myDosSetFileLocksL( (HFILE) f,
858 &unlockL, &lockL,
859 0, 0);
860 }
861 else
862 {
863 rv = DosSetFileLocks( (HFILE) f,
864 &unlock, &lock,
865 0, 0);
866 }
868 if ( rv != NO_ERROR )
869 {
870 return PR_SUCCESS;
871 }
872 else
873 {
874 return PR_FAILURE;
875 }
876 } /* end _PR_MD_UNLOCKFILE() */
878 PRStatus
879 _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable)
880 {
881 APIRET rc = 0;
882 ULONG flags;
883 switch (fd->methods->file_type)
884 {
885 case PR_DESC_PIPE:
886 case PR_DESC_FILE:
887 rc = DosQueryFHState((HFILE)fd->secret->md.osfd, &flags);
888 if (rc != NO_ERROR) {
889 PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
890 return PR_FAILURE;
891 }
893 if (inheritable)
894 flags &= ~OPEN_FLAGS_NOINHERIT;
895 else
896 flags |= OPEN_FLAGS_NOINHERIT;
898 /* Mask off flags DosSetFHState don't want. */
899 flags &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
900 rc = DosSetFHState((HFILE)fd->secret->md.osfd, flags);
901 if (rc != NO_ERROR) {
902 PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
903 return PR_FAILURE;
904 }
905 break;
907 case PR_DESC_LAYERED:
908 /* what to do here? */
909 PR_SetError(PR_UNKNOWN_ERROR, 87 /*ERROR_INVALID_PARAMETER*/);
910 return PR_FAILURE;
912 case PR_DESC_SOCKET_TCP:
913 case PR_DESC_SOCKET_UDP:
914 /* These are global on OS/2. */
915 break;
916 }
918 return PR_SUCCESS;
919 }
921 void
922 _PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported)
923 {
924 /* XXX this function needs to be implemented */
925 fd->secret->inheritable = _PR_TRI_UNKNOWN;
926 }
928 void
929 _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd)
930 {
931 /* XXX this function needs to be reviewed */
932 ULONG flags;
934 PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
935 if (DosQueryFHState((HFILE)fd->secret->md.osfd, &flags) == 0) {
936 if (flags & OPEN_FLAGS_NOINHERIT) {
937 fd->secret->inheritable = _PR_TRI_FALSE;
938 } else {
939 fd->secret->inheritable = _PR_TRI_TRUE;
940 }
941 }
942 }