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