summaryrefslogtreecommitdiff
path: root/include/iprt/file.h
blob: 3357ab23ba4c0e122d4f89c80f233e45ea4a3f56 (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
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
/** @file
 * IPRT - File I/O.
 */

/*
 * Copyright (C) 2006-2011 Oracle Corporation
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
 * VirtualBox OSE distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 */

#ifndef ___iprt_file_h
#define ___iprt_file_h

#include <iprt/cdefs.h>
#include <iprt/types.h>
#include <iprt/stdarg.h>
#include <iprt/fs.h>

RT_C_DECLS_BEGIN

/** @defgroup grp_rt_fileio     RTFile - File I/O
 * @ingroup grp_rt
 * @{
 */

/** Platform specific text line break.
 * @deprecated Use text I/O streams and '\\n'. See iprt/stream.h. */
#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
# define RTFILE_LINEFEED    "\r\n"
#else
# define RTFILE_LINEFEED    "\n"
#endif

/** Platform specific native standard input "handle". */
#ifdef RT_OS_WINDOWS
# define RTFILE_NATIVE_STDIN ((uint32_t)-10)
#else
# define RTFILE_NATIVE_STDIN 0
#endif

/** Platform specific native standard out "handle". */
#ifdef RT_OS_WINDOWS
# define RTFILE_NATIVE_STDOUT ((uint32_t)-11)
#else
# define RTFILE_NATIVE_STDOUT 1
#endif

/** Platform specific native standard error "handle". */
#ifdef RT_OS_WINDOWS
# define RTFILE_NATIVE_STDERR ((uint32_t)-12)
#else
# define RTFILE_NATIVE_STDERR 2
#endif


/**
 * Checks if the specified file name exists and is a regular file.
 *
 * Symbolic links will be resolved.
 *
 * @returns true if it's a regular file, false if it isn't.
 * @param   pszPath         The path to the file.
 *
 * @sa      RTDirExists, RTPathExists, RTSymlinkExists.
 */
RTDECL(bool) RTFileExists(const char *pszPath);

/**
 * Queries the size of a file, given the path to it.
 *
 * Symbolic links will be resolved.
 *
 * @returns IPRT status code.
 * @param   pszPath         The path to the file.
 * @param   pcbFile         Where to return the file size (bytes).
 *
 * @sa      RTFileGetSize, RTPathQueryInfoEx.
 */
RTDECL(int) RTFileQuerySize(const char *pszPath, uint64_t *pcbFile);


/** @name Open flags
 * @{ */
/** Open the file with read access. */
#define RTFILE_O_READ                   UINT32_C(0x00000001)
/** Open the file with write access. */
#define RTFILE_O_WRITE                  UINT32_C(0x00000002)
/** Open the file with read & write access. */
#define RTFILE_O_READWRITE              UINT32_C(0x00000003)
/** The file access mask.
 * @remarks The value 0 is invalid. */
#define RTFILE_O_ACCESS_MASK            UINT32_C(0x00000003)

/** Open file in APPEND mode, so all writes to the file handle will
 * append data at the end of the file.
 * @remarks It is ignored if write access is not requested, that is
 *          RTFILE_O_WRITE is not set. */
#define RTFILE_O_APPEND                 UINT32_C(0x00000004)
                                     /* UINT32_C(0x00000008) is unused atm. */

/** Sharing mode: deny none. */
#define RTFILE_O_DENY_NONE              UINT32_C(0x00000080)
/** Sharing mode: deny read. */
#define RTFILE_O_DENY_READ              UINT32_C(0x00000010)
/** Sharing mode: deny write. */
#define RTFILE_O_DENY_WRITE             UINT32_C(0x00000020)
/** Sharing mode: deny read and write. */
#define RTFILE_O_DENY_READWRITE         UINT32_C(0x00000030)
/** Sharing mode: deny all. */
#define RTFILE_O_DENY_ALL               RTFILE_O_DENY_READWRITE
/** Sharing mode: do NOT deny delete (NT).
 * @remarks This might not be implemented on all platforms, and will be
 *          defaulted & ignored on those.
 */
#define RTFILE_O_DENY_NOT_DELETE        UINT32_C(0x00000040)
/** Sharing mode mask. */
#define RTFILE_O_DENY_MASK              UINT32_C(0x000000f0)

/** Action: Open an existing file (the default action). */
#define RTFILE_O_OPEN                   UINT32_C(0x00000700)
/** Action: Create a new file or open an existing one. */
#define RTFILE_O_OPEN_CREATE            UINT32_C(0x00000100)
/** Action: Create a new a file. */
#define RTFILE_O_CREATE                 UINT32_C(0x00000200)
/** Action: Create a new file or replace an existing one. */
#define RTFILE_O_CREATE_REPLACE         UINT32_C(0x00000300)
/** Action mask. */
#define RTFILE_O_ACTION_MASK            UINT32_C(0x00000700)

/** Turns off indexing of files on Windows hosts, *CREATE* only.
 * @remarks Window only. */
#define RTFILE_O_NOT_CONTENT_INDEXED    UINT32_C(0x00000800)
/** Truncate the file.
 * @remarks This will not truncate files opened for read-only.
 * @remarks The trunction doesn't have to be atomically, so anyone else opening
 *          the file may be racing us. The caller is responsible for not causing
 *          this race. */
#define RTFILE_O_TRUNCATE               UINT32_C(0x00001000)
/** Make the handle inheritable on RTProcessCreate(/exec). */
#define RTFILE_O_INHERIT                UINT32_C(0x00002000)
/** Open file in non-blocking mode - non-portable.
 * @remarks This flag may not be supported on all platforms, in which case it's
 *          considered an invalid parameter. */
#define RTFILE_O_NON_BLOCK              UINT32_C(0x00004000)
/** Write through directly to disk. Workaround to avoid iSCSI
 * initiator deadlocks on Windows hosts.
 * @remarks This might not be implemented on all platforms, and will be ignored
 *          on those. */
#define RTFILE_O_WRITE_THROUGH          UINT32_C(0x00008000)

/** Attribute access: Attributes can be read if the file is being opened with
 * read access, and can be written with write access. */
#define RTFILE_O_ACCESS_ATTR_DEFAULT    UINT32_C(0x00000000)
/** Attribute access: Attributes can be read.
 * @remarks Windows only.  */
#define RTFILE_O_ACCESS_ATTR_READ       UINT32_C(0x00010000)
/** Attribute access: Attributes can be written.
 * @remarks Windows only.  */
#define RTFILE_O_ACCESS_ATTR_WRITE      UINT32_C(0x00020000)
/** Attribute access: Attributes can be both read & written.
 * @remarks Windows only.  */
#define RTFILE_O_ACCESS_ATTR_READWRITE  UINT32_C(0x00030000)
/** Attribute access: The file attributes access mask.
 * @remarks Windows only.  */
#define RTFILE_O_ACCESS_ATTR_MASK       UINT32_C(0x00030000)

/** Open file for async I/O
 * @remarks This flag may not be needed on all platforms, and will be ignored on
 *          those. */
#define RTFILE_O_ASYNC_IO               UINT32_C(0x00040000)

/** Disables caching.
 *
 * Useful when using very big files which might bring the host I/O scheduler to
 * its knees during high I/O load.
 *
 * @remarks This flag might impose restrictions
 *          on the buffer alignment, start offset and/or transfer size.
 *
 *          On Linux the buffer needs to be aligned to the 512 sector
 *          boundary.
 *
 *          On Windows the FILE_FLAG_NO_BUFFERING is used (see
 *          http://msdn.microsoft.com/en-us/library/cc644950(VS.85).aspx ).
 *          The buffer address, the transfer size and offset needs to be aligned
 *          to the sector size of the volume.  Furthermore FILE_APPEND_DATA is
 *          disabled.  To write beyond the size of file use RTFileSetSize prior
 *          writing the data to the file.
 *
 *          This flag does not work on Solaris if the target filesystem is ZFS.
 *          RTFileOpen will return an error with that configuration.  When used
 *          with UFS the same alginment restrictions apply like Linux and
 *          Windows.
 *
 * @remarks This might not be implemented on all platforms, and will be ignored
 *          on those.
 */
#define RTFILE_O_NO_CACHE               UINT32_C(0x00080000)

/** Don't allow symbolic links as part of the path.
 * @remarks this flag is currently not implemented and will be ignored. */
#define RTFILE_O_NO_SYMLINKS            UINT32_C(0x20000000)

/** Unix file mode mask for use when creating files. */
#define RTFILE_O_CREATE_MODE_MASK       UINT32_C(0x1ff00000)
/** The number of bits to shift to get the file mode mask.
 * To extract it: (fFlags & RTFILE_O_CREATE_MODE_MASK) >> RTFILE_O_CREATE_MODE_SHIFT.
 */
#define RTFILE_O_CREATE_MODE_SHIFT      20

                                      /* UINT32_C(0x40000000)
                                     and UINT32_C(0x80000000) are unused atm. */

/** Mask of all valid flags.
 * @remark  This doesn't validate the access mode properly.
 */
#define RTFILE_O_VALID_MASK             UINT32_C(0x3ffffff7)

/** @} */


#ifdef IN_RING3
/**
 * Force the use of open flags for all files opened after the setting is
 * changed. The caller is responsible for not causing races with RTFileOpen().
 *
 * @returns iprt status code.
 * @param   fOpenForAccess  Access mode to which the set/mask settings apply.
 * @param   fSet            Open flags to be forced set.
 * @param   fMask           Open flags to be masked out.
 */
RTR3DECL(int)  RTFileSetForceFlags(unsigned fOpenForAccess, unsigned fSet, unsigned fMask);
#endif /* IN_RING3 */

/**
 * Open a file.
 *
 * @returns iprt status code.
 * @param   pFile           Where to store the handle to the opened file.
 * @param   pszFilename     Path to the file which is to be opened. (UTF-8)
 * @param   fOpen           Open flags, i.e a combination of the RTFILE_O_* defines.
 *                          The ACCESS, ACTION and DENY flags are mandatory!
 */
RTDECL(int)  RTFileOpen(PRTFILE pFile, const char *pszFilename, uint64_t fOpen);

/**
 * Open a file given as a format string.
 *
 * @returns iprt status code.
 * @param   pFile           Where to store the handle to the opened file.
 * @param   fOpen           Open flags, i.e a combination of the RTFILE_O_* defines.
 *                          The ACCESS, ACTION and DENY flags are mandatory!
 * @param   pszFilenameFmt  Format string givin the path to the file which is to
 *                          be opened. (UTF-8)
 * @param   ...             Arguments to the format string.
 */
RTDECL(int)  RTFileOpenF(PRTFILE pFile, uint64_t fOpen, const char *pszFilenameFmt, ...);

/**
 * Open a file given as a format string.
 *
 * @returns iprt status code.
 * @param   pFile           Where to store the handle to the opened file.
 * @param   fOpen           Open flags, i.e a combination of the RTFILE_O_* defines.
 *                          The ACCESS, ACTION and DENY flags are mandatory!
 * @param   pszFilenameFmt  Format string givin the path to the file which is to
 *                          be opened. (UTF-8)
 * @param   va              Arguments to the format string.
 */
RTDECL(int)  RTFileOpenV(PRTFILE pFile, uint64_t fOpen, const char *pszFilenameFmt, va_list va);

/**
 * Open the bit bucket (aka /dev/null or nul).
 *
 * @returns IPRT status code.
 * @param   phFile          Where to store the handle to the opened file.
 * @param   fAccess         The desired access only, i.e. read, write or both.
 */
RTDECL(int)  RTFileOpenBitBucket(PRTFILE phFile, uint64_t fAccess);

/**
 * Close a file opened by RTFileOpen().
 *
 * @returns iprt status code.
 * @param   File            The file handle to close.
 */
RTDECL(int)  RTFileClose(RTFILE File);

/**
 * Creates an IPRT file handle from a native one.
 *
 * @returns IPRT status code.
 * @param   pFile           Where to store the IPRT file handle.
 * @param   uNative         The native handle.
 */
RTDECL(int) RTFileFromNative(PRTFILE pFile, RTHCINTPTR uNative);

/**
 * Gets the native handle for an IPRT file handle.
 *
 * @return  The native handle.
 * @param   File            The IPRT file handle.
 */
RTDECL(RTHCINTPTR) RTFileToNative(RTFILE File);

/**
 * Delete a file.
 *
 * @returns iprt status code.
 * @param   pszFilename     Path to the file which is to be deleted. (UTF-8)
 * @todo    This is a RTPath api!
 */
RTDECL(int)  RTFileDelete(const char *pszFilename);

/** @name Seek flags.
 * @{ */
/** Seek from the start of the file. */
#define RTFILE_SEEK_BEGIN     0x00
/** Seek from the current file position. */
#define RTFILE_SEEK_CURRENT   0x01
/** Seek from the end of the file. */
#define RTFILE_SEEK_END       0x02
/** @internal */
#define RTFILE_SEEK_FIRST     RTFILE_SEEK_BEGIN
/** @internal */
#define RTFILE_SEEK_LAST      RTFILE_SEEK_END
/** @} */


/**
 * Changes the read & write position in a file.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   offSeek     Offset to seek.
 * @param   uMethod     Seek method, i.e. one of the RTFILE_SEEK_* defines.
 * @param   poffActual  Where to store the new file position.
 *                      NULL is allowed.
 */
RTDECL(int)  RTFileSeek(RTFILE File, int64_t offSeek, unsigned uMethod, uint64_t *poffActual);

/**
 * Read bytes from a file.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   pvBuf       Where to put the bytes we read.
 * @param   cbToRead    How much to read.
 * @param   *pcbRead    How much we actually read .
 *                      If NULL an error will be returned for a partial read.
 */
RTDECL(int)  RTFileRead(RTFILE File, void *pvBuf, size_t cbToRead, size_t *pcbRead);

/**
 * Read bytes from a file at a given offset.
 * This function may modify the file position.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   off         Where to read.
 * @param   pvBuf       Where to put the bytes we read.
 * @param   cbToRead    How much to read.
 * @param   *pcbRead    How much we actually read .
 *                      If NULL an error will be returned for a partial read.
 */
RTDECL(int)  RTFileReadAt(RTFILE File, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead);

/**
 * Write bytes to a file.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   pvBuf       What to write.
 * @param   cbToWrite   How much to write.
 * @param   *pcbWritten How much we actually wrote.
 *                      If NULL an error will be returned for a partial write.
 */
RTDECL(int)  RTFileWrite(RTFILE File, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);

/**
 * Write bytes to a file at a given offset.
 * This function may modify the file position.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   off         Where to write.
 * @param   pvBuf       What to write.
 * @param   cbToWrite   How much to write.
 * @param   *pcbWritten How much we actually wrote.
 *                      If NULL an error will be returned for a partial write.
 */
RTDECL(int)  RTFileWriteAt(RTFILE File, RTFOFF off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);

/**
 * Flushes the buffers for the specified file.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 */
RTDECL(int)  RTFileFlush(RTFILE File);

/**
 * Set the size of the file.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   cbSize      The new file size.
 */
RTDECL(int)  RTFileSetSize(RTFILE File, uint64_t cbSize);

/**
 * Query the size of the file.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   pcbSize     Where to store the filesize.
 */
RTDECL(int)  RTFileGetSize(RTFILE File, uint64_t *pcbSize);

/**
 * Determine the maximum file size.
 *
 * @returns The max size of the file.
 *          -1 on failure, the file position is undefined.
 * @param   File        Handle to the file.
 * @see     RTFileGetMaxSizeEx.
 */
RTDECL(RTFOFF) RTFileGetMaxSize(RTFILE File);

/**
 * Determine the maximum file size.
 *
 * @returns IPRT status code.
 * @param   File        Handle to the file.
 * @param   pcbMax      Where to store the max file size.
 * @see     RTFileGetMaxSize.
 */
RTDECL(int) RTFileGetMaxSizeEx(RTFILE File, PRTFOFF pcbMax);

/**
 * Determine the maximum file size depending on the file system the file is stored on.
 *
 * @returns The max size of the file.
 *          -1 on failure.
 * @param   File        Handle to the file.
 */
RTDECL(RTFOFF) RTFileGetMaxSize(RTFILE File);

/**
 * Gets the current file position.
 *
 * @returns File offset.
 * @returns ~0UUL on failure.
 * @param   File        Handle to the file.
 */
RTDECL(uint64_t)  RTFileTell(RTFILE File);

/**
 * Checks if the supplied handle is valid.
 *
 * @returns true if valid.
 * @returns false if invalid.
 * @param   File        The file handle
 */
RTDECL(bool) RTFileIsValid(RTFILE File);

/**
 * Copies a file.
 *
 * @returns VERR_ALREADY_EXISTS if the destination file exists.
 * @returns VBox Status code.
 *
 * @param   pszSrc      The path to the source file.
 * @param   pszDst      The path to the destination file.
 *                      This file will be created.
 */
RTDECL(int) RTFileCopy(const char *pszSrc, const char *pszDst);

/**
 * Copies a file given the handles to both files.
 *
 * @returns VBox Status code.
 *
 * @param   FileSrc     The source file. The file position is unaltered.
 * @param   FileDst     The destination file.
 *                      On successful returns the file position is at the end of the file.
 *                      On failures the file position and size is undefined.
 */
RTDECL(int) RTFileCopyByHandles(RTFILE FileSrc, RTFILE FileDst);

/** Flags for RTFileCopyEx().
 * @{ */
/** Do not use RTFILE_O_DENY_WRITE on the source file to allow for copying files opened for writing. */
#define RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE  RT_BIT(0)
/** Do not use RTFILE_O_DENY_WRITE on the target file. */
#define RTFILECOPY_FLAGS_NO_DST_DENY_WRITE  RT_BIT(1)
/** Do not use RTFILE_O_DENY_WRITE on either of the two files. */
#define RTFILECOPY_FLAGS_NO_DENY_WRITE      ( RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE | RTFILECOPY_FLAGS_NO_DST_DENY_WRITE )
/** */
#define RTFILECOPY_FLAGS_MASK               UINT32_C(0x00000003)
/** @} */

/**
 * Copies a file.
 *
 * @returns VERR_ALREADY_EXISTS if the destination file exists.
 * @returns VBox Status code.
 *
 * @param   pszSrc      The path to the source file.
 * @param   pszDst      The path to the destination file.
 *                      This file will be created.
 * @param   fFlags      Flags (RTFILECOPY_*).
 * @param   pfnProgress Pointer to callback function for reporting progress.
 * @param   pvUser      User argument to pass to pfnProgress along with the completion percentage.
 */
RTDECL(int) RTFileCopyEx(const char *pszSrc, const char *pszDst, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser);

/**
 * Copies a file given the handles to both files and
 * provide progress callbacks.
 *
 * @returns IPRT status code.
 *
 * @param   FileSrc     The source file. The file position is unaltered.
 * @param   FileDst     The destination file.
 *                      On successful returns the file position is at the end of the file.
 *                      On failures the file position and size is undefined.
 * @param   pfnProgress Pointer to callback function for reporting progress.
 * @param   pvUser      User argument to pass to pfnProgress along with the completion percentage.
 */
RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser);

/**
 * Renames a file.
 *
 * Identical to RTPathRename except that it will ensure that the source is not a directory.
 *
 * @returns IPRT status code.
 * @returns VERR_ALREADY_EXISTS if the destination file exists.
 *
 * @param   pszSrc      The path to the source file.
 * @param   pszDst      The path to the destination file.
 *                      This file will be created.
 * @param   fRename     See RTPathRename.
 */
RTDECL(int) RTFileRename(const char *pszSrc, const char *pszDst, unsigned fRename);


/** @name RTFileMove flags (bit masks).
 * @{ */
/** Replace destination file if present. */
#define RTFILEMOVE_FLAGS_REPLACE      0x1
/** Don't allow symbolic links as part of the path.
 * @remarks this flag is currently not implemented and will be ignored. */
#define RTFILEMOVE_FLAGS_NO_SYMLINKS  0x2
/** @} */

/**
 * Moves a file.
 *
 * RTFileMove differs from RTFileRename in that it works across volumes.
 *
 * @returns IPRT status code.
 * @returns VERR_ALREADY_EXISTS if the destination file exists.
 *
 * @param   pszSrc      The path to the source file.
 * @param   pszDst      The path to the destination file.
 *                      This file will be created.
 * @param   fMove       A combination of the RTFILEMOVE_* flags.
 */
RTDECL(int) RTFileMove(const char *pszSrc, const char *pszDst, unsigned fMove);


/**
 * Creates a new file with a unique name using the given template.
 *
 * One or more trailing X'es in the template will be replaced by random alpha
 * numeric characters until a RTFileOpen with RTFILE_O_CREATE succeeds or we
 * run out of patience.
 * For instance:
 *          "/tmp/myprog-XXXXXX"
 *
 * As an alternative to trailing X'es, it is possible to put 3 or more X'es
 * somewhere inside the file name. In the following string only the last
 * bunch of X'es will be modified:
 *          "/tmp/myprog-XXX-XXX.tmp"
 *
 * @returns iprt status code.
 * @param   pszTemplate     The file name template on input. The actual file
 *                          name on success. Empty string on failure.
 * @param   fMode           The mode to create the file with.  Use 0600 unless
 *                          you have reason not to.
 */
RTDECL(int) RTFileCreateTemp(char *pszTemplate, RTFMODE fMode);

/**
 * Secure version of @a RTFileCreateTemp with a fixed mode of 0600.
 *
 * This function behaves in the same way as @a RTFileCreateTemp with two
 * additional points.  Firstly the mode is fixed to 0600.  Secondly it will
 * fail if it is not possible to perform the operation securely.  Possible
 * reasons include that the file could be removed by another unprivileged
 * user before it is used (e.g. if is created in a non-sticky /tmp directory)
 * or that the path contains symbolic links which another unprivileged user
 * could manipulate; however the exact criteria will be specified on a
 * platform-by-platform basis as platform support is added.
 * @see RTPathIsSecure for the current list of criteria.
 * @returns iprt status code.
 * @returns VERR_NOT_SUPPORTED if the interface can not be supported on the
 *                             current platform at this time.
 * @returns VERR_INSECURE      if the file could not be created securely.
 * @param   pszTemplate        The file name template on input. The actual
 *                             file name on success. Empty string on failure.
 */
RTDECL(int) RTFileCreateTempSecure(char *pszTemplate);


/** @page   pg_rt_filelock      RT File locking API description
 *
 * File locking general rules:
 *
 * Region to lock or unlock can be located beyond the end of file, this can be used for
 * growing files.
 * Read (or Shared) locks can be acquired held by an unlimited number of processes at the
 * same time, but a Write (or Exclusive) lock can only be acquired by one process, and
 * cannot coexist with a Shared lock. To acquire a Read lock, a process must wait until
 * there are no processes holding any Write locks. To acquire a Write lock, a process must
 * wait until there are no processes holding either kind of lock.
 * By default, RTFileLock and RTFileChangeLock calls returns error immediately if the lock
 * can't be acquired due to conflict with other locks, however they can be called in wait mode.
 *
 * Differences in implementation:
 *
 * Win32, OS/2: Locking is mandatory, since locks are enforced by the operating system.
 * I.e. when file region is locked in Read mode, any write in it will fail; in case of Write
 * lock - region can be read and writed only by lock's owner.
 *
 * Win32: File size change (RTFileSetSize) is not controlled by locking at all (!) in the
 * operation system. Also see comments to RTFileChangeLock API call.
 *
 * Linux/Posix: By default locks in Unixes are advisory. This means that cooperating processes
 * may use locks to coordinate access to a file between themselves, but programs are also free
 * to ignore locks and access the file in any way they choose to.
 *
 * Additional reading:
 *     http://en.wikipedia.org/wiki/File_locking
 *     http://unixhelp.ed.ac.uk/CGI/man-cgi?fcntl+2
 *     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/lockfileex.asp
 */

/** @name Lock flags (bit masks).
 * @{ */
/** Read access, can be shared with others. */
#define RTFILE_LOCK_READ            0x00
/** Write access, one at a time. */
#define RTFILE_LOCK_WRITE           0x01
/** Don't wait for other locks to be released. */
#define RTFILE_LOCK_IMMEDIATELY     0x00
/** Wait till conflicting locks have been released. */
#define RTFILE_LOCK_WAIT            0x02
/** Valid flags mask */
#define RTFILE_LOCK_MASK            0x03
/** @} */


/**
 * Locks a region of file for read (shared) or write (exclusive) access.
 *
 * @returns iprt status code.
 * @returns VERR_FILE_LOCK_VIOLATION if lock can't be acquired.
 * @param   File        Handle to the file.
 * @param   fLock       Lock method and flags, see RTFILE_LOCK_* defines.
 * @param   offLock     Offset of lock start.
 * @param   cbLock      Length of region to lock, may overlap the end of file.
 */
RTDECL(int)  RTFileLock(RTFILE File, unsigned fLock, int64_t offLock, uint64_t cbLock);

/**
 * Changes a lock type from read to write or from write to read.
 * The region to type change must correspond exactly to an existing locked region.
 * If change can't be done due to locking conflict and non-blocking mode is used, error is
 * returned and lock keeps its state (see next warning).
 *
 * WARNING: win32 implementation of this call is not atomic, it transforms to a pair of
 * calls RTFileUnlock and RTFileLock. Potentially the previously acquired lock can be
 * lost, i.e. function is called in non-blocking mode, previous lock is freed, new lock can't
 * be acquired, and old lock (previous state) can't be acquired back too. This situation
 * may occurs _only_ if the other process is acquiring a _write_ lock in blocking mode or
 * in race condition with the current call.
 * In this very bad case special error code VERR_FILE_LOCK_LOST will be returned.
 *
 * @returns iprt status code.
 * @returns VERR_FILE_NOT_LOCKED if region was not locked.
 * @returns VERR_FILE_LOCK_VIOLATION if lock type can't be changed, lock remains its type.
 * @returns VERR_FILE_LOCK_LOST if lock was lost, we haven't this lock anymore :(
 * @param   File        Handle to the file.
 * @param   fLock       Lock method and flags, see RTFILE_LOCK_* defines.
 * @param   offLock     Offset of lock start.
 * @param   cbLock      Length of region to lock, may overlap the end of file.
 */
RTDECL(int)  RTFileChangeLock(RTFILE File, unsigned fLock, int64_t offLock, uint64_t cbLock);

/**
 * Unlocks previously locked region of file.
 * The region to unlock must correspond exactly to an existing locked region.
 *
 * @returns iprt status code.
 * @returns VERR_FILE_NOT_LOCKED if region was not locked.
 * @param   File        Handle to the file.
 * @param   offLock     Offset of lock start.
 * @param   cbLock      Length of region to unlock, may overlap the end of file.
 */
RTDECL(int)  RTFileUnlock(RTFILE File, int64_t offLock, uint64_t cbLock);


/**
 * Query information about an open file.
 *
 * @returns iprt status code.
 *
 * @param   File                    Handle to the file.
 * @param   pObjInfo                Object information structure to be filled on successful return.
 * @param   enmAdditionalAttribs    Which set of additional attributes to request.
 *                                  Use RTFSOBJATTRADD_NOTHING if this doesn't matter.
 */
RTDECL(int) RTFileQueryInfo(RTFILE File, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs);

/**
 * Changes one or more of the timestamps associated of file system object.
 *
 * @returns iprt status code.
 * @retval  VERR_NOT_SUPPORTED is returned if the operation isn't supported by
 *          the OS.
 *
 * @param   File                Handle to the file.
 * @param   pAccessTime         Pointer to the new access time. NULL if not to be changed.
 * @param   pModificationTime   Pointer to the new modifcation time. NULL if not to be changed.
 * @param   pChangeTime         Pointer to the new change time. NULL if not to be changed.
 * @param   pBirthTime          Pointer to the new time of birth. NULL if not to be changed.
 *
 * @remark  The file system might not implement all these time attributes,
 *          the API will ignore the ones which aren't supported.
 *
 * @remark  The file system might not implement the time resolution
 *          employed by this interface, the time will be chopped to fit.
 *
 * @remark  The file system may update the change time even if it's
 *          not specified.
 *
 * @remark  POSIX can only set Access & Modification and will always set both.
 */
RTDECL(int) RTFileSetTimes(RTFILE File, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
                           PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime);

/**
 * Gets one or more of the timestamps associated of file system object.
 *
 * @returns iprt status code.
 * @param   File                Handle to the file.
 * @param   pAccessTime         Where to store the access time. NULL is ok.
 * @param   pModificationTime   Where to store the modifcation time. NULL is ok.
 * @param   pChangeTime         Where to store the change time. NULL is ok.
 * @param   pBirthTime          Where to store the time of birth. NULL is ok.
 *
 * @remark  This is wrapper around RTFileQueryInfo() and exists to complement RTFileSetTimes().
 */
RTDECL(int) RTFileGetTimes(RTFILE File, PRTTIMESPEC pAccessTime, PRTTIMESPEC pModificationTime,
                           PRTTIMESPEC pChangeTime, PRTTIMESPEC pBirthTime);

/**
 * Changes the mode flags of an open file.
 *
 * The API requires at least one of the mode flag sets (Unix/Dos) to
 * be set. The type is ignored.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   fMode       The new file mode, see @ref grp_rt_fs for details.
 */
RTDECL(int) RTFileSetMode(RTFILE File, RTFMODE fMode);

/**
 * Gets the mode flags of an open file.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   pfMode      Where to store the file mode, see @ref grp_rt_fs for details.
 *
 * @remark  This is wrapper around RTFileQueryInfo()
 *          and exists to complement RTFileSetMode().
 */
RTDECL(int) RTFileGetMode(RTFILE File, uint32_t *pfMode);

/**
 * Changes the owner and/or group of an open file.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   uid         The new file owner user id.  Pass NIL_RTUID to leave
 *                      this unchanged.
 * @param   gid         The new group id.  Pass NIL_RTGID to leave this
 *                      unchanged.
 */
RTDECL(int) RTFileSetOwner(RTFILE File, uint32_t uid, uint32_t gid);

/**
 * Gets the owner and/or group of an open file.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   pUid        Where to store the owner user id. NULL is ok.
 * @param   pGid        Where to store the group id. NULL is ok.
 *
 * @remark  This is wrapper around RTFileQueryInfo() and exists to complement RTFileGetOwner().
 */
RTDECL(int) RTFileGetOwner(RTFILE File, uint32_t *pUid, uint32_t *pGid);

/**
 * Executes an IOCTL on a file descriptor.
 *
 * This function is currently only available in L4 and posix environments.
 * Attemps at calling it from code shared with any other platforms will break things!
 *
 * The rational for defining this API is to simplify L4 porting of audio drivers,
 * and to remove some of the assumptions on RTFILE being a file descriptor on
 * platforms using the posix file implementation.
 *
 * @returns iprt status code.
 * @param   File        Handle to the file.
 * @param   iRequest    IOCTL request to carry out.
 * @param   pvData      IOCTL data.
 * @param   cbData      Size of the IOCTL data.
 * @param   piRet       Return value of the IOCTL request.
 */
RTDECL(int) RTFileIoCtl(RTFILE File, unsigned long ulRequest, void *pvData, unsigned cbData, int *piRet);

/**
 * Query the sizes of a filesystem.
 *
 * @returns iprt status code.
 * @retval  VERR_NOT_SUPPORTED is returned if the operation isn't supported by
 *          the OS.
 *
 * @param   hFile       The file handle.
 * @param   pcbTotal    Where to store the total filesystem space. (Optional)
 * @param   pcbFree     Where to store the remaining free space in the filesystem. (Optional)
 * @param   pcbBlock    Where to store the block size. (Optional)
 * @param   pcbSector   Where to store the sector size. (Optional)
 *
 * @sa      RTFsQuerySizes
 */
RTDECL(int) RTFileQueryFsSizes(RTFILE hFile, PRTFOFF pcbTotal, RTFOFF *pcbFree,
                               uint32_t *pcbBlock, uint32_t *pcbSector);

/**
 * Reads the file into memory.
 *
 * The caller must free the memory using RTFileReadAllFree().
 *
 * @returns IPRT status code.
 * @param   pszFilename     The name of the file.
 * @param   ppvFile         Where to store the pointer to the memory on successful return.
 * @param   pcbFile         Where to store the size of the returned memory.
 *
 * @remarks Note that this function may be implemented using memory mapping, which means
 *          that the file may remain open until RTFileReadAllFree() is called. It also
 *          means that the return memory may reflect the state of the file when it's
 *          accessed instead of when this call was done. So, in short, don't use this
 *          API for volatile files, then rather use the extended variant with a
 *          yet-to-be-defined flag.
 */
RTDECL(int) RTFileReadAll(const char *pszFilename, void **ppvFile, size_t *pcbFile);

/**
 * Reads the file into memory.
 *
 * The caller must free the memory using RTFileReadAllFree().
 *
 * @returns IPRT status code.
 * @param   pszFilename     The name of the file.
 * @param   off             The offset to start reading at.
 * @param   cbMax           The maximum number of bytes to read into memory. Specify RTFOFF_MAX
 *                          to read to the end of the file.
 * @param   fFlags          See RTFILE_RDALL_*.
 * @param   ppvFile         Where to store the pointer to the memory on successful return.
 * @param   pcbFile         Where to store the size of the returned memory.
 *
 * @remarks See the remarks for RTFileReadAll.
 */
RTDECL(int) RTFileReadAllEx(const char *pszFilename, RTFOFF off, RTFOFF cbMax, uint32_t fFlags, void **ppvFile, size_t *pcbFile);

/**
 * Reads the file into memory.
 *
 * The caller must free the memory using RTFileReadAllFree().
 *
 * @returns IPRT status code.
 * @param   File            The handle to the file.
 * @param   ppvFile         Where to store the pointer to the memory on successful return.
 * @param   pcbFile         Where to store the size of the returned memory.
 *
 * @remarks See the remarks for RTFileReadAll.
 */
RTDECL(int) RTFileReadAllByHandle(RTFILE File, void **ppvFile, size_t *pcbFile);

/**
 * Reads the file into memory.
 *
 * The caller must free the memory using RTFileReadAllFree().
 *
 * @returns IPRT status code.
 * @param   File            The handle to the file.
 * @param   off             The offset to start reading at.
 * @param   cbMax           The maximum number of bytes to read into memory. Specify RTFOFF_MAX
 *                          to read to the end of the file.
 * @param   fFlags          See RTFILE_RDALL_*.
 * @param   ppvFile         Where to store the pointer to the memory on successful return.
 * @param   pcbFile         Where to store the size of the returned memory.
 *
 * @remarks See the remarks for RTFileReadAll.
 */
RTDECL(int) RTFileReadAllByHandleEx(RTFILE File, RTFOFF off, RTFOFF cbMax, uint32_t fFlags, void **ppvFile, size_t *pcbFile);

/**
 * Frees the memory returned by one of the RTFileReadAll(), RTFileReadAllEx(),
 * RTFileReadAllByHandle() and RTFileReadAllByHandleEx() functions.
 *
 * @param   pvFile          Pointer to the memory.
 * @param   cbFile          The size of the memory.
 */
RTDECL(void) RTFileReadAllFree(void *pvFile, size_t cbFile);

/** @name RTFileReadAllEx and RTFileReadAllHandleEx flags
 * The open flags are ignored by RTFileReadAllHandleEx.
 * @{ */
#define RTFILE_RDALL_O_DENY_NONE            RTFILE_O_DENY_NONE
#define RTFILE_RDALL_O_DENY_READ            RTFILE_O_DENY_READ
#define RTFILE_RDALL_O_DENY_WRITE           RTFILE_O_DENY_WRITE
#define RTFILE_RDALL_O_DENY_READWRITE       RTFILE_O_DENY_READWRITE
#define RTFILE_RDALL_O_DENY_ALL             RTFILE_O_DENY_ALL
#define RTFILE_RDALL_O_DENY_NOT_DELETE      RTFILE_O_DENY_NOT_DELETE
#define RTFILE_RDALL_O_DENY_MASK            RTFILE_O_DENY_MASK
/** Mask of valid flags. */
#define RTFILE_RDALL_VALID_MASK             RTFILE_RDALL_O_DENY_MASK
/** @} */


#ifdef IN_RING3

