Avoid potential negative array index access to cached text.
[LibreOffice.git] / sal / osl / unx / uunxapi.cxx
blob033b1a435a77d21bcb96a0e13cc804ef5fa95671
1 /* -*- Mode: ObjC; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <string_view>
24 #include <config_features.h>
26 #include "uunxapi.hxx"
27 #include "system.hxx"
28 #include "unixerrnostring.hxx"
29 #include <limits.h>
30 #include <rtl/ustring.hxx>
31 #include <osl/thread.h>
32 #include <sal/log.hxx>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <utime.h>
39 #ifdef ANDROID
40 #include <osl/detail/android-bootstrap.h>
41 #endif
43 OString osl::OUStringToOString(std::u16string_view s)
45 return rtl::OUStringToOString(s, osl_getThreadTextEncoding());
48 #if HAVE_FEATURE_MACOSX_SANDBOX
50 #include <Foundation/Foundation.h>
51 #include <Security/Security.h>
52 #include <mach-o/dyld.h>
54 static NSUserDefaults *userDefaults = NULL;
55 static bool isSandboxed = false;
57 static void do_once()
59 SecCodeRef code;
60 OSStatus rc = SecCodeCopySelf(kSecCSDefaultFlags, &code);
62 SecStaticCodeRef staticCode;
63 if (rc == errSecSuccess)
64 rc = SecCodeCopyStaticCode(code, kSecCSDefaultFlags, &staticCode);
66 CFDictionaryRef signingInformation;
67 if (rc == errSecSuccess)
68 rc = SecCodeCopySigningInformation(staticCode, kSecCSRequirementInformation, &signingInformation);
70 CFDictionaryRef entitlements = NULL;
71 if (rc == errSecSuccess)
72 entitlements = (CFDictionaryRef) CFDictionaryGetValue(signingInformation, kSecCodeInfoEntitlementsDict);
74 if (entitlements != NULL)
75 if (CFDictionaryGetValue(entitlements, CFSTR("com.apple.security.app-sandbox")) != NULL)
76 isSandboxed = true;
78 if (isSandboxed)
79 userDefaults = [NSUserDefaults standardUserDefaults];
82 typedef struct {
83 NSURL *scopeURL;
84 NSAutoreleasePool *pool;
85 } accessFilePathState;
87 static accessFilePathState *
88 prepare_to_access_file_path( const char *cpFilePath )
90 static pthread_once_t once = PTHREAD_ONCE_INIT;
91 pthread_once(&once, &do_once);
92 NSURL *fileURL = nil;
93 NSData *data = nil;
94 BOOL stale;
95 accessFilePathState *state;
97 if (!isSandboxed)
98 return NULL;
100 // If malloc() fails we are screwed anyway
101 state = (accessFilePathState*) malloc(sizeof(accessFilePathState));
103 state->pool = [[NSAutoreleasePool alloc] init];
104 state->scopeURL = nil;
106 if (userDefaults != nil)
107 fileURL = [NSURL fileURLWithPath:[NSString stringWithUTF8String:cpFilePath]];
109 if (fileURL != nil)
110 data = [userDefaults dataForKey:[@"bookmarkFor:" stringByAppendingString:[fileURL absoluteString]]];
112 if (data != nil)
113 state->scopeURL = [NSURL URLByResolvingBookmarkData:data
114 options:NSURLBookmarkResolutionWithSecurityScope
115 relativeToURL:nil
116 bookmarkDataIsStale:&stale
117 error:nil];
118 if (state->scopeURL != nil)
119 [state->scopeURL startAccessingSecurityScopedResource];
121 return state;
124 static void
125 done_accessing_file_path( const char * /*cpFilePath*/, accessFilePathState *state )
127 if (!isSandboxed)
128 return;
130 int saved_errno = errno;
132 if (state->scopeURL != nil)
133 [state->scopeURL stopAccessingSecurityScopedResource];
134 [state->pool release];
135 free(state);
137 errno = saved_errno;
140 #else
142 typedef void accessFilePathState;
144 #define prepare_to_access_file_path( cpFilePath ) nullptr
146 #define done_accessing_file_path( cpFilePath, state ) ((void) cpFilePath, (void) state)
148 #endif
150 #ifdef MACOSX
152 * Helper function for resolving Mac native alias files (not the same as unix alias files)
153 * and to return the resolved alias as OString
155 static OString macxp_resolveAliasAndConvert(OString const & p)
157 char path[PATH_MAX];
158 if (p.getLength() < PATH_MAX)
160 strcpy(path, p.getStr());
161 macxp_resolveAlias(path, PATH_MAX);
162 return path;
164 return p;
166 #endif /* MACOSX */
168 int osl::access(const OString& pstrPath, int mode)
170 OString fn = pstrPath;
171 #ifdef ANDROID
172 if (fn == "/assets" || fn.startsWith("/assets/"))
174 struct stat stat;
175 if (lo_apk_lstat(fn.getStr(), &stat) == -1)
176 return -1;
177 if (mode & W_OK)
179 errno = EACCES;
180 return -1;
182 return 0;
184 #endif
186 #ifdef MACOSX
187 fn = macxp_resolveAliasAndConvert(fn);
188 #endif
190 accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
192 int result = ::access(fn.getStr(), mode);
193 int saved_errno = errno;
194 if (result == -1)
195 SAL_INFO("sal.file", "access(" << fn << ",0" << std::oct << mode << std::dec << "): " << UnixErrnoString(saved_errno));
196 else
197 SAL_INFO("sal.file", "access(" << fn << ",0" << std::oct << mode << std::dec << "): OK");
199 done_accessing_file_path(fn.getStr(), state);
201 errno = saved_errno;
203 return result;
206 namespace {
208 OString toOString(OString const & s) { return s; }
210 OString toOString(std::u16string_view s) { return osl::OUStringToOString(s); }
212 template<typename T> T fromOString(OString const &) = delete;
214 template<> OString fromOString(OString const & s) { return s; }
216 template<> OUString fromOString(OString const & s)
217 { return OStringToOUString(s, osl_getThreadTextEncoding()); }
219 template<typename T> bool realpath_(const T& pstrFileName, T& ppstrResolvedName)
221 OString fn = toOString(pstrFileName);
222 #if defined ANDROID || defined(EMSCRIPTEN)
223 #if defined ANDROID
224 if (fn == "/assets" || fn.startsWith("/assets/"))
225 #else
226 if (fn == "/instdir" || fn.startsWith("/instdir/"))
227 #endif
229 if (osl::access(fn, F_OK) == -1)
230 return false;
232 ppstrResolvedName = pstrFileName;
234 return true;
236 #endif // ANDROID || EMSCRIPTEN
238 #ifdef MACOSX
239 fn = macxp_resolveAliasAndConvert(fn);
240 #endif
242 accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
244 char rp[PATH_MAX];
245 bool bRet = realpath(fn.getStr(), rp);
246 int saved_errno = errno;
247 if (!bRet)
248 SAL_INFO("sal.file", "realpath(" << fn << "): " << UnixErrnoString(saved_errno));
249 else
250 SAL_INFO("sal.file", "realpath(" << fn << "): OK");
252 done_accessing_file_path(fn.getStr(), state);
254 if (bRet)
256 ppstrResolvedName = fromOString<T>(OString(rp));
259 errno = saved_errno;
261 return bRet;
266 bool osl::realpath(const OUString& pustrFileName, OUString& ppustrResolvedName)
268 return realpath_(pustrFileName, ppustrResolvedName);
271 bool osl::realpath(const OString& pstrFileName, OString& ppstrResolvedName)
273 return realpath_(pstrFileName, ppstrResolvedName);
276 int stat_c(const char* cpPath, struct stat* buf)
278 #ifdef ANDROID
279 if (strncmp(cpPath, "/assets", sizeof("/assets")-1) == 0 &&
280 (cpPath[sizeof("/assets")-1] == '\0' ||
281 cpPath[sizeof("/assets")-1] == '/'))
282 return lo_apk_lstat(cpPath, buf);
283 #endif
285 accessFilePathState *state = prepare_to_access_file_path(cpPath);
287 int result = stat(cpPath, buf);
288 int saved_errno = errno;
289 if (result == -1)
290 SAL_INFO("sal.file", "stat(" << cpPath << "): " << UnixErrnoString(saved_errno));
291 else
292 SAL_INFO("sal.file", "stat(" << cpPath << "): OK");
294 done_accessing_file_path(cpPath, state);
296 errno = saved_errno;
298 return result;
301 int lstat_c(const char* cpPath, struct stat* buf)
303 #ifdef ANDROID
304 if (strncmp(cpPath, "/assets", sizeof("/assets")-1) == 0 &&
305 (cpPath[sizeof("/assets")-1] == '\0' ||
306 cpPath[sizeof("/assets")-1] == '/'))
307 return lo_apk_lstat(cpPath, buf);
308 #endif
310 accessFilePathState *state = prepare_to_access_file_path(cpPath);
312 int result = lstat(cpPath, buf);
313 int saved_errno = errno;
314 if (result == -1)
315 SAL_INFO("sal.file", "lstat(" << cpPath << "): " << UnixErrnoString(saved_errno));
316 else
317 SAL_INFO("sal.file", "lstat(" << cpPath << "): OK");
319 done_accessing_file_path(cpPath, state);
321 errno = saved_errno;
323 return result;
326 namespace {
328 template<typename T> int lstat_(const T& pstrPath, struct stat& buf)
330 OString fn = toOString(pstrPath);
332 #ifdef MACOSX
333 fn = macxp_resolveAliasAndConvert(fn);
334 #endif
336 return lstat_c(fn.getStr(), &buf);
341 int osl::lstat(const OUString& pustrPath, struct stat& buf)
343 return lstat_(pustrPath, buf);
346 int osl::lstat(const OString& pstrPath, struct stat& buf)
348 return lstat_(pstrPath, buf);
351 int osl::mkdir(const OString& path, mode_t mode)
353 accessFilePathState *state = prepare_to_access_file_path(path.getStr());
355 int result = ::mkdir(path.getStr(), mode);
356 int saved_errno = errno;
357 if (result == -1)
358 SAL_INFO("sal.file", "mkdir(" << path << ",0" << std::oct << mode << std::dec << "): " << UnixErrnoString(saved_errno));
359 else
360 SAL_INFO("sal.file", "mkdir(" << path << ",0" << std::oct << mode << std::dec << "): OK");
362 done_accessing_file_path(path.getStr(), state);
364 errno = saved_errno;
366 return result;
369 int open_c(const OString& path, int oflag, int mode)
371 accessFilePathState *state = prepare_to_access_file_path(path.getStr());
373 int result = open(path.getStr(), oflag, mode);
374 int saved_errno = errno;
375 if (result == -1)
376 SAL_INFO("sal.file", "open(" << path << ",0" << std::oct << oflag << ",0" << mode << std::dec << "): " << UnixErrnoString(saved_errno));
377 else
378 SAL_INFO("sal.file", "open(" << path << ",0" << std::oct << oflag << ",0" << mode << std::dec << ") => " << result);
380 #if HAVE_FEATURE_MACOSX_SANDBOX
381 if (isSandboxed && result != -1 && (oflag & O_CREAT) && (oflag & O_EXCL))
383 // A new file was created. Check if it is outside the sandbox.
384 // (In that case it must be one the user selected as export or
385 // save destination in a file dialog, otherwise we wouldn't
386 // have been able to create it.) Create and store a security
387 // scoped bookmark for it so that we can access the file in
388 // the future, too. (For the "Recent Files" functionality.)
389 const char *sandbox = [NSHomeDirectory() UTF8String];
390 if (!(strncmp(sandbox, path.getStr(), strlen(sandbox)) == 0 &&
391 path[strlen(sandbox)] == '/'))
393 auto cpPath = path.getStr();
394 NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:cpPath]];
395 NSData *data = [url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
396 includingResourceValuesForKeys:nil
397 relativeToURL:nil
398 error:nil];
399 if (data != NULL)
401 [userDefaults setObject:data
402 forKey:[@"bookmarkFor:" stringByAppendingString:[url absoluteString]]];
406 #endif
408 done_accessing_file_path(path.getStr(), state);
410 errno = saved_errno;
412 return result;
415 int utime_c(const char *cpPath, struct utimbuf *times)
417 accessFilePathState *state = prepare_to_access_file_path(cpPath);
419 int result = utime(cpPath, times);
421 done_accessing_file_path(cpPath, state);
423 return result;
426 int ftruncate_with_name(int fd, sal_uInt64 uSize, const OString& path)
428 /* When sandboxed on macOS, ftruncate(), even if it takes an
429 * already open file descriptor which was returned from an open()
430 * call already checked by the sandbox, still requires a security
431 * scope bookmark for the file to be active in case the file is
432 * one that the sandbox doesn't otherwise allow access to. Luckily
433 * LibreOffice usually calls ftruncate() through the helpful C++
434 * abstraction layer that keeps the pathname around.
437 OString fn(path);
439 #ifdef MACOSX
440 fn = macxp_resolveAliasAndConvert(fn);
441 #endif
443 accessFilePathState *state = prepare_to_access_file_path(fn.getStr());
445 int result = ftruncate(fd, uSize);
446 int saved_errno = errno;
447 if (result < 0)
448 SAL_INFO("sal.file", "ftruncate(" << fd << "," << uSize << "): " << UnixErrnoString(saved_errno));
449 else
450 SAL_INFO("sal.file", "ftruncate(" << fd << "," << uSize << "): OK");
452 done_accessing_file_path(fn.getStr(), state);
454 errno = saved_errno;
456 return result;
460 std::string UnixErrnoString(int nErrno)
462 // Errnos from <asm-generic/errno-base.h> and <asm-generic/errno.h> on Linux and <sys/errno.h>
463 // on macOS.
464 switch (nErrno)
466 case EPERM:
467 return "EPERM";
468 case ENOENT:
469 return "ENOENT";
470 case ESRCH:
471 return "ESRCH";
472 case EINTR:
473 return "EINTR";
474 case EIO:
475 return "EIO";
476 case ENXIO:
477 return "ENXIO";
478 case E2BIG:
479 return "E2BIG";
480 case ENOEXEC:
481 return "ENOEXEC";
482 case EBADF:
483 return "EBADF";
484 case ECHILD:
485 return "ECHILD";
486 case EAGAIN:
487 return "EAGAIN";
488 case ENOMEM:
489 return "ENOMEM";
490 case EACCES:
491 return "EACCES";
492 case EFAULT:
493 return "EFAULT";
494 #ifdef ENOTBLK
495 case ENOTBLK:
496 return "ENOTBLK";
497 #endif
498 case EBUSY:
499 return "EBUSY";
500 case EEXIST:
501 return "EEXIST";
502 case EXDEV:
503 return "EXDEV";
504 case ENODEV:
505 return "ENODEV";
506 case ENOTDIR:
507 return "ENOTDIR";
508 case EISDIR:
509 return "EISDIR";
510 case EINVAL:
511 return "EINVAL";
512 case ENFILE:
513 return "ENFILE";
514 case EMFILE:
515 return "EMFILE";
516 case ENOTTY:
517 return "ENOTTY";
518 case ETXTBSY:
519 return "ETXTBSY";
520 case EFBIG:
521 return "EFBIG";
522 case ENOSPC:
523 return "ENOSPC";
524 case ESPIPE:
525 return "ESPIPE";
526 case EROFS:
527 return "EROFS";
528 case EMLINK:
529 return "EMLINK";
530 case EPIPE:
531 return "EPIPE";
532 case EDOM:
533 return "EDOM";
534 case ERANGE:
535 return "ERANGE";
536 case EDEADLK:
537 return "EDEADLK";
538 case ENAMETOOLONG:
539 return "ENAMETOOLONG";
540 case ENOLCK:
541 return "ENOLCK";
542 case ENOSYS:
543 return "ENOSYS";
544 case ENOTEMPTY:
545 return "ENOTEMPTY";
546 case ELOOP:
547 return "ELOOP";
548 case ENOMSG:
549 return "ENOMSG";
550 case EIDRM:
551 return "EIDRM";
552 #ifdef ECHRNG
553 case ECHRNG:
554 return "ECHRNG";
555 #endif
556 #ifdef EL2NSYNC
557 case EL2NSYNC:
558 return "EL2NSYNC";
559 #endif
560 #ifdef EL3HLT
561 case EL3HLT:
562 return "EL3HLT";
563 #endif
564 #ifdef EL3RST
565 case EL3RST:
566 return "EL3RST";
567 #endif
568 #ifdef ELNRNG
569 case ELNRNG:
570 return "ELNRNG";
571 #endif
572 #ifdef EUNATCH
573 case EUNATCH:
574 return "EUNATCH";
575 #endif
576 #ifdef ENOCSI
577 case ENOCSI:
578 return "ENOCSI";
579 #endif
580 #ifdef EL2HLT
581 case EL2HLT:
582 return "EL2HLT";
583 #endif
584 #ifdef EBADE
585 case EBADE:
586 return "EBADE";
587 #endif
588 #ifdef EBADR
589 case EBADR:
590 return "EBADR";
591 #endif
592 #ifdef EXFULL
593 case EXFULL:
594 return "EXFULL";
595 #endif
596 #ifdef ENOANO
597 case ENOANO:
598 return "ENOANO";
599 #endif
600 #ifdef EBADRQC
601 case EBADRQC:
602 return "EBADRQC";
603 #endif
604 #ifdef EBADSLT
605 case EBADSLT:
606 return "EBADSLT";
607 #endif
608 #ifdef EBFONT
609 case EBFONT:
610 return "EBFONT";
611 #endif
612 case ENOSTR:
613 return "ENOSTR";
614 case ENODATA:
615 return "ENODATA";
616 case ETIME:
617 return "ETIME";
618 case ENOSR:
619 return "ENOSR";
620 #ifdef ENONET
621 case ENONET:
622 return "ENONET";
623 #endif
624 #ifdef ENOPKG
625 case ENOPKG:
626 return "ENOPKG";
627 #endif
628 #ifdef EREMOTE
629 case EREMOTE:
630 return "EREMOTE";
631 #endif
632 case ENOLINK:
633 return "ENOLINK";
634 #ifdef EADV
635 case EADV:
636 return "EADV";
637 #endif
638 #ifdef ESRMNT
639 case ESRMNT:
640 return "ESRMNT";
641 #endif
642 #ifdef ECOMM
643 case ECOMM:
644 return "ECOMM";
645 #endif
646 case EPROTO:
647 return "EPROTO";
648 case EMULTIHOP:
649 return "EMULTIHOP";
650 #ifdef EDOTDOT
651 case EDOTDOT:
652 return "EDOTDOT";
653 #endif
654 case EBADMSG:
655 return "EBADMSG";
656 case EOVERFLOW:
657 return "EOVERFLOW";
658 #ifdef ENOTUNIQ
659 case ENOTUNIQ:
660 return "ENOTUNIQ";
661 #endif
662 #ifdef EBADFD
663 case EBADFD:
664 return "EBADFD";
665 #endif
666 #ifdef EREMCHG
667 case EREMCHG:
668 return "EREMCHG";
669 #endif
670 #ifdef ELIBACC
671 case ELIBACC:
672 return "ELIBACC";
673 #endif
674 #ifdef ELIBBAD
675 case ELIBBAD:
676 return "ELIBBAD";
677 #endif
678 #ifdef ELIBSCN
679 case ELIBSCN:
680 return "ELIBSCN";
681 #endif
682 #ifdef ELIBMAX
683 case ELIBMAX:
684 return "ELIBMAX";
685 #endif
686 #ifdef ELIBEXEC
687 case ELIBEXEC:
688 return "ELIBEXEC";
689 #endif
690 case EILSEQ:
691 return "EILSEQ";
692 #ifdef ERESTART
693 case ERESTART:
694 return "ERESTART";
695 #endif
696 #ifdef ESTRPIPE
697 case ESTRPIPE:
698 return "ESTRPIPE";
699 #endif
700 #ifdef EUSERS
701 case EUSERS:
702 return "EUSERS";
703 #endif
704 case ENOTSOCK:
705 return "ENOTSOCK";
706 case EDESTADDRREQ:
707 return "EDESTADDRREQ";
708 case EMSGSIZE:
709 return "EMSGSIZE";
710 case EPROTOTYPE:
711 return "EPROTOTYPE";
712 case ENOPROTOOPT:
713 return "ENOPROTOOPT";
714 case EPROTONOSUPPORT:
715 return "EPROTONOSUPPORT";
716 #ifdef ESOCKTNOSUPPORT
717 case ESOCKTNOSUPPORT:
718 return "ESOCKTNOSUPPORT";
719 #endif
720 #ifdef EOPNOTSUPP
721 case EOPNOTSUPP:
722 return "EOPNOTSUPP";
723 #endif
724 case EPFNOSUPPORT:
725 return "EPFNOSUPPORT";
726 case EAFNOSUPPORT:
727 return "EAFNOSUPPORT";
728 case EADDRINUSE:
729 return "EADDRINUSE";
730 case EADDRNOTAVAIL:
731 return "EADDRNOTAVAIL";
732 case ENETDOWN:
733 return "ENETDOWN";
734 case ENETUNREACH:
735 return "ENETUNREACH";
736 case ENETRESET:
737 return "ENETRESET";
738 case ECONNABORTED:
739 return "ECONNABORTED";
740 case ECONNRESET:
741 return "ECONNRESET";
742 case ENOBUFS:
743 return "ENOBUFS";
744 case EISCONN:
745 return "EISCONN";
746 case ENOTCONN:
747 return "ENOTCONN";
748 #ifdef ESHUTDOWN
749 case ESHUTDOWN:
750 return "ESHUTDOWN";
751 #endif
752 #ifdef ETOOMANYREFS
753 case ETOOMANYREFS:
754 return "ETOOMANYREFS";
755 #endif
756 case ETIMEDOUT:
757 return "ETIMEDOUT";
758 case ECONNREFUSED:
759 return "ECONNREFUSED";
760 #ifdef EHOSTDOWN
761 case EHOSTDOWN:
762 return "EHOSTDOWN";
763 #endif
764 case EHOSTUNREACH:
765 return "EHOSTUNREACH";
766 case EALREADY:
767 return "EALREADY";
768 case EINPROGRESS:
769 return "EINPROGRESS";
770 case ESTALE:
771 return "ESTALE";
772 #ifdef EUCLEAN
773 case EUCLEAN:
774 return "EUCLEAN";
775 #endif
776 #ifdef ENOTNAM
777 case ENOTNAM:
778 return "ENOTNAM";
779 #endif
780 #ifdef ENAVAIL
781 case ENAVAIL:
782 return "ENAVAIL";
783 #endif
784 #ifdef EISNAM
785 case EISNAM:
786 return "EISNAM";
787 #endif
788 #ifdef EREMOTEIO
789 case EREMOTEIO:
790 return "EREMOTEIO";
791 #endif
792 case EDQUOT:
793 return "EDQUOT";
794 #ifdef ENOMEDIUM
795 case ENOMEDIUM:
796 return "ENOMEDIUM";
797 #endif
798 #ifdef EMEDIUMTYPE
799 case EMEDIUMTYPE:
800 return "EMEDIUMTYPE";
801 #endif
802 case ECANCELED:
803 return "ECANCELED";
804 #ifdef ENOKEY
805 case ENOKEY:
806 return "ENOKEY";
807 #endif
808 #ifdef EKEYEXPIRED
809 case EKEYEXPIRED:
810 return "EKEYEXPIRED";
811 #endif
812 #ifdef EKEYREVOKED
813 case EKEYREVOKED:
814 return "EKEYREVOKED";
815 #endif
816 #ifdef EKEYREJECTED
817 case EKEYREJECTED:
818 return "EKEYREJECTED";
819 #endif
820 #ifdef EOWNERDEAD
821 case EOWNERDEAD:
822 return "EOWNERDEAD";
823 #endif
824 #ifdef ENOTRECOVERABLE
825 case ENOTRECOVERABLE:
826 return "ENOTRECOVERABLE";
827 #endif
828 #ifdef ERFKILL
829 case ERFKILL:
830 return "ERFKILL";
831 #endif
832 #ifdef EHWPOISON
833 case EHWPOISON:
834 return "EHWPOISON";
835 #endif
836 #ifdef EPROCLIM
837 case EPROCLIM:
838 return "EPROCLIM";
839 #endif
840 #ifdef EBADRPC
841 case EBADRPC:
842 return "EBADRPC";
843 #endif
844 #ifdef ERPCMISMATCH
845 case ERPCMISMATCH:
846 return "ERPCMISMATCH";
847 #endif
848 #ifdef EPROGUNAVAIL
849 case EPROGUNAVAIL:
850 return "EPROGUNAVAIL";
851 #endif
852 #ifdef EPROGMISMATCH
853 case EPROGMISMATCH:
854 return "EPROGMISMATCH";
855 #endif
856 #ifdef EPROCUNAVAIL
857 case EPROCUNAVAIL:
858 return "EPROCUNAVAIL";
859 #endif
860 #ifdef EFTYPE
861 case EFTYPE:
862 return "EFTYPE";
863 #endif
864 #ifdef EAUTH
865 case EAUTH:
866 return "EAUTH";
867 #endif
868 #ifdef ENEEDAUTH
869 case ENEEDAUTH:
870 return "ENEEDAUTH";
871 #endif
872 #ifdef EPWROFF
873 case EPWROFF:
874 return "EPWROFF";
875 #endif
876 #ifdef EDEVERR
877 case EDEVERR:
878 return "EDEVERR";
879 #endif
880 #ifdef EBADEXEC
881 case EBADEXEC:
882 return "EBADEXEC";
883 #endif
884 #ifdef EBADARCH
885 case EBADARCH:
886 return "EBADARCH";
887 #endif
888 #ifdef ESHLIBVERS
889 case ESHLIBVERS:
890 return "ESHLIBVERS";
891 #endif
892 #ifdef EBADMACHO
893 case EBADMACHO:
894 return "EBADMACHO";
895 #endif
896 #ifdef ENOATTR
897 case ENOATTR:
898 return "ENOATTR";
899 #endif
900 #ifdef EQFULL
901 case EQFULL:
902 return "EQFULL";
903 #endif
904 default:
905 char* str = strerror(nErrno);
906 return std::to_string(nErrno) + " (" + std::string(str) + ")";
910 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */