summaryrefslogtreecommitdiffstats
path: root/src/common/win32/errno.cc
blob: bac9320a36121b920c41cb982d4eb4d2db8432c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2020 SUSE LINUX GmbH
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */


#include <errno.h>
#include <stdlib.h>

#include "include/int_types.h"
#include <ntdef.h>
#include <ntstatus.h>

#include "include/compat.h"
#include "include/int_types.h"
#include "include/types.h"
#include "include/fs_types.h"

// We're only converting errors defined in errno.h, not standard Windows
// system error codes that are usually retrievied using GetLastErrorCode().
// TODO: consider converting WinSock2 (WSA*) error codes, which are quite
// similar to the errno.h ones.

__u32 ceph_to_hostos_errno_unsigned(__u32 r)
{
  // using an array like like freebsd_errno.cc might be more readable but
  // we have some large values defined by Boost.
  switch(r) {
    case 1: return EPERM;
    case 2: return ENOENT;
    case 3: return ESRCH;
    case 4: return EINTR;
    case 5: return EIO;
    case 6: return ENXIO;
    case 7: return E2BIG;
    case 8: return ENOEXEC;
    case 9: return EBADF;
    case 10: return ECHILD;
    // same as EWOULDBLOCK
    case 11: return EAGAIN;
    case 12: return ENOMEM;
    case 13: return EACCES;
    case 14: return EFAULT;
    case 15: return ENOTBLK;
    case 16: return EBUSY;
    case 17: return EEXIST;
    case 18: return EXDEV;
    case 19: return ENODEV;
    case 20: return ENOTDIR;
    case 21: return EISDIR;
    case 22: return EINVAL;
    case 23: return ENFILE;
    case 24: return EMFILE;
    case 25: return ENOTTY;
    case 26: return ETXTBSY;
    case 27: return EFBIG;
    case 28: return ENOSPC;
    case 29: return ESPIPE;
    case 30: return EROFS;
    case 31: return EMLINK;
    case 32: return EPIPE;
    case 33: return EDOM;
    case 34: return ERANGE;
    // same as EDEADLK
    case 35: return EDEADLOCK;
    case 36: return ENAMETOOLONG;
    case 37: return ENOLCK;
    case 38: return ENOSYS;
    case 39: return ENOTEMPTY;
    case 40: return ELOOP;
    case 42: return ENOMSG;
    case 43: return EIDRM;
    case 44: return ECHRNG;
    case 45: return EL2NSYNC;
    case 46: return EL3HLT;
    case 47: return EL3RST;
    case 48: return ELNRNG;
    case 49: return EUNATCH;
    case 50: return ENOCSI;
    case 51: return EL2HLT;
    case 52: return EBADE;
    case 53: return EBADR;
    case 54: return EXFULL;
    case 55: return ENOANO;
    case 56: return EBADRQC;
    case 57: return EBADSLT;
    case 59: return EBFONT;
    case 60: return ENOSTR;
    case 61: return ENODATA;
    case 62: return ETIME;
    case 63: return ENOSR;
    case 64: return ENONET;
    case 65: return ENOPKG;
    case 66: return EREMOTE;
    case 67: return ENOLINK;
    case 68: return EADV;
    case 69: return ESRMNT;
    case 70: return ECOMM;
    case 71: return EPROTO;
    case 72: return EMULTIHOP;
    case 73: return EDOTDOT;
    case 74: return EBADMSG;
    case 75: return EOVERFLOW;
    case 76: return ENOTUNIQ;
    case 77: return EBADFD;
    case 78: return EREMCHG;
    case 79: return ELIBACC;
    case 80: return ELIBBAD;
    case 81: return ELIBSCN;
    case 82: return ELIBMAX;
    case 83: return ELIBEXEC;
    case 84: return EILSEQ;
    case 85: return ERESTART;
    case 86: return ESTRPIPE;
    case 87: return EUSERS;
    case 88: return ENOTSOCK;
    case 89: return EDESTADDRREQ;
    case 90: return EMSGSIZE;
    case 91: return EPROTOTYPE;
    case 92: return ENOPROTOOPT;
    case 93: return EPROTONOSUPPORT;
    case 94: return ESOCKTNOSUPPORT;
    // same as ENOTSUP
    case 95: return EOPNOTSUPP;
    case 96: return EPFNOSUPPORT;
    case 97: return EAFNOSUPPORT;
    case 98: return EADDRINUSE;
    case 99: return EADDRNOTAVAIL;
    case 100: return ENETDOWN;
    case 101: return ENETUNREACH;
    case 102: return ENETRESET;
    case 103: return ECONNABORTED;
    case 104: return ECONNRESET;
    case 105: return ENOBUFS;
    case 106: return EISCONN;
    case 107: return ENOTCONN;
    case 108: return ESHUTDOWN;
    case 109: return ETOOMANYREFS;
    case 110: return ETIMEDOUT;
    case 111: return ECONNREFUSED;
    case 112: return EHOSTDOWN;
    case 113: return EHOSTUNREACH;
    case 114: return EALREADY;
    case 115: return EINPROGRESS;
    case 116: return ESTALE;
    case 117: return EUCLEAN;
    case 118: return ENOTNAM;
    case 119: return ENAVAIL;
    case 120: return EISNAM;
    case 121: return EREMOTEIO;
    case 122: return EDQUOT;
    case 123: return ENOMEDIUM;
    case 124: return EMEDIUMTYPE;
    case 125: return ECANCELED;
    case 126: return ENOKEY;
    case 127: return EKEYEXPIRED;
    case 128: return EKEYREVOKED;
    case 129: return EKEYREJECTED;
    case 130: return EOWNERDEAD;
    case 131: return ENOTRECOVERABLE;
    case 132: return ERFKILL;
    case 133: return EHWPOISON;
    default:
      return r;
  }
}

__u32 hostos_to_ceph_errno_unsigned(__u32 r) {
  // Windows errno -> Linux errno
  switch(r) {
    case EPERM: return 1;
    case ENOENT: return 2;
    case ESRCH: return 3;
    case EINTR: return 4;
    case EIO: return 5;
    case ENXIO: return 6;
    case E2BIG: return 7;
    case ENOEXEC: return 8;
    case EBADF: return 9;
    case ECHILD: return 10;
    case EAGAIN: return 11;
    case EWOULDBLOCK: return 11;
    case ENOMEM: return 12;
    case EACCES: return 13;
    case EFAULT: return 14;
    case ENOTBLK: return 15;
    case EBUSY: return 16;
    case EEXIST: return 17;
    case EXDEV: return 18;
    case ENODEV: return 19;
    case ENOTDIR: return 20;
    case EISDIR: return 21;
    case EINVAL: return 22;
    case ENFILE: return 23;
    case EMFILE: return 24;
    case ENOTTY: return 25;
    case ETXTBSY: return 26;
    case EFBIG: return 27;
    case ENOSPC: return 28;
    case ESPIPE: return 29;
    case EROFS: return 30;
    case EMLINK: return 31;
    case EPIPE: return 32;
    case EDOM: return 33;
    case ERANGE: return 34;
    // same as EDEADLOCK
    // case EDEADLK: return 35;
    case EDEADLOCK: return 35;
    case ENAMETOOLONG: return 36;
    case ENOLCK: return 37;
    case ENOSYS: return 38;
    case ENOTEMPTY: return 39;
    case ELOOP: return 40;
    case ENOMSG: return 42;
    case EIDRM: return 43;
    case ECHRNG: return 44;
    case EL2NSYNC: return 45;
    case EL3HLT: return 46;
    case EL3RST: return 47;
    case ELNRNG: return 48;
    case EUNATCH: return 49;
    case ENOCSI: return 50;
    case EL2HLT: return 51;
    case EBADE: return 52;
    case EBADR: return 53;
    case EXFULL: return 54;
    case ENOANO: return 55;
    case EBADRQC: return 56;
    case EBADSLT: return 57;
    case EBFONT: return 59;
    case ENOSTR: return 60;
    case ENODATA: return 61;
    case ETIME: return 62;
    case ENOSR: return 63;
    case ENONET: return 64;
    case ENOPKG: return 65;
    case EREMOTE: return 66;
    case ENOLINK: return 67;
    case EADV: return 68;
    case ESRMNT: return 69;
    case ECOMM: return 70;
    case EPROTO: return 71;
    case EMULTIHOP: return 72;
    case EDOTDOT: return 73;
    case EBADMSG: return 74;
    case EOVERFLOW: return 75;
    case ENOTUNIQ: return 76;
    case EBADFD: return 77;
    case EREMCHG: return 78;
    case ELIBACC: return 79;
    case ELIBBAD: return 80;
    case ELIBSCN: return 81;
    case ELIBMAX: return 82;
    case ELIBEXEC: return 83;
    case EILSEQ: return 84;
    // compat.h defines ERESTART as EINTR
    // case ERESTART: return 85;
    case ESTRPIPE: return 86;
    case EUSERS: return 87;
    case ENOTSOCK: return 88;
    case EDESTADDRREQ: return 89;
    case EMSGSIZE: return 90;
    case EPROTOTYPE: return 91;
    case ENOPROTOOPT: return 92;
    case EPROTONOSUPPORT: return 93;
    case ESOCKTNOSUPPORT: return 94;
    case EOPNOTSUPP: return 95;
    case ENOTSUP: return 95;
    case EPFNOSUPPORT: return 96;
    case EAFNOSUPPORT: return 97;
    case EADDRINUSE: return 98;
    case EADDRNOTAVAIL: return 99;
    case ENETDOWN: return 100;
    case ENETUNREACH: return 101;
    case ENETRESET: return 102;
    case ECONNABORTED: return 103;
    case ECONNRESET: return 104;
    case ENOBUFS: return 105;
    case EISCONN: return 106;
    case ENOTCONN: return 107;
    case ESHUTDOWN: return 108;
    case ETOOMANYREFS: return 109;
    case ETIMEDOUT: return 110;
    case ECONNREFUSED: return 111;
    case EHOSTDOWN: return 112;
    case EHOSTUNREACH: return 113;
    case EALREADY: return 114;
    case EINPROGRESS: return 115;
    case ESTALE: return 116;
    case EUCLEAN: return 117;
    case ENOTNAM: return 118;
    case ENAVAIL: return 119;
    case EISNAM: return 120;
    case EREMOTEIO: return 121;
    case EDQUOT: return 122;
    case ENOMEDIUM: return 123;
    case EMEDIUMTYPE: return 124;
    case ECANCELED: return 125;
    case ENOKEY: return 126;
    case EKEYEXPIRED: return 127;
    case EKEYREVOKED: return 128;
    case EKEYREJECTED: return 129;
    case EOWNERDEAD: return 130;
    case ENOTRECOVERABLE: return 131;
    case ERFKILL: return 132;
    case EHWPOISON: return 133;
    default:
      return r;
 }
}

__s32 wsae_to_errno_unsigned(__s32 r)
{
  switch(r) {
    case WSAEINTR: return EINTR;
    case WSAEBADF: return EBADF;
    case WSAEACCES: return EACCES;
    case WSAEFAULT: return EFAULT;
    case WSAEINVAL: return EINVAL;
    case WSAEMFILE: return EMFILE;
    // Linux defines WSAEWOULDBLOCK as EAGAIN, but not Windows headers.
    // Since all ceph code uses EAGAIN instead of EWOULDBLOCK, we'll do
    // the same here.
    case WSAEWOULDBLOCK: return EAGAIN;
    // Some functions (e.g. connect) can return WSAEWOULDBLOCK instead of
    // EINPROGRESS.
    case WSAEINPROGRESS: return EINPROGRESS;
    case WSAEALREADY: return EALREADY;
    case WSAENOTSOCK: return ENOTSOCK;
    case WSAEDESTADDRREQ: return EDESTADDRREQ;
    case WSAEMSGSIZE: return EMSGSIZE;
    case WSAEPROTOTYPE: return EPROTOTYPE;
    case WSAENOPROTOOPT: return ENOPROTOOPT;
    case WSAEPROTONOSUPPORT: return EPROTONOSUPPORT;
    case WSAESOCKTNOSUPPORT: return ESOCKTNOSUPPORT;
    case WSAEOPNOTSUPP: return EOPNOTSUPP;
    case WSAEPFNOSUPPORT: return EPFNOSUPPORT;
    case WSAEAFNOSUPPORT: return EAFNOSUPPORT;
    case WSAEADDRINUSE: return EADDRINUSE;
    case WSAEADDRNOTAVAIL: return EADDRNOTAVAIL;
    case WSAENETDOWN: return ENETDOWN;
    case WSAENETUNREACH: return ENETUNREACH;
    case WSAENETRESET: return ENETRESET;
    case WSAECONNABORTED: return ECONNABORTED;
    case WSAECONNRESET: return ECONNRESET;
    case WSAENOBUFS: return ENOBUFS;
    case WSAEISCONN: return EISCONN;
    case WSAENOTCONN: return ENOTCONN;
    case WSAESHUTDOWN: return ESHUTDOWN;
    case WSAETOOMANYREFS: return ETOOMANYREFS;
    case WSAETIMEDOUT: return ETIMEDOUT;
    case WSAECONNREFUSED: return ECONNREFUSED;
    case WSAELOOP: return ELOOP;
    case WSAENAMETOOLONG: return ENAMETOOLONG;
    case WSAEHOSTDOWN: return EHOSTDOWN;
    case WSAEHOSTUNREACH: return EHOSTUNREACH;
    case WSAENOTEMPTY: return ENOTEMPTY;
    // case WSAEPROCLIM
    case WSAEUSERS: return EUSERS;
    case WSAEDQUOT: return EDQUOT;
    case WSAESTALE: return ESTALE;
    case WSAEREMOTE: return EREMOTE;
    // case WSASYSNOTREADY
    // case WSAVERNOTSUPPORTED
    // case WSANOTINITIALISED
    case WSAEDISCON: return ESHUTDOWN;
    // case WSAENOMORE
    case WSAECANCELLED: return ECANCELED;
    // We might return EINVAL, but it's probably better if we propagate the
    // original error code here.
    // case WSAEINVALIDPROCTABLE
    // case WSAEINVALIDPROVIDER
    // case WSAEPROVIDERFAILEDINIT
    // case WSASYSCALLFAILURE
    // case WSASERVICE_NOT_FOUND:
    // case WSATYPE_NOT_FOUND:
    // case WSA_E_NO_MORE:
    case WSA_E_CANCELLED: return ECANCELED;
    case WSAEREFUSED: return ECONNREFUSED;
    case WSAHOST_NOT_FOUND: return EHOSTUNREACH;
    case WSATRY_AGAIN: return EAGAIN;
    // case WSANO_RECOVERY
    // case WSANO_DATA:
    default: return r;
  }
}

// converts from linux errno values to host values
__s32 ceph_to_hostos_errno(__s32 r)
{
  int sign = (r < 0 ? -1 : 1);
  return ceph_to_hostos_errno_unsigned(abs(r)) * sign;
}

// converts Host OS errno values to linux/Ceph values
__s32 hostos_to_ceph_errno(__s32 r)
{
  int sign = (r < 0 ? -1 : 1);
  return hostos_to_ceph_errno_unsigned(abs(r)) * sign;
}

__s32 wsae_to_errno(__s32 r)
{
  int sign = (r < 0 ? -1 : 1);
  return wsae_to_errno_unsigned(abs(r)) * sign;
}

__u32 errno_to_ntstatus(__s32 r) {
  // errno -> NTSTATUS
  // In some cases, there might be more than one applicable NTSTATUS
  // value or there might be none. Certain values can be overridden
  // when the caller (or whoever is supposed to handle the error) is
  // expecting a different NTSTATUS value.
  r = abs(r);

  switch(r) {
    case 0: return 0;
    case EPERM: return STATUS_ACCESS_DENIED;
    case ENOENT: return STATUS_OBJECT_NAME_NOT_FOUND;
    case ESRCH: return STATUS_NOT_FOUND;
    case EINTR: return STATUS_RETRY;
    case EIO: return STATUS_DATA_ERROR;
    case ENXIO: return STATUS_NOT_FOUND;
    case E2BIG: return STATUS_FILE_TOO_LARGE;
    case ENOEXEC: return STATUS_ACCESS_DENIED;
    case EBADF: return STATUS_INVALID_HANDLE;
    case ECHILD: return STATUS_INTERNAL_ERROR;
    case EAGAIN: return STATUS_RETRY;
    case EWOULDBLOCK: return STATUS_RETRY;
    case ENOMEM: return STATUS_NO_MEMORY;
    case EACCES: return STATUS_ACCESS_DENIED;
    case EFAULT: return STATUS_INVALID_ADDRESS;
    case ENOTBLK: return STATUS_BAD_DEVICE_TYPE;
    case EBUSY: return STATUS_DEVICE_BUSY;
    case EEXIST: return STATUS_OBJECT_NAME_COLLISION;
    case EXDEV: return STATUS_NOT_SAME_DEVICE;
    case ENODEV: return STATUS_SYSTEM_DEVICE_NOT_FOUND;
    case ENOTDIR: return STATUS_NOT_A_DIRECTORY;
    case EISDIR: return STATUS_FILE_IS_A_DIRECTORY;
    case EINVAL: return STATUS_INVALID_PARAMETER;
    case ENFILE: return STATUS_TOO_MANY_OPENED_FILES;
    case EMFILE: return STATUS_TOO_MANY_OPENED_FILES;
    case ENOTTY: return STATUS_INVALID_PARAMETER;
    case ETXTBSY: return STATUS_DEVICE_BUSY;
    case EFBIG: return STATUS_FILE_TOO_LARGE;
    case ENOSPC: return STATUS_DISK_FULL;
    case ESPIPE: return STATUS_INVALID_PARAMETER;
    case EROFS: return STATUS_MEDIA_WRITE_PROTECTED;
    case EMLINK: return STATUS_TOO_MANY_LINKS;
    case EPIPE: return STATUS_PIPE_BROKEN;
    case EDOM: return STATUS_INVALID_PARAMETER;
    case ERANGE: return STATUS_INVALID_PARAMETER;
    // same as EDEADLOCK
    // case EDEADLK: return 35;
    case EDEADLOCK: return STATUS_POSSIBLE_DEADLOCK;
    case ENAMETOOLONG: return STATUS_NAME_TOO_LONG;
    case ENOLCK: return STATUS_NOT_LOCKED;
    case ENOSYS: return STATUS_NOT_IMPLEMENTED;
    case ENOTEMPTY: return STATUS_DIRECTORY_NOT_EMPTY;
    case ELOOP: return STATUS_TOO_MANY_LINKS;
    case ENOMSG: return STATUS_MESSAGE_NOT_FOUND;
    case EIDRM: return STATUS_INVALID_PARAMETER;
    case ECHRNG: return STATUS_INVALID_PARAMETER;
    case EL2NSYNC: return STATUS_INTERNAL_ERROR;
    case EL3HLT: return STATUS_INTERNAL_ERROR;
    case EL3RST: return STATUS_INTERNAL_ERROR;
    case ELNRNG: return STATUS_INTERNAL_ERROR;
    case EUNATCH: return STATUS_INTERNAL_ERROR;
    case ENOCSI: return STATUS_INTERNAL_ERROR;
    case EL2HLT: return STATUS_INTERNAL_ERROR;
    case EBADE: return STATUS_INTERNAL_ERROR;
    case EBADR: return STATUS_INVALID_HANDLE;
    case EXFULL: return STATUS_DISK_FULL;
    case ENOANO: return STATUS_INTERNAL_ERROR;
    case EBADRQC: return STATUS_INVALID_PARAMETER;
    case EBADSLT: return STATUS_INVALID_PARAMETER;
    case EBFONT: return STATUS_INVALID_PARAMETER;
    case ENOSTR: return STATUS_INVALID_PARAMETER;
    case ENODATA: return STATUS_NOT_FOUND;
    case ETIME: return STATUS_TIMEOUT;
    case ENOSR: return STATUS_INSUFFICIENT_RESOURCES;
    case ENONET: return STATUS_NETWORK_UNREACHABLE;
    case ENOPKG: return STATUS_NO_SUCH_PACKAGE;
    case EREMOTE: return STATUS_INVALID_PARAMETER;
    case ENOLINK: return STATUS_INTERNAL_ERROR;
    case EADV: return STATUS_INTERNAL_ERROR;
    case ESRMNT: return STATUS_INTERNAL_ERROR;
    case ECOMM: return STATUS_INTERNAL_ERROR;
    case EPROTO: return STATUS_PROTOCOL_NOT_SUPPORTED;
    case EMULTIHOP: return STATUS_INTERNAL_ERROR;
    case EDOTDOT: return STATUS_INTERNAL_ERROR;
    case EBADMSG: return STATUS_INVALID_PARAMETER;
    case EOVERFLOW: return STATUS_BUFFER_OVERFLOW;
    case ENOTUNIQ: return STATUS_DUPLICATE_NAME;
    case EBADFD: return STATUS_INVALID_HANDLE;
    case EREMCHG: return STATUS_FILE_RENAMED;
    case ELIBACC: return STATUS_DLL_NOT_FOUND;
    case ELIBBAD: return STATUS_BAD_DLL_ENTRYPOINT;
    case ELIBSCN: return STATUS_BAD_DLL_ENTRYPOINT;
    case ELIBMAX: return STATUS_TOO_MANY_OPENED_FILES;
    case ELIBEXEC: return STATUS_INVALID_PARAMETER;
    case EILSEQ: return STATUS_INVALID_PARAMETER;
    // compat.h defines ERESTART as EINTR
    // case ERESTART: return 85;
    case ESTRPIPE: return STATUS_RETRY;
    case EUSERS: return STATUS_TOO_MANY_SIDS;
    case ENOTSOCK: return STATUS_INVALID_HANDLE;
    case EDESTADDRREQ: return STATUS_INVALID_PARAMETER;
    case EMSGSIZE: return STATUS_BUFFER_OVERFLOW;
    case EPROTOTYPE: return STATUS_INVALID_PARAMETER;
    case ENOPROTOOPT: return STATUS_PROTOCOL_NOT_SUPPORTED;
    case EPROTONOSUPPORT: return STATUS_PROTOCOL_NOT_SUPPORTED;
    case ESOCKTNOSUPPORT: return STATUS_NOT_SUPPORTED;
    case EOPNOTSUPP: return STATUS_NOT_SUPPORTED;
    case ENOTSUP: return STATUS_NOT_SUPPORTED;
    case EPFNOSUPPORT: return STATUS_PROTOCOL_NOT_SUPPORTED;
    case EAFNOSUPPORT: return STATUS_NOT_SUPPORTED;
    case EADDRINUSE: return STATUS_ADDRESS_ALREADY_EXISTS;
    case EADDRNOTAVAIL: return STATUS_INVALID_ADDRESS;
    case ENETDOWN: return STATUS_NETWORK_UNREACHABLE;
    case ENETUNREACH: return STATUS_NETWORK_UNREACHABLE;
    case ENETRESET: return STATUS_CONNECTION_RESET;
    case ECONNABORTED: return STATUS_CONNECTION_ABORTED;
    case ECONNRESET: return STATUS_CONNECTION_DISCONNECTED;
    case ENOBUFS: return STATUS_BUFFER_TOO_SMALL;
    case EISCONN: return STATUS_CONNECTION_ACTIVE;
    case ENOTCONN: return STATUS_CONNECTION_DISCONNECTED;
    case ESHUTDOWN: return STATUS_SYSTEM_SHUTDOWN;
    case ETOOMANYREFS: return STATUS_TOO_MANY_LINKS;
    case ETIMEDOUT: return STATUS_TIMEOUT;
    case ECONNREFUSED: return STATUS_CONNECTION_REFUSED;
    case EHOSTDOWN: return STATUS_FILE_CLOSED;
    case EHOSTUNREACH: return STATUS_HOST_UNREACHABLE;
    case EALREADY: return STATUS_PENDING;
    case EINPROGRESS: return STATUS_PENDING;
    case ESTALE: return STATUS_INVALID_HANDLE;
    case EUCLEAN: return STATUS_INVALID_PARAMETER;
    case ENOTNAM: return STATUS_INVALID_PARAMETER;
    case ENAVAIL: return STATUS_INVALID_PARAMETER;
    case EISNAM: return STATUS_INVALID_PARAMETER;
    case EREMOTEIO: return STATUS_DATA_ERROR;
    case EDQUOT: return STATUS_QUOTA_EXCEEDED;
    case ENOMEDIUM: return STATUS_NO_MEDIA;
    case EMEDIUMTYPE: return STATUS_INVALID_PARAMETER;
    case ECANCELED: return STATUS_REQUEST_CANCELED;
    case ENOKEY: return STATUS_NO_USER_KEYS;
    case EKEYEXPIRED: return STATUS_SMARTCARD_CERT_EXPIRED;
    case EKEYREVOKED: return STATUS_IMAGE_CERT_REVOKED;
    case EKEYREJECTED: return STATUS_ACCESS_DENIED;
    case EOWNERDEAD: return STATUS_INTERNAL_ERROR;
    case ENOTRECOVERABLE: return STATUS_INTERNAL_ERROR;
    case ERFKILL: return STATUS_INTERNAL_ERROR;
    case EHWPOISON: return STATUS_INTERNAL_ERROR;
    default:
      return STATUS_INTERNAL_ERROR;
 }
}