/** @page pg_rt_asyncio RT File async I/O API
 *
 * File operations are usually blocking the calling thread until
 * they completed making it impossible to let the thread do anything
 * else in-between.
 * The RT File async I/O API provides an easy and efficient way to
 * access files asynchronously using the native facilities provided
 * by each operating system.
 *
 * @section sec_rt_asyncio_objects       Objects
 *
 * There are two objects used in this API.
 * The first object is the request. A request contains every information
 * needed two complete the file operation successfully like the start offset
 * and pointer to the source or destination buffer.
 * Requests are created with RTFileAioReqCreate() and destroyed with
 * RTFileAioReqDestroy().
 * Because creating a request may require allocating various operating
 * system dependent resources and may be quite expensive it is possible
 * to use a request more than once to save CPU cycles.
 * A request is constructed with either RTFileAioReqPrepareRead()
 * which will set up a request to read from the given file or
 * RTFileAioReqPrepareWrite() which will write to a given file.
 *
 * The second object is the context. A file is associated with a context
 * and requests for this file may complete only on the context the file
 * was associated with and not on the context given in RTFileAioCtxSubmit()
 * (see below for further information).
 * RTFileAioCtxWait() is used to wait for completion of requests which were
 * associated with the context. While waiting for requests the thread can not
 * respond to global state changes. That's why the API provides a way to let
 * RTFileAioCtxWait() return immediately no matter how many requests
 * have finished through RTFileAioCtxWakeup(). The return code is
 * VERR_INTERRUPTED to let the thread know that he got interrupted.
 *
 * @section sec_rt_asyncio_request_states  Request states
 *
 * Created:
 * After a request was created with RTFileAioReqCreate() it is in the same state
 * like it just completed successfully. RTFileAioReqGetRC() will return VINF_SUCCESS
 * and a transfer size of 0. RTFileAioReqGetUser() will return NULL. The request can be
 * destroyed RTFileAioReqDestroy(). It is also allowed to prepare a the request
 * for a data transfer with the RTFileAioReqPrepare* methods.
 * Calling any other method like RTFileAioCtxSubmit() will return VERR_FILE_AIO_NOT_PREPARED
 * and RTFileAioReqCancel() returns VERR_FILE_AIO_NOT_SUBMITTED.
 *
 * Prepared:
 * A request will enter this state if one of the RTFileAioReqPrepare* methods
 * is called. In this state you can still destroy and retrieve the user data
 * associated with the request but trying to cancel the request or getting
 * the result of the operation will return VERR_FILE_AIO_NOT_SUBMITTED.
 *
 * Submitted:
 * A prepared request can be submitted with RTFileAioCtxSubmit(). If the operation
 * succeeds it is not allowed to touch the request or free any resources until
 * it completed through RTFileAioCtxWait(). The only allowed method is RTFileAioReqCancel()
 * which tries to cancel the request. The request will go into the completed state
 * and RTFileAioReqGetRC() will return VERR_FILE_AIO_CANCELED.
 * If the request completes not matter if successfully or with an error it will
 * switch into the completed state. RTFileReqDestroy() fails if the given request
 * is in this state.
 *
 * Completed:
 * The request will be in this state after it completed and returned through
 * RTFileAioCtxWait(). RTFileAioReqGetRC() returns the final result code
 * and the number of bytes transferred.
 * The request can be used for new data transfers.
 *
 * @section sec_rt_asyncio_threading       Threading
 *
 * The API is a thin wrapper around the specific host OS APIs and therefore
 * relies on the thread safety of the underlying API.
 * The interesting functions with regards to thread safety are RTFileAioCtxSubmit()
 * and RTFileAioCtxWait(). RTFileAioCtxWait() must not be called from different
 * threads at the same time with the same context handle. The same applies to
 * RTFileAioCtxSubmit(). However it is possible to submit new requests from a different
 * thread while waiting for completed requests on another thread with RTFileAioCtxWait().
 *
 * @section sec_rt_asyncio_implementations  Differences in implementation
 *
 * Because the host APIs are quite different on every OS and every API has other limitations
 * there are some things to consider to make the code as portable as possible.
 *
 * The first restriction at the moment is that every buffer has to be aligned to a 512 byte boundary.
 * This limitation comes from the Linux io_* interface. To use the interface the file
 * must be opened with O_DIRECT. This flag disables the kernel cache too which may
 * degrade performance but is unfortunately the only way to make asynchronous
 * I/O work till today (if O_DIRECT is omitted io_submit will revert to sychronous behavior
 * and will return when the requests finished and when they are queued).
 * It is mostly used by DBMS which do theire own caching.
 * Furthermore there is no filesystem independent way to discover the restrictions at least
 * for the 2.4 kernel series. Since 2.6 the 512 byte boundary seems to be used by all
 * file systems. So Linus comment about this flag is comprehensible but Linux
 * lacks an alternative at the moment.
 *
 * The next limitation applies only to Windows. Requests are not associated with the
 * I/O context they are associated with but with the file the request is for.
 * The file needs to be associated with exactly one I/O completion port and requests
 * for this file will only arrive at that context after they completed and not on
 * the context the request was submitted.
 * To associate a file with a specific context RTFileAioCtxAssociateWithFile() is
 * used. It is only implemented on Windows and does nothing on the other platforms.
 * If the file needs to be associated with different context for some reason
 * the file must be closed first. After it was opened again the new context
 * can be associated with the other context.
 * This can't be done by the API because there is no way to retrieve the flags
 * the file was opened with.
 */

/**
 * Global limits for the AIO API.
 */
typedef struct RTFILEAIOLIMITS
{
    /** Global number of simultaneous outstanding requests allowed.
     *  RTFILEAIO_UNLIMITED_REQS means no limit. */
    uint32_t cReqsOutstandingMax;
    /** The alignment data buffers need to have.
     * 0 means no alignment restrictions. */
    uint32_t cbBufferAlignment;
} RTFILEAIOLIMITS;
/** A pointer to a AIO limits structure. */
typedef RTFILEAIOLIMITS *PRTFILEAIOLIMITS;

/**
 * Returns the global limits for the AIO API.
 *
 * @returns IPRT status code.
 * @retval  VERR_NOT_SUPPORTED if the host does not support the async I/O API.
 *
 * @param   pAioLimits      Where to store the global limit information.
 */
RTDECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits);

/**
 * Creates an async I/O request handle.
 *
 * @returns IPRT status code.
 * @param   phReq           Where to store the request handle.
 */
RTDECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq);

/**
 * Destroys an async I/O request handle.
 *
 * @returns IPRT status code.
 * @retval  VERR_FILE_AIO_IN_PROGRESS if the request is still in progress.
 *
 * @param   hReq            The request handle.
 */
RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq);

/**
 * Prepares an async read request.
 *
 * @returns IPRT status code.
 * @retval  VERR_FILE_AIO_IN_PROGRESS if the request is still in progress.
 *
 * @param   hReq            The request handle.
 * @param   hFile           The file to read from.
 * @param   off             The offset to start reading at.
 * @param   pvBuf           Where to store the read bits.
 * @param   cbRead          Number of bytes to read.
 * @param   pvUser          Opaque user data associated with this request which
 *                          can be retrieved with RTFileAioReqGetUser().
 */
RTDECL(int) RTFileAioReqPrepareRead(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off,
                                    void *pvBuf, size_t cbRead, void *pvUser);

/**
 * Prepares an async write request.
 *
 * @returns IPRT status code.
 * @retval  VERR_FILE_AIO_IN_PROGRESS if the request is still in progress.
 *
 * @param   hReq            The request handle.
 * @param   hFile           The file to write to.
 * @param   off             The offset to start writing at.
 * @param   pvBuf           The bits to write.
 * @param   cbWrite         Number of bytes to write.
 * @param   pvUser          Opaque user data associated with this request which
 *                          can be retrieved with RTFileAioReqGetUser().
 */
RTDECL(int) RTFileAioReqPrepareWrite(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off,
                                     void const *pvBuf, size_t cbWrite, void *pvUser);

/**
 * Prepares an async flush of all cached data associated with a file handle.
 *
 * @returns IPRT status code.
 * @retval  VERR_FILE_AIO_IN_PROGRESS if the request is still in progress.
 *
 * @param   hReq            The request handle.
 * @param   hFile           The file to flush.
 * @param   pvUser          Opaque user data associated with this request which
 *                          can be retrieved with RTFileAioReqGetUser().
 *
 * @remarks May also flush other caches on some platforms.
 */
RTDECL(int) RTFileAioReqPrepareFlush(RTFILEAIOREQ hReq, RTFILE hFile, void *pvUser);

/**
 * Gets the opaque user data associated with the given request.
 *
 * @returns Opaque user data.
 * @retval  NULL if the request hasn't been prepared yet.
 *
 * @param   hReq            The request handle.
 */
