1
2 // Copyright (C) 2023 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 #include <Windows.h>
16 #include <fcntl.h>
17 #include <io.h>
18 #include <stdio.h>
19 #include <string.h>
20
21 #include <cerrno>
22 #include <cstdio>
23 #include <cstring>
24 #include <iostream>
25
26 #include "compat_compiler.h"
27
28 ANDROID_BEGIN_HEADER
29
_ftruncate(int fd,int64_t length)30 int _ftruncate(int fd, int64_t length) {
31 LARGE_INTEGER li;
32 DWORD dw;
33 LONG high;
34 HANDLE h;
35 BOOL res;
36
37 if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0) return -1;
38
39 h = (HANDLE)_get_osfhandle(fd);
40
41 /* get current position, ftruncate do not change position */
42 li.HighPart = 0;
43 li.LowPart = SetFilePointer(h, 0, &li.HighPart, FILE_CURRENT);
44 if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
45 return -1;
46 }
47
48 high = length >> 32;
49 dw = SetFilePointer(h, (DWORD)length, &high, FILE_BEGIN);
50 if (dw == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
51 return -1;
52 }
53 res = SetEndOfFile(h);
54
55 /* back to old position */
56 SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
57 return res ? 0 : -1;
58 }
59
mkstemp(char * tmplate)60 int mkstemp(char* tmplate) {
61 // Check if the tmplate string is null or doesn't end with "XXXXXX"
62 if (tmplate == nullptr || std::strlen(tmplate) < 6 ||
63 std::strcmp(tmplate + std::strlen(tmplate) - 6, "XXXXXX") != 0) {
64 errno = EINVAL; // Invalid argument
65 return -1;
66 }
67
68 // Generate a unique filename
69 if (_mktemp_s(tmplate, std::strlen(tmplate) + 1) != 0) {
70 errno = EIO; // I/O error
71 return -1;
72 }
73
74 // Open the file with read and write access
75 int fd;
76 if (_sopen_s(&fd, tmplate, _O_RDWR | _O_CREAT | _O_EXCL, _SH_DENYNO, _S_IREAD | _S_IWRITE) !=
77 0) {
78 return -1;
79 }
80
81 return fd;
82 }
83
mkostemp(char * tmplate,int flags)84 int mkostemp(char* tmplate, int flags) {
85 // Use mkstemp for Windows as it doesn't have all the flags like O_APPEND or O_SYNC
86 return mkstemp(tmplate);
87 }
88
mkstemps(char * tmplate,int suffixlen)89 int mkstemps(char* tmplate, int suffixlen) {
90 // Check if the tmplate string is null or doesn't end with "XXXXXX"
91 if (tmplate == nullptr || std::strlen(tmplate) < 6 ||
92 std::strcmp(tmplate + std::strlen(tmplate) - 6, "XXXXXX") != 0) {
93 errno = EINVAL; // Invalid argument
94 return -1;
95 }
96
97 // Generate a unique filename
98 if (_mktemp_s(tmplate, std::strlen(tmplate) + 1) != 0) {
99 errno = EIO; // I/O error
100 return -1;
101 }
102
103 // Add the suffix to the tmplate
104 std::strncat(tmplate, "suffix", suffixlen);
105
106 // Open the file with read and write access
107 int fd;
108 if (_sopen_s(&fd, tmplate, _O_RDWR | _O_CREAT | _O_EXCL, _SH_DENYNO, _S_IREAD | _S_IWRITE) !=
109 0) {
110 return -1;
111 }
112
113 return fd;
114 }
115
mkostemps(char * tmplate,int suffixlen,int flags)116 int mkostemps(char* tmplate, int suffixlen, int flags) {
117 // Use mkstemps for Windows as it doesn't have all the flags like O_APPEND or O_SYNC
118 return mkstemps(tmplate, suffixlen);
119 }
120
121 ANDROID_END_HEADER