std::string win32_strerror(int err)
{
  // As opposed to dlerror messages, this has to be freed.
  LPSTR msg = NULL;
  DWORD msg_len = ::FormatMessageA(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM |
    FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    err,
    0,
    (LPSTR) &msg,
    0,
    NULL);

  std::ostringstream msg_stream;
  msg_stream << "(" << err << ") ";
  if (!msg_len) {
    msg_stream << "Unknown error";
  }
  else {
    msg_stream << msg;
    ::LocalFree(msg);
  }
  return msg_stream.str();
}

std::string win32_lasterror_str()
{
  DWORD err = ::GetLastError();
  return win32_strerror(err);
}

static const ceph::unordered_map<int,NTSTATUS> cephfs_errno_to_ntstatus = {
  {CEPHFS_EBLOCKLISTED,    STATUS_SYSTEM_SHUTDOWN},
  {CEPHFS_EPERM,           STATUS_ACCESS_DENIED},
  {CEPHFS_ESTALE,          STATUS_INVALID_HANDLE},
  {CEPHFS_ENOSPC,          STATUS_DISK_FULL},
  {CEPHFS_ETIMEDOUT,       STATUS_TIMEOUT},
  {CEPHFS_EIO,             STATUS_DATA_ERROR},
  {CEPHFS_ENOTCONN,        STATUS_CONNECTION_DISCONNECTED},
  {CEPHFS_EEXIST,          STATUS_OBJECT_NAME_COLLISION},
  {CEPHFS_EINTR,           STATUS_RETRY},
  {CEPHFS_EINVAL,          STATUS_INVALID_PARAMETER},
  {CEPHFS_EBADF,           STATUS_INVALID_HANDLE},
  {CEPHFS_EROFS,           STATUS_MEDIA_WRITE_PROTECTED},
  {CEPHFS_EAGAIN,          STATUS_RETRY},
  {CEPHFS_EACCES,          STATUS_ACCESS_DENIED},
  {CEPHFS_ELOOP,           STATUS_TOO_MANY_LINKS},
  {CEPHFS_EISDIR,          STATUS_FILE_IS_A_DIRECTORY},
  {CEPHFS_ENOENT,          STATUS_OBJECT_NAME_NOT_FOUND},
  {CEPHFS_ENOTDIR,         STATUS_NOT_A_DIRECTORY},
  {CEPHFS_ENAMETOOLONG,    STATUS_NAME_TOO_LONG},
  {CEPHFS_EBUSY,           STATUS_DEVICE_BUSY},
  {CEPHFS_EDQUOT,          STATUS_QUOTA_EXCEEDED},
  {CEPHFS_EFBIG,           STATUS_FILE_TOO_LARGE},
  {CEPHFS_ERANGE,          STATUS_INVALID_PARAMETER},
  {CEPHFS_ENXIO,           STATUS_NOT_FOUND},
  {CEPHFS_ECANCELED,       STATUS_REQUEST_CANCELED},
  {CEPHFS_ENODATA,         STATUS_NOT_FOUND},
  {CEPHFS_EOPNOTSUPP,      STATUS_NOT_SUPPORTED},
  {CEPHFS_EXDEV,           STATUS_NOT_SAME_DEVICE},
  {CEPHFS_ENOMEM,          STATUS_NO_MEMORY},
  {CEPHFS_ENOTRECOVERABLE, STATUS_INTERNAL_ERROR},
  {CEPHFS_ENOSYS,          STATUS_NOT_IMPLEMENTED},
  {CEPHFS_ENOTEMPTY,       STATUS_DIRECTORY_NOT_EMPTY},
  {CEPHFS_EDEADLK,         STATUS_POSSIBLE_DEADLOCK},
  {CEPHFS_EDOM,            STATUS_INVALID_PARAMETER},
  {CEPHFS_EMLINK,          STATUS_TOO_MANY_LINKS},
  {CEPHFS_ETIME,           STATUS_TIMEOUT},
  {CEPHFS_EOLDSNAPC,       STATUS_DATA_ERROR}
};

__u32 cephfs_errno_to_ntsatus(int cephfs_errno)
{
  cephfs_errno = abs(cephfs_errno);

  if (cephfs_errno == 0)
    return 0;

  auto it = cephfs_errno_to_ntstatus.find(cephfs_errno);
  if (it != cephfs_errno_to_ntstatus.end())
    return it->second;
  return STATUS_INTERNAL_ERROR;
}