RTDECL(void *) RTFileAioReqGetUser(RTFILEAIOREQ hReq);

/**
 * Cancels a pending request.
 *
 * @returns IPRT status code.
 * @retval  VINF_SUCCESS              If the request was canceled.
 * @retval  VERR_FILE_AIO_NOT_SUBMITTED If the request wasn't submitted yet.
 * @retval  VERR_FILE_AIO_IN_PROGRESS If the request could not be canceled because it is already processed.
 * @retval  VERR_FILE_AIO_COMPLETED   If the request could not be canceled because it already completed.
 *
 * @param   hReq            The request to cancel.
 */
RTDECL(int) RTFileAioReqCancel(RTFILEAIOREQ hReq);

/**
 * Gets the status of a completed request.
 *
 * @returns The IPRT status code of the given request.
 * @retval  VERR_FILE_AIO_NOT_SUBMITTED if the request wasn't submitted yet.
 * @retval  VERR_FILE_AIO_CANCELED if the request was canceled.
 * @retval  VERR_FILE_AIO_IN_PROGRESS if the request isn't yet completed.
 *
 * @param   hReq            The request handle.
 * @param   pcbTransferred  Where to store the number of bytes transferred.
 *                          Optional since it is not relevant for all kinds of
 *                          requests.
 */
RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransferred);



/**
 * Creates an async I/O context.
 *
 * @todo briefly explain what an async context is here or in the page
 *       above.
 *
 * @returns IPRT status code.
 * @param   phAioCtx        Where to store the async I/O context handle.
 * @param   cAioReqsMax     How many async I/O requests the context should be capable
 *                          to handle. Pass RTFILEAIO_UNLIMITED_REQS if the
 *                          context should support an unlimited number of
 *                          requests.
 */
RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax);

/** Unlimited number of requests.
 * Used with RTFileAioCtxCreate and RTFileAioCtxGetMaxReqCount. */
#define RTFILEAIO_UNLIMITED_REQS    UINT32_MAX

/**
 * Destroys an async I/O context.
 *
 * @returns IPRT status code.
 * @param   hAioCtx         The async I/O context handle.
 */
RTDECL(int) RTFileAioCtxDestroy(RTFILEAIOCTX hAioCtx);

/**
 * Get the maximum number of requests one aio context can handle.
 *
 * @returns Maximum number of tasks the context can handle.
 *          RTFILEAIO_UNLIMITED_REQS if there is no limit.
 *
 * @param   hAioCtx         The async I/O context handle.
 *                          If NIL_RTAIOCONTEXT is passed the maximum value
 *                          which can be passed to RTFileAioCtxCreate()
 *                          is returned.
 */
RTDECL(uint32_t) RTFileAioCtxGetMaxReqCount(RTFILEAIOCTX hAioCtx);

/**
 * Associates a file with an async I/O context.
 * Requests for this file will arrive at the completion port
 * associated with the file.
 *
 * @returns IPRT status code.
 *
 * @param   hAioCtx        The async I/O context handle.
 * @param   hFile          The file handle.
 */
RTDECL(int) RTFileAioCtxAssociateWithFile(RTFILEAIOCTX hAioCtx, RTFILE hFile);

/**
 * Submits a set of requests to an async I/O context for processing.
 *
 * @returns IPRT status code.
 * @returns VERR_FILE_AIO_INSUFFICIENT_RESSOURCES if the maximum number of
 *          simultaneous outstanding requests would be exceeded.
 *
 * @param   hAioCtx         The async I/O context handle.
 * @param   pahReqs         Pointer to an array of request handles.
 * @param   cReqs           The number of entries in the array.
 *
 * @remarks It is possible that some requests could be submitted successfully
 *          even if the method returns an error code. In that case RTFileAioReqGetRC()
 *          can be used to determine the status of a request.
 *          If it returns VERR_FILE_AIO_IN_PROGRESS it was submitted successfully.
 *          Any other error code may indicate why the request failed.
 *          VERR_FILE_AIO_NOT_SUBMITTED indicates that a request wasn't submitted
 *          probably because the previous request encountered an error.
 *
 * @remarks @a cReqs uses the type size_t while it really is a uint32_t, this is
 *          to avoid annoying warnings when using RT_ELEMENTS and similar
 *          macros.
 */
RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs);

/**
 * Waits for request completion.
 *
 * Only one thread at a time may call this API on a context.
 *
 * @returns IPRT status code.
 * @retval  VERR_INVALID_POINTER     If pcReqs or/and pahReqs are invalid.
 * @retval  VERR_INVALID_HANDLE      If hAioCtx is invalid.
 * @retval  VERR_OUT_OF_RANGE        If cMinReqs is larger than cReqs.
 * @retval  VERR_INVALID_PARAMETER   If cReqs is 0.
 * @retval  VERR_TIMEOUT             If cMinReqs didn't complete before the
 *                                   timeout expired.
 * @retval  VERR_INTERRUPTED         If the completion context was interrupted
 *                                   by RTFileAioCtxWakeup().
 * @retval  VERR_FILE_AIO_NO_REQUEST If there are no pending request.
 *
 * @param   hAioCtx         The async I/O context handle to wait and get
 *                          completed requests from.
 * @param   cMinReqs        The minimum number of requests which have to
 *                          complete before this function returns.
 * @param   cMillies        The number of milliseconds to wait before returning
 *                          VERR_TIMEOUT.  Use RT_INDEFINITE_WAIT to wait
 *                          forever.
 * @param   pahReqs         Pointer to an array where the handles of the
 *                          completed requests will be stored on success.
 * @param   cReqs           The number of entries @a pahReqs can hold.
 * @param   pcReqs          Where to store the number of returned (complete)
 *                          requests. This will always be set.
 *
 * @remarks The wait will be resume if interrupted by a signal. An
 *          RTFileAioCtxWaitNoResume variant can be added later if it becomes
 *          necessary.
 *
 * @remarks @a cMinReqs and @a cReqs use the type size_t while they really are
 *          uint32_t's, this is to avoid annoying warnings when using
 *          RT_ELEMENTS and similar macros.
 */
RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL cMillies,
                             PRTFILEAIOREQ pahReqs, size_t cReqs, uint32_t *pcReqs);

/**
 * Forces any RTFileAioCtxWait() call on another thread to return immediately.
 *
 * @returns IPRT status code.
 *
 * @param   hAioCtx         The handle of the async I/O context to wakeup.
 */
RTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx);

#endif /* IN_RING3 */

/** @} */

RT_C_DECLS_END

#endif