• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #3535

23 Nov 2024 02:07AM UTC coverage: 60.85% (+0.03%) from 60.825%
#3535

push

travis-ci

web-flow
Merge pull request #28893 from taosdata/doc/internal

refact: rename taos lib name

120252 of 252737 branches covered (47.58%)

Branch coverage included in aggregate %.

201187 of 275508 relevant lines covered (73.02%)

15886166.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

58.45
/source/os/src/osFile.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15
#define ALLOW_FORBID_FUNC
16
#include "os.h"
17
#include "osSemaphore.h"
18
#include "tdef.h"
19
#include "zlib.h"
20

21
#ifdef WINDOWS
22
#include <WinBase.h>
23
#include <io.h>
24
#include <ktmw32.h>
25
#include <windows.h>
26
#define F_OK 0
27
#define W_OK 2
28
#define R_OK 4
29

30
#define _SEND_FILE_STEP_ 1024
31

32
#else
33
#include <fcntl.h>
34
#include <sys/file.h>
35

36
#if !defined(_TD_DARWIN_64)
37
#include <sys/sendfile.h>
38
#endif
39
#include <sys/stat.h>
40
#include <unistd.h>
41
#define LINUX_FILE_NO_TEXT_OPTION 0
42
#define O_TEXT                    LINUX_FILE_NO_TEXT_OPTION
43

44
#define _SEND_FILE_STEP_ 1000
45
#endif
46

47
typedef int32_t FileFd;
48

49
#ifdef WINDOWS
50
typedef struct TdFile {
51
  TdThreadRwlock rwlock;
52
  int            refId;
53
  HANDLE         hFile;
54
  FILE          *fp;
55
  int32_t        tdFileOptions;
56
} TdFile;
57
#else
58
typedef struct TdFile {
59
  TdThreadRwlock rwlock;
60
  int            refId;
61
  FileFd         fd;
62
  FILE          *fp;
63
} TdFile;
64
#endif  // WINDOWS
65

66
#define FILE_WITH_LOCK 1
67

68
#ifdef BUILD_WITH_RAND_ERR
69
#define STUB_RAND_IO_ERR(ret)                                \
70
  if (tsEnableRandErr && (tsRandErrScope & RAND_ERR_FILE)) { \
71
    uint32_t r = taosRand() % tsRandErrDivisor;              \
72
    if ((r + 1) <= tsRandErrChance) {                        \
73
      errno = EIO;                                           \
74
      terrno = TAOS_SYSTEM_ERROR(errno);                     \
75
      return (ret);                                          \
76
    }                                                        \
77
  }
78
#else
79
#define STUB_RAND_IO_ERR(ret)
80
#endif
81

82
void taosGetTmpfilePath(const char *inputTmpDir, const char *fileNamePrefix, char *dstPath) {
847,125✔
83
  if (inputTmpDir == NULL || fileNamePrefix == NULL) return;
847,125!
84
#ifdef WINDOWS
85

86
  char tmpPath[PATH_MAX];
87

88
  int32_t len = (int32_t)strlen(inputTmpDir);
89
  memcpy(tmpPath, inputTmpDir, len);
90

91
  if (tmpPath[len - 1] != '/' && tmpPath[len - 1] != '\\') {
92
    tmpPath[len++] = '\\';
93
  }
94

95
  snprintf(tmpPath + len, sizeof(tmpPath) - len, "%s%s%s", TD_TMP_FILE_PREFIX, fileNamePrefix, "-%d-%s");
96

97
  char rand[8] = {0};
98
  taosRandStr(rand, tListLen(rand) - 1);
99
  snprintf(dstPath, PATH_MAX, tmpPath, getpid(), rand);
100

101
#else
102

103
  char    tmpPath[PATH_MAX];
104
  int32_t len = strlen(inputTmpDir);
847,409✔
105
  (void)memcpy(tmpPath, inputTmpDir, len);
847,409✔
106
  static uint64_t seqId = 0;
107

108
  if (tmpPath[len - 1] != '/') {
847,409!
109
    tmpPath[len++] = '/';
×
110
  }
111

112
  snprintf(tmpPath + len, sizeof(tmpPath) - len, "%s%s%s", TD_TMP_FILE_PREFIX, fileNamePrefix, "-%d-%s");
847,409✔
113

114
  char rand[32] = {0};
847,409✔
115

116
  (void)snprintf(rand, sizeof(rand), "%" PRIu64, atomic_add_fetch_64(&seqId, 1));
847,409✔
117

118
  (void)snprintf(dstPath, PATH_MAX, tmpPath, getpid(), rand);
848,284✔
119

120
#endif
121
}
122

123
int64_t taosCopyFile(const char *from, const char *to) {
62✔
124
  if (from == NULL || to == NULL) {
62!
125
    terrno = TSDB_CODE_INVALID_PARA;
×
126
    return -1;
×
127
  }
128
#ifdef WINDOWS
129
  if (CopyFile(from, to, 0)) {
130
    return 1;
131
  } else {
132
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
133
    return -1;
134
  }
135
#else
136
  char    buffer[4096];
137
  int64_t size = 0;
62✔
138
  int64_t bytes;
139
  int32_t code = TSDB_CODE_SUCCESS;
62✔
140

141
  TdFilePtr pFileFrom = NULL;
62✔
142
  TdFilePtr pFileTo = NULL;
62✔
143
  pFileFrom = taosOpenFile(from, TD_FILE_READ);
62✔
144
  if (pFileFrom == NULL) {
62!
145
    code = terrno;
×
146
    goto _err;
×
147
  }
148

149
  pFileTo = taosOpenFile(to, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_EXCL);
62✔
150
  if (pFileTo == NULL) {
62!
151
    code = terrno;
×
152
    goto _err;
×
153
  }
154

155
  while (true) {
156
    bytes = taosReadFile(pFileFrom, buffer, sizeof(buffer));
62✔
157
    if (bytes < 0) {
62!
158
      code = terrno;
×
159
      goto _err;
×
160
    }
161

162
    if (bytes == 0) break;
62!
163

164
    size += bytes;
62✔
165

166
    if (taosWriteFile(pFileTo, (void *)buffer, bytes) < bytes) {
62!
167
      code = terrno;
×
168
      goto _err;
×
169
    }
170
    if (bytes < sizeof(buffer)) break;
62!
171
  }
172

173
  code = taosFsyncFile(pFileTo);
62✔
174
  if (code != 0) {
62!
175
    goto _err;
×
176
  }
177

178
  TAOS_UNUSED(taosCloseFile(&pFileFrom));
62✔
179
  TAOS_UNUSED(taosCloseFile(&pFileTo));
62✔
180

181
  if (code != 0) {
62!
182
    terrno = code;
×
183
    return -1;
×
184
  }
185

186
  return size;
62✔
187

188
_err:
×
189

190
  if (pFileFrom != NULL) TAOS_SKIP_ERROR(taosCloseFile(&pFileFrom));
×
191
  if (pFileTo != NULL) TAOS_SKIP_ERROR(taosCloseFile(&pFileTo));
×
192
  /* coverity[+retval] */
193
  TAOS_SKIP_ERROR(taosRemoveFile(to));
×
194

195
  terrno = code;
×
196
  return -1;
×
197
#endif
198
}
199

200
TdFilePtr taosCreateFile(const char *path, int32_t tdFileOptions) {
×
201
  if(path == NULL) {
×
202
    terrno = TSDB_CODE_INVALID_PARA;
×
203
    return NULL;
×
204
  }
205
  TdFilePtr fp = taosOpenFile(path, tdFileOptions);
×
206
  if (!fp) {
×
207
    if (terrno == TAOS_SYSTEM_ERROR(ENOENT)) {
×
208
      // Try to create directory recursively
209
      char s[PATH_MAX];
210
      tstrncpy(s, path, sizeof(s));
×
211
      if (taosMulMkDir(taosDirName(s)) != 0) {
×
212
        return NULL;
×
213
      }
214
      fp = taosOpenFile(path, tdFileOptions);
×
215
      if (!fp) {
×
216
        return NULL;
×
217
      }
218
    }
219
  }
220

221
  return fp;
×
222
}
223

224
int32_t taosRemoveFile(const char *path) {
1,170,133✔
225
  OS_PARAM_CHECK(path);
1,170,133!
226
  int32_t code = remove(path);
1,170,133✔
227
  if (-1 == code) {
1,170,150✔
228
    terrno = TAOS_SYSTEM_ERROR(errno);
848,375✔
229
    return terrno;
848,380✔
230
  }
231
  return code;
321,775✔
232
}
233

234
int32_t taosRenameFile(const char *oldName, const char *newName) {
276,392✔
235
  OS_PARAM_CHECK(oldName);
276,392!
236
  OS_PARAM_CHECK(newName);
276,392!
237
#ifdef WINDOWS
238
  bool finished = false;
239

240
  HANDLE transactionHandle = CreateTransaction(NULL, NULL, 0, 0, 0, INFINITE, NULL);
241
  if (transactionHandle == INVALID_HANDLE_VALUE) {
242
    DWORD error = GetLastError();
243
    terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
244
    return terrno;
245
  }
246

247
  BOOL result = MoveFileTransacted(oldName, newName, NULL, NULL, MOVEFILE_REPLACE_EXISTING, transactionHandle);
248

249
  if (result) {
250
    finished = CommitTransaction(transactionHandle);
251
    if (!finished) {
252
      DWORD error = GetLastError();
253
      terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
254
    }
255
  } else {
256
    RollbackTransaction(transactionHandle);
257
    DWORD error = GetLastError();
258
    terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
259
    finished = false;
260
  }
261

262
  CloseHandle(transactionHandle);
263

264
  return finished ? 0 : terrno;
265
#else
266
  int32_t code = rename(oldName, newName);
276,392✔
267
  if (-1 == code) {
276,389✔
268
    terrno = TAOS_SYSTEM_ERROR(errno);
132✔
269
    return terrno;
130✔
270
  }
271

272
  return TSDB_CODE_SUCCESS;
276,257✔
273
#endif
274
}
275

276
int32_t taosStatFile(const char *path, int64_t *size, int32_t *mtime, int32_t *atime) {
247,437✔
277
  OS_PARAM_CHECK(path);
247,437!
278
#ifdef WINDOWS
279
  struct _stati64 fileStat;
280
  int32_t         code = _stati64(path, &fileStat);
281
#else
282
  struct stat fileStat;
283
  int32_t     code = stat(path, &fileStat);
247,437✔
284
#endif
285
  if (-1 == code) {
247,418✔
286
    terrno = TAOS_SYSTEM_ERROR(errno);
48,085✔
287
    return terrno;
48,122✔
288
  }
289

290
  if (size != NULL) {
199,333✔
291
    *size = fileStat.st_size;
186,232✔
292
  }
293

294
  if (mtime != NULL) {
199,333✔
295
    *mtime = fileStat.st_mtime;
3,415✔
296
  }
297

298
  if (atime != NULL) {
199,333!
299
    *atime = fileStat.st_atime;
×
300
  }
301

302
  return 0;
199,333✔
303
}
304
int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno) {
40,932✔
305
#ifdef WINDOWS
306
  if (pFile == NULL || pFile->hFile == NULL) {
307
    terrno = TSDB_CODE_INVALID_PARA;
308
    return terrno;
309
  }
310
  BY_HANDLE_FILE_INFORMATION bhfi;
311
  if (GetFileInformationByHandle(pFile->hFile, &bhfi) == FALSE) {
312
    DWORD error = GetLastError();
313
    terrno = TAOS_SYSTEM_WINAPI_ERROR(error);
314
    return terrno;
315
  }
316

317
  if (stDev != NULL) {
318
    *stDev = (int64_t)(bhfi.dwVolumeSerialNumber);
319
  }
320

321
  if (stIno != NULL) {
322
    *stIno = (int64_t)((((uint64_t)bhfi.nFileIndexHigh) << 32) + bhfi.nFileIndexLow);
323
  }
324

325
#else
326
  if (pFile == NULL || pFile->fd < 0) {
40,932!
327
    terrno = TSDB_CODE_INVALID_PARA;
×
328
    return terrno;
×
329
  }
330

331
  struct stat fileStat;
332
  int32_t     code = fstat(pFile->fd, &fileStat);
40,977✔
333
  if (-1 == code) {
40,950!
334
    terrno = TAOS_SYSTEM_ERROR(errno);
×
335
    return terrno;
×
336
  }
337

338
  if (stDev != NULL) {
40,969✔
339
    *stDev = fileStat.st_dev;
40,956✔
340
  }
341

342
  if (stIno != NULL) {
40,969!
343
    *stIno = fileStat.st_ino;
40,969✔
344
  }
345
#endif
346

347
  return 0;
40,969✔
348
}
349

350
FILE *taosOpenFileForStream(const char *path, int32_t tdFileOptions) {
55,966✔
351
  if (path == NULL) {
55,966!
352
    terrno = TSDB_CODE_INVALID_PARA;
×
353
    return NULL;
×
354
  }
355
  char *mode = NULL;
55,966✔
356
  if (tdFileOptions & TD_FILE_APPEND) {
55,966✔
357
    mode = (tdFileOptions & TD_FILE_TEXT) ? "at+" : "ab+";
2,226!
358
  } else if (tdFileOptions & TD_FILE_TRUNC) {
53,740✔
359
    mode = (tdFileOptions & TD_FILE_TEXT) ? "wt+" : "wb+";
1,267✔
360
  } else if ((tdFileOptions & TD_FILE_READ) && !(tdFileOptions & TD_FILE_WRITE)) {
52,473!
361
    mode = (tdFileOptions & TD_FILE_TEXT) ? "rt" : "rb";
52,473!
362
  } else {
363
    mode = (tdFileOptions & TD_FILE_TEXT) ? "rt+" : "rb+";
×
364
  }
365
  if (tdFileOptions & TD_FILE_EXCL) {
55,966!
366
    terrno = TSDB_CODE_INVALID_PARA;
×
367
    return NULL;
×
368
  }
369
  FILE *f = fopen(path, mode);
55,966✔
370
  if (NULL == f) {
55,966✔
371
    terrno = TAOS_SYSTEM_ERROR(errno);
94✔
372
  }
373
  return f;
55,966✔
374
}
375

376
#ifdef WINDOWS
377
HANDLE taosOpenFileNotStream(const char *path, int32_t tdFileOptions) {
378
  if (path == NULL) {
379
    terrno = TSDB_CODE_INVALID_PARA;
380
    return INVALID_HANDLE_VALUE;
381
  }
382
  DWORD openMode = 0;
383
  DWORD access = 0;
384
  DWORD fileFlag = FILE_ATTRIBUTE_NORMAL;
385
  DWORD shareMode = FILE_SHARE_READ;
386

387
  openMode = OPEN_EXISTING;
388
  if (tdFileOptions & TD_FILE_CREATE) {
389
    openMode = OPEN_ALWAYS;
390
  } else if (tdFileOptions & TD_FILE_EXCL) {
391
    openMode = CREATE_NEW;
392
  } else if ((tdFileOptions & TD_FILE_TRUNC)) {
393
    openMode = TRUNCATE_EXISTING;
394
    access |= GENERIC_WRITE;
395
  }
396
  if (tdFileOptions & TD_FILE_APPEND) {
397
    access |= FILE_APPEND_DATA;
398
  }
399
  if (tdFileOptions & TD_FILE_WRITE) {
400
    access |= GENERIC_WRITE;
401
  }
402

403
  shareMode |= FILE_SHARE_WRITE;
404

405
  access |= GENERIC_READ;
406

407
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
408
    fileFlag |= FILE_ATTRIBUTE_TEMPORARY;
409
  }
410
  if (tdFileOptions & TD_FILE_WRITE_THROUGH) {
411
    fileFlag |= FILE_FLAG_WRITE_THROUGH;
412
  }
413

414
  HANDLE h = CreateFile(path, access, shareMode, NULL, openMode, fileFlag, NULL);
415
  if (h != INVALID_HANDLE_VALUE && (tdFileOptions & TD_FILE_APPEND) && (tdFileOptions & TD_FILE_WRITE)) {
416
    SetFilePointer(h, 0, NULL, FILE_END);
417
  }
418
  if (h == INVALID_HANDLE_VALUE) {
419
    DWORD dwError = GetLastError();
420
    terrno = TAOS_SYSTEM_WINAPI_ERROR(dwError);
421
    // LPVOID lpMsgBuf;
422
    // FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, (LPTSTR)&lpMsgBuf,
423
    // 0,
424
    //               NULL);
425
    // printf("CreateFile failed with error %d: %s", dwError, (char *)lpMsgBuf);
426
    // LocalFree(lpMsgBuf);
427
  }
428
  return h;
429
}
430

431
int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
432
  if (pFile == NULL  ||  buf == NULL) {
433
    terrno = TSDB_CODE_INVALID_PARA;
434
    return terrno;
435
  }
436
#if FILE_WITH_LOCK
437
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
438
#endif
439
  if (pFile->hFile == NULL) {
440
#if FILE_WITH_LOCK
441
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
442
#endif
443
    terrno = TSDB_CODE_INVALID_PARA;
444
    return terrno;
445
  }
446

447
  int64_t res = 0;
448
  DWORD bytesRead;
449
  if (!ReadFile(pFile->hFile, buf, count, &bytesRead, NULL)) {
450
    DWORD errCode = GetLastError();
451
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errCode);
452
    res = -1;
453
  } else {
454
    res = bytesRead;
455
  }
456
#if FILE_WITH_LOCK
457
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
458
#endif
459
  return res;
460
}
461

462
int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
463
  if (pFile == NULL || pFile->hFile == NULL || buf == NULL) {
464
    terrno = TSDB_CODE_INVALID_PARA;
465
    return 0;
466
  }
467
#if FILE_WITH_LOCK
468
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
469
#endif
470

471
  DWORD bytesWritten;
472
  if (!WriteFile(pFile->hFile, buf, count, &bytesWritten, NULL)) {
473
    errno = GetLastError();
474
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
475
    bytesWritten = -1;
476
  }
477

478
#if FILE_WITH_LOCK
479
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
480
#endif
481
  return bytesWritten;
482
}
483

484
int64_t taosPWriteFile(TdFilePtr pFile, const void *buf, int64_t count, int64_t offset) {
485
  if (pFile == NULL || buf == NULL) {
486
    terrno = TSDB_CODE_INVALID_PARA;
487
    return 0;
488
  }
489
#if FILE_WITH_LOCK
490
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
491
#endif
492
  if (pFile->hFile == NULL) {
493
#if FILE_WITH_LOCK
494
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
495
#endif
496
    return 0;
497
  }
498

499
  DWORD      ret = 0;
500
  OVERLAPPED ol = {0};
501
  ol.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 0x20);
502
  ol.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
503

504
  SetLastError(0);
505
  BOOL result = WriteFile(pFile->hFile, buf, count, &ret, &ol);
506
  if (!result) {
507
    errno = GetLastError();
508
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
509
    ret = -1;
510
  }
511

512
#if FILE_WITH_LOCK
513
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
514
#endif
515
  return ret;
516
}
517

518
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
519
  if (pFile == NULL || pFile->hFile == NULL) {
520
    terrno = TSDB_CODE_INVALID_PARA;
521
    return -1;
522
  }
523
#if FILE_WITH_LOCK
524
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
525
#endif
526

527
  LARGE_INTEGER liOffset;
528
  liOffset.QuadPart = offset;
529
  if (!SetFilePointerEx(pFile->hFile, liOffset, NULL, whence)) {
530
    errno = GetLastError();
531
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
532
    return -1;
533
  }
534

535
  liOffset.QuadPart = 0;
536
  if (!SetFilePointerEx(pFile->hFile, liOffset, &liOffset, FILE_CURRENT)) {
537
    errno = GetLastError();
538
    terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
539
    return -1;
540
  }
541
#if FILE_WITH_LOCK
542
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
543
#endif
544
  return liOffset.QuadPart;
545
}
546

547
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) {
548
  if (pFile == NULL || pFile->hFile == NULL) {
549
    terrno = TSDB_CODE_INVALID_PARA;
550
    return terrno;
551
  }
552

553
  if (size != NULL) {
554
    LARGE_INTEGER fileSize;
555
    if (!GetFileSizeEx(pFile->hFile, &fileSize)) {
556
      errno = GetLastError();
557
      terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
558
      return terrno;  // Error getting file size
559
    }
560
    *size = fileSize.QuadPart;
561
  }
562

563
  if (mtime != NULL) {
564
    FILETIME creationTime, lastAccessTime, lastWriteTime;
565
    if (!GetFileTime(pFile->hFile, &creationTime, &lastAccessTime, &lastWriteTime)) {
566
      errno = GetLastError();
567
      terrno = TAOS_SYSTEM_WINAPI_ERROR(errno);
568
      return terrno;  // Error getting file time
569
    }
570
    // Convert the FILETIME structure to a time_t value
571
    ULARGE_INTEGER ull;
572
    ull.LowPart = lastWriteTime.dwLowDateTime;
573
    ull.HighPart = lastWriteTime.dwHighDateTime;
574
    *mtime = (int32_t)((ull.QuadPart - 116444736000000000ULL) / 10000000ULL);
575
  }
576
  return 0;
577
}
578

579
int32_t taosLockFile(TdFilePtr pFile) {
580
  if (pFile == NULL || pFile->hFile == NULL) {
581
    terrno = TSDB_CODE_INVALID_PARA;
582
    return terrno;
583
  }
584

585
  BOOL          fSuccess = FALSE;
586
  LARGE_INTEGER fileSize;
587
  OVERLAPPED    overlapped = {0};
588

589
  fSuccess = LockFileEx(pFile->hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
590
                        0,           // reserved
591
                        ~0,          // number of bytes to lock low
592
                        ~0,          // number of bytes to lock high
593
                        &overlapped  // overlapped structure
594
  );
595
  if (!fSuccess) {
596
    return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
597
  }
598
  return 0;
599
}
600

601
int32_t taosUnLockFile(TdFilePtr pFile) {
602
  if (pFile == NULL || pFile->hFile == NULL) {
603
    return 0;
604
  }
605
  BOOL       fSuccess = FALSE;
606
  OVERLAPPED overlapped = {0};
607

608
  fSuccess = UnlockFileEx(pFile->hFile, 0, ~0, ~0, &overlapped);
609
  if (!fSuccess) {
610
    return TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
611
  }
612
  return 0;
613
}
614

615
int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
616
  if (pFile == NULL) {
617
    terrno = TSDB_CODE_INVALID_PARA;
618
    return terrno;
619
  }
620
  if (pFile->hFile == NULL) {
621
    printf("Ftruncate file error, hFile was null\n");
622
    terrno = TSDB_CODE_INVALID_PARA;
623
    return terrno;
624
  }
625

626
  LARGE_INTEGER li_0;
627
  li_0.QuadPart = (int64_t)0;
628
  BOOL cur = SetFilePointerEx(pFile->hFile, li_0, NULL, FILE_CURRENT);
629
  if (!cur) {
630
    printf("SetFilePointerEx Error getting current position in file.\n");
631
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
632
    return terrno;
633
  }
634

635
  LARGE_INTEGER li_size;
636
  li_size.QuadPart = l_size;
637
  BOOL cur2 = SetFilePointerEx(pFile->hFile, li_size, NULL, FILE_BEGIN);
638
  if (cur2 == 0) {
639
    int error = GetLastError();
640
    switch (error) {
641
      case ERROR_INVALID_HANDLE:
642
        errno = EBADF;
643
        break;
644
      default:
645
        errno = EIO;
646
        break;
647
    }
648
    terrno = TAOS_SYSTEM_ERROR(errno);
649
    return terrno;
650
  }
651

652
  if (!SetEndOfFile(pFile->hFile)) {
653
    int error = GetLastError();
654
    printf("SetEndOfFile GetLastError is:%d", error);
655
    switch (error) {
656
      case ERROR_INVALID_HANDLE:
657
        errno = EBADF;
658
        break;
659
      default:
660
        errno = EIO;
661
        break;
662
    }
663
    terrno = TAOS_SYSTEM_ERROR(errno);
664
    return terrno;
665
  }
666
  return 0;
667
}
668

669
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
670
  if (pFileOut == NULL || pFileIn == NULL) {
671
    terrno = TSDB_CODE_INVALID_PARA;
672
    return -1;
673
  }
674
  if (pFileIn->hFile == NULL || pFileOut->hFile == NULL) {
675
    terrno = TSDB_CODE_INVALID_PARA;
676
    return -1;
677
  }
678

679
  LARGE_INTEGER fileOffset;
680
  fileOffset.QuadPart = *offset;
681

682
  if (!SetFilePointerEx(pFileIn->hFile, fileOffset, &fileOffset, FILE_BEGIN)) {
683
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
684
    return -1;
685
  }
686

687
  int64_t writeLen = 0;
688
  uint8_t buffer[_SEND_FILE_STEP_] = {0};
689

690
  DWORD bytesRead;
691
  DWORD bytesWritten;
692
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
693
    if (!ReadFile(pFileIn->hFile, buffer, _SEND_FILE_STEP_, &bytesRead, NULL)) {
694
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
695
      return writeLen;
696
    }
697

698
    if (bytesRead <= 0) {
699
      return writeLen;
700
    } else if (bytesRead < _SEND_FILE_STEP_) {
701
      if (!WriteFile(pFileOut->hFile, buffer, bytesRead, &bytesWritten, NULL)) {
702
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
703
        return -1;
704
      } else {
705
        return (int64_t)(writeLen + bytesRead);
706
      }
707
    } else {
708
      if (!WriteFile(pFileOut->hFile, buffer, _SEND_FILE_STEP_, &bytesWritten, NULL)) {
709
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
710
        return -1;
711
      } else {
712
        writeLen += _SEND_FILE_STEP_;
713
      }
714
    }
715
  }
716

717
  int64_t remain = size - writeLen;
718
  if (remain > 0) {
719
    DWORD bytesRead;
720
    if (!ReadFile(pFileIn->hFile, buffer, (DWORD)remain, &bytesRead, NULL)) {
721
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
722
      return -1;
723
    }
724

725
    if (bytesRead <= 0) {
726
      return writeLen;
727
    } else {
728
      DWORD bytesWritten;
729
      if (!WriteFile(pFileOut->hFile, buffer, bytesRead, &bytesWritten, NULL)) {
730
        terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
731
        return -1;
732
      } else {
733
        writeLen += bytesWritten;
734
      }
735
    }
736
  }
737
  return writeLen;
738
}
739

740
bool lastErrorIsFileNotExist() {
741
  DWORD dwError = GetLastError();
742
  return dwError == ERROR_FILE_NOT_FOUND;
743
}
744

745
#else
746
int taosOpenFileNotStream(const char *path, int32_t tdFileOptions) {
29,764,999✔
747
  if (path == NULL) {
29,764,999!
748
    terrno = TSDB_CODE_INVALID_PARA;
×
749
    return -1;
×
750
  }
751
  int access = O_BINARY;
29,764,999✔
752
  access |= (tdFileOptions & TD_FILE_CREATE) ? O_CREAT : 0;
29,764,999✔
753
  if ((tdFileOptions & TD_FILE_WRITE) && (tdFileOptions & TD_FILE_READ)) {
29,764,999✔
754
    access |= O_RDWR;
597,830✔
755
  } else if (tdFileOptions & TD_FILE_WRITE) {
29,167,169✔
756
    access |= O_WRONLY;
425,053✔
757
  } else if (tdFileOptions & TD_FILE_READ) {
28,742,116!
758
    access |= O_RDONLY;
28,742,388✔
759
  }
760
  access |= (tdFileOptions & TD_FILE_TRUNC) ? O_TRUNC : 0;
29,764,999✔
761
  access |= (tdFileOptions & TD_FILE_APPEND) ? O_APPEND : 0;
29,764,999✔
762
  access |= (tdFileOptions & TD_FILE_TEXT) ? O_TEXT : 0;
29,764,999✔
763
  access |= (tdFileOptions & TD_FILE_EXCL) ? O_EXCL : 0;
29,764,999✔
764
  access |= (tdFileOptions & TD_FILE_CLOEXEC) ? O_CLOEXEC : 0;
29,764,999✔
765

766
  int fd = open(path, access, S_IRWXU | S_IRWXG | S_IRWXO);
29,764,999✔
767
  if (-1 == fd) {
29,771,231✔
768
    terrno = TAOS_SYSTEM_ERROR(errno);
24,809✔
769
  }
770
  return fd;
29,774,985✔
771
}
772

773
int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
53,134,968✔
774
  if (pFile == NULL || buf == NULL) {
53,134,968!
775
    terrno = TSDB_CODE_INVALID_PARA;
×
776
    return -1;
×
777
  }
778
  STUB_RAND_IO_ERR(terrno)
779
#if FILE_WITH_LOCK
780
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
53,138,995✔
781
#endif
782

783
  if (pFile->fd < 0) {
53,149,864✔
784
#if FILE_WITH_LOCK
785
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
109✔
786
#endif
787
    terrno = TSDB_CODE_INVALID_PARA;
×
788
    return -1;
×
789
  }
790

791
  int64_t leftbytes = count;
53,149,755✔
792
  int64_t readbytes;
793
  char   *tbuf = (char *)buf;
53,149,755✔
794
  int32_t code = 0;
53,149,755✔
795

796
  while (leftbytes > 0) {
106,289,496✔
797
#ifdef WINDOWS
798
    readbytes = _read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
799
#else
800
    readbytes = read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
53,145,586✔
801
#endif
802
    if (readbytes < 0) {
53,144,737✔
803
      if (errno == EINTR) {
181!
804
        continue;
×
805
      } else {
806
        code = TAOS_SYSTEM_ERROR(errno);
181✔
807
#if FILE_WITH_LOCK
808
        (void)taosThreadRwlockUnlock(&(pFile->rwlock));
181✔
809
#endif
810
        terrno = code;
181✔
811
        return -1;
181✔
812
      }
813
    } else if (readbytes == 0) {
53,144,556✔
814
#if FILE_WITH_LOCK
815
      (void)taosThreadRwlockUnlock(&(pFile->rwlock));
4,815✔
816
#endif
817
      return (int64_t)(count - leftbytes);
4,815✔
818
    }
819

820
    leftbytes -= readbytes;
53,139,741✔
821
    tbuf += readbytes;
53,139,741✔
822
  }
823

824
#if FILE_WITH_LOCK
825
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
53,143,910✔
826
#endif
827

828
  return count;
53,146,542✔
829
}
830

831
int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
596,723,318✔
832
  STUB_RAND_IO_ERR(terrno)
833
  if (pFile == NULL || buf == NULL) {
596,723,318!
834
    terrno = TSDB_CODE_INVALID_PARA;
×
835
    return 0;
×
836
  }
837
#if FILE_WITH_LOCK
838
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
596,743,004✔
839
#endif
840
  if (pFile->fd < 0) {
596,947,041!
841
#if FILE_WITH_LOCK
842
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
843
#endif
844
    terrno = TSDB_CODE_INVALID_PARA;
×
845
    return 0;
×
846
  }
847

848
  int64_t nleft = count;
596,947,340✔
849
  int64_t nwritten = 0;
596,947,340✔
850
  char   *tbuf = (char *)buf;
596,947,340✔
851
  int32_t code = 0;
596,947,340✔
852

853
  while (nleft > 0) {
1,193,891,983✔
854
    nwritten = write(pFile->fd, (void *)tbuf, (uint32_t)nleft);
596,946,697✔
855
    if (nwritten < 0) {
596,944,643!
856
      if (errno == EINTR) {
×
857
        continue;
×
858
      }
859
      code = TAOS_SYSTEM_ERROR(errno);
×
860
#if FILE_WITH_LOCK
861
      (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
862
#endif
863
      terrno = code;
×
864
      return -1;
×
865
    }
866
    nleft -= nwritten;
596,944,643✔
867
    tbuf += nwritten;
596,944,643✔
868
  }
869

870
#if FILE_WITH_LOCK
871
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
596,945,286✔
872
#endif
873

874
  return count;
596,914,371✔
875
}
876

877
int64_t taosPWriteFile(TdFilePtr pFile, const void *buf, int64_t count, int64_t offset) {
740,498✔
878
  STUB_RAND_IO_ERR(terrno)
879
  if (pFile == NULL || buf == NULL) {
740,498!
880
    terrno = TSDB_CODE_INVALID_PARA;
×
881
    return 0;
×
882
  }
883

884
  int32_t code = 0;
740,618✔
885
#if FILE_WITH_LOCK
886
  (void)taosThreadRwlockWrlock(&(pFile->rwlock));
740,618✔
887
#endif
888

889
#if FILE_WITH_LOCK
890
  if (pFile->fd < 0) {
741,018!
891
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
892
    return 0;
×
893
  }
894
#endif
895

896
  int64_t ret = pwrite(pFile->fd, buf, count, offset);
741,018✔
897
  if (-1 == ret) {
740,456!
898
    code = TAOS_SYSTEM_ERROR(errno);
×
899
  }
900

901
#if FILE_WITH_LOCK
902
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
740,456✔
903
#endif
904

905
  if (code) {
740,804!
906
    terrno = code;
×
907
  }
908

909
  return ret;
740,832✔
910
}
911

912
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
58,941,741✔
913
  if (pFile == NULL || pFile->fd < 0) {
58,941,741!
914
    terrno = TSDB_CODE_INVALID_PARA;
×
915
    return -1;
×
916
  }
917
#if FILE_WITH_LOCK
918
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
58,949,577✔
919
#endif
920

921
  int32_t code = 0;
58,960,844✔
922

923
  int64_t ret = lseek(pFile->fd, offset, whence);
58,960,844✔
924
  if (-1 == ret) {
58,958,908!
925
    code = TAOS_SYSTEM_ERROR(errno);
×
926
  }
927

928
#if FILE_WITH_LOCK
929
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
58,958,908✔
930
#endif
931

932
  if (code) {
58,955,728✔
933
    terrno = code;
91✔
934
    return -1;
×
935
  }
936

937
  return ret;
58,955,637✔
938
}
939

940
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) {
103,375✔
941
  if (pFile == NULL) {
103,375!
942
    terrno = TSDB_CODE_INVALID_PARA;
×
943
    return terrno;
×
944
  }
945

946
  if (pFile->fd < 0) {
103,375!
947
    terrno = TSDB_CODE_INVALID_PARA;
×
948
    return terrno;
×
949
  }
950

951
  struct stat fileStat;
952
  int32_t     code = fstat(pFile->fd, &fileStat);
103,375✔
953
  if (-1 == code) {
103,375✔
954
    terrno = TAOS_SYSTEM_ERROR(errno);
5✔
955
    return terrno;
×
956
  }
957

958
  if (size != NULL) {
103,370✔
959
    *size = fileStat.st_size;
103,358✔
960
  }
961

962
  if (mtime != NULL) {
103,370!
963
    *mtime = fileStat.st_mtime;
×
964
  }
965

966
  return 0;
103,370✔
967
}
968

969
int32_t taosLockFile(TdFilePtr pFile) {
23,016✔
970
  if (NULL == pFile || pFile->fd < 0) {
23,016!
971
    terrno = TSDB_CODE_INVALID_PARA;
×
972
    return terrno;
×
973
  }
974
  int32_t code = (int32_t)flock(pFile->fd, LOCK_EX | LOCK_NB);
23,016✔
975
  if (-1 == code) {
23,016✔
976
    terrno = TAOS_SYSTEM_ERROR(errno);
15,517✔
977
    return terrno;
15,517✔
978
  }
979
  return 0;
7,499✔
980
}
981

982
int32_t taosUnLockFile(TdFilePtr pFile) {
4,430✔
983
  if (NULL == pFile || pFile->fd < 0) {
4,430!
984
    terrno = TSDB_CODE_INVALID_PARA;
×
985
    return terrno;
×
986
  }
987
  int32_t code = (int32_t)flock(pFile->fd, LOCK_UN | LOCK_NB);
4,430✔
988
  if (-1 == code) {
4,430!
989
    terrno = TAOS_SYSTEM_ERROR(errno);
×
990
    return terrno;
×
991
  }
992
  return 0;
4,430✔
993
}
994

995
int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
86✔
996
  if (NULL == pFile || pFile->fd < 0) {
86!
997
    terrno = TSDB_CODE_INVALID_PARA;
×
998
    return terrno;
×
999
  }
1000

1001
  int32_t code = ftruncate(pFile->fd, l_size);
86✔
1002
  if (-1 == code) {
86!
1003
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1004
    return terrno;
×
1005
  }
1006
  return 0;
86✔
1007
}
1008

1009
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
19✔
1010
  if (pFileOut == NULL || pFileIn == NULL) {
19!
1011
    terrno = TSDB_CODE_INVALID_PARA;
×
1012
    return -1;
×
1013
  }
1014
  if (pFileIn->fd < 0 || pFileOut->fd < 0) {
19!
1015
    terrno = TSDB_CODE_INVALID_PARA;
×
1016
    return -1;
×
1017
  }
1018

1019
#ifdef _TD_DARWIN_64
1020
  if (lseek(pFileIn->fd, (int32_t)(*offset), 0) < 0) {
1021
    terrno = TAOS_SYSTEM_ERROR(errno);
1022
    return -1;
1023
  }
1024
  int64_t writeLen = 0;
1025
  uint8_t buffer[_SEND_FILE_STEP_] = {0};
1026

1027
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
1028
    size_t rlen = read(pFileIn->fd, (void *)buffer, _SEND_FILE_STEP_);
1029
    if (rlen <= 0) {
1030
      return writeLen;
1031
    } else if (rlen < _SEND_FILE_STEP_) {
1032
      write(pFileOut->fd, (void *)buffer, (uint32_t)rlen);
1033
      return (int64_t)(writeLen + rlen);
1034
    } else {
1035
      write(pFileOut->fd, (void *)buffer, _SEND_FILE_STEP_);
1036
      writeLen += _SEND_FILE_STEP_;
1037
    }
1038
  }
1039

1040
  int64_t remain = size - writeLen;
1041
  if (remain > 0) {
1042
    size_t rlen = read(pFileIn->fd, (void *)buffer, (size_t)remain);
1043
    if (rlen <= 0) {
1044
      return writeLen;
1045
    } else {
1046
      write(pFileOut->fd, (void *)buffer, (uint32_t)remain);
1047
      writeLen += remain;
1048
    }
1049
  }
1050
  return writeLen;
1051

1052
#else  // for linux
1053

1054
  int64_t leftbytes = size;
19✔
1055
  int64_t sentbytes;
1056

1057
  while (leftbytes > 0) {
38✔
1058
#ifdef _TD_ARM_32
1059
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, (long int *)offset, leftbytes);
1060
#else
1061
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, offset, leftbytes);
19✔
1062
#endif
1063
    if (sentbytes == -1) {
19!
1064
      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
×
1065
        continue;
×
1066
      } else {
1067
        terrno = TAOS_SYSTEM_ERROR(errno);
×
1068
        return -1;
×
1069
      }
1070
    } else if (sentbytes == 0) {
19!
1071
      return (int64_t)(size - leftbytes);
×
1072
    }
1073

1074
    leftbytes -= sentbytes;
19✔
1075
  }
1076

1077
  return size;
19✔
1078
#endif
1079
}
1080

1081
bool lastErrorIsFileNotExist() { return terrno == TAOS_SYSTEM_ERROR(ENOENT); }
10,454✔
1082

1083
#endif  // WINDOWS
1084

1085
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
29,823,670✔
1086
  if (path == NULL) {
29,823,670!
1087
    terrno = TSDB_CODE_INVALID_PARA;
×
1088
    return NULL;
×
1089
  }
1090
  STUB_RAND_IO_ERR(NULL)
1091
  FILE *fp = NULL;
29,823,670✔
1092
#ifdef WINDOWS
1093
  HANDLE hFile = NULL;
1094
#else
1095
  int fd = -1;
29,823,670✔
1096
#endif
1097
  if (tdFileOptions & TD_FILE_STREAM) {
29,823,670✔
1098
    fp = taosOpenFileForStream(path, tdFileOptions);
55,966✔
1099
    if (fp == NULL) return NULL;
55,966✔
1100
  } else {
1101
#ifdef WINDOWS
1102
    hFile = taosOpenFileNotStream(path, tdFileOptions);
1103
    if (hFile == INVALID_HANDLE_VALUE) return NULL;
1104
#else
1105
    fd = taosOpenFileNotStream(path, tdFileOptions);
29,767,704✔
1106
    if (fd == -1) return NULL;
29,769,026✔
1107
#endif
1108
  }
1109

1110
  TdFilePtr pFile = (TdFilePtr)taosMemoryMalloc(sizeof(TdFile));
29,796,335✔
1111
  if (pFile == NULL) {
29,801,612!
1112
#ifdef WINDOWS
1113
    if (hFile != NULL) CloseHandle(hFile);
1114
#else
1115
    if (fd >= 0) (void)close(fd);
×
1116
#endif
1117
    if (fp != NULL) (void)fclose(fp);
×
1118
    terrno = TSDB_CODE_OUT_OF_MEMORY;
×
1119
    return NULL;
×
1120
  }
1121

1122
#if FILE_WITH_LOCK
1123
  (void)taosThreadRwlockInit(&(pFile->rwlock), NULL);
29,801,612✔
1124
#endif
1125
  pFile->fp = fp;
29,795,311✔
1126
  pFile->refId = 0;
29,795,311✔
1127

1128
#ifdef WINDOWS
1129
  pFile->hFile = hFile;
1130
  pFile->tdFileOptions = tdFileOptions;
1131
  // do nothing, since the property of pmode is set with _O_TEMPORARY; the OS will recycle
1132
  // the file handle, as well as the space on disk.
1133
#else
1134
  pFile->fd = fd;
29,795,311✔
1135
  // Remove it instantly, so when the program exits normally/abnormally, the file
1136
  // will be automatically remove by OS.
1137
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
29,795,311✔
1138
    if (-1 == unlink(path)) {
10,027✔
1139
      terrno = TAOS_SYSTEM_ERROR(errno);
579✔
1140
      (void)close(fd);
×
1141
      taosMemoryFree(pFile);
×
1142
      return NULL;
×
1143
    }
1144
  }
1145
#endif
1146

1147
  return pFile;
29,794,732✔
1148
}
1149

1150
int32_t taosCloseFile(TdFilePtr *ppFile) {
45,664,325✔
1151
  int32_t code = 0;
45,664,325✔
1152
  if (ppFile == NULL || *ppFile == NULL) {
45,664,325!
1153
    return 0;
15,859,798✔
1154
  }
1155
#if FILE_WITH_LOCK
1156
  (void)taosThreadRwlockWrlock(&((*ppFile)->rwlock));
29,804,527✔
1157
#endif
1158
  if ((*ppFile)->fp != NULL) {
29,805,714✔
1159
    TAOS_UNUSED(fflush((*ppFile)->fp));
55,156✔
1160
    TAOS_UNUSED(fclose((*ppFile)->fp));
55,156✔
1161
    (*ppFile)->fp = NULL;
55,156✔
1162
  }
1163
#ifdef WINDOWS
1164
  if ((*ppFile)->hFile != NULL) {
1165
    // FlushFileBuffers((*ppFile)->hFile);
1166
    if (!CloseHandle((*ppFile)->hFile)) {
1167
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1168
      code = -1;
1169
    }
1170
    (*ppFile)->hFile = NULL;
1171
#else
1172
  if ((*ppFile)->fd >= 0) {
29,805,714✔
1173
    // warning: never fsync silently in base lib
1174
    /*fsync((*ppFile)->fd);*/
1175
    code = close((*ppFile)->fd);
29,750,664✔
1176
    if (-1 == code) {
29,753,658!
1177
      terrno = TAOS_SYSTEM_ERROR(errno);
×
1178
    }
1179
    (*ppFile)->fd = -1;
29,753,771✔
1180
#endif
1181
  }
1182
  (*ppFile)->refId = 0;
29,808,821✔
1183
#if FILE_WITH_LOCK
1184
  (void)taosThreadRwlockUnlock(&((*ppFile)->rwlock));
29,808,821✔
1185
  (void)taosThreadRwlockDestroy(&((*ppFile)->rwlock));
29,808,569✔
1186
#endif
1187
  taosMemoryFree(*ppFile);
29,808,144✔
1188
  *ppFile = NULL;
29,807,738✔
1189
  return code;
29,807,738✔
1190
}
1191

1192
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) {
743,450✔
1193
  STUB_RAND_IO_ERR(terrno)
1194
  if (pFile == NULL) {
743,450!
1195
    terrno = TSDB_CODE_INVALID_PARA;
×
1196
    return -1;
×
1197
  }
1198

1199
  int32_t code = 0;
743,450✔
1200

1201
#ifdef WINDOWS
1202
#if FILE_WITH_LOCK
1203
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
1204
#endif
1205

1206
  if (pFile->hFile == NULL) {
1207
#if FILE_WITH_LOCK
1208
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
1209
#endif
1210

1211
    terrno = TSDB_CODE_INVALID_PARA;
1212
    return -1;
1213
  }
1214

1215
  DWORD      ret = 0;
1216
  OVERLAPPED ol = {0};
1217
  ol.OffsetHigh = (uint32_t)((offset & 0xFFFFFFFF00000000LL) >> 0x20);
1218
  ol.Offset = (uint32_t)(offset & 0xFFFFFFFFLL);
1219

1220
  SetLastError(0);
1221
  BOOL result = ReadFile(pFile->hFile, buf, count, &ret, &ol);
1222
  if (!result && GetLastError() != ERROR_HANDLE_EOF) {
1223
    code = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1224
    ret = -1;
1225
  }
1226
#else
1227
#if FILE_WITH_LOCK
1228
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
743,450✔
1229
#endif
1230

1231
  if (pFile->fd < 0) {
743,486!
1232
#if FILE_WITH_LOCK
1233
    (void)taosThreadRwlockUnlock(&(pFile->rwlock));
×
1234
#endif
1235
    terrno = TSDB_CODE_INVALID_PARA;
×
1236
    return -1;
×
1237
  }
1238
  int64_t ret = pread(pFile->fd, buf, count, offset);
743,486✔
1239
  if (-1 == ret) {
743,492!
1240
    code = TAOS_SYSTEM_ERROR(errno);
×
1241
  }
1242
#endif
1243
#if FILE_WITH_LOCK
1244
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
743,492✔
1245
#endif
1246

1247
  if (code) {
743,520!
1248
    terrno = code;
×
1249
    return -1;
×
1250
  }
1251

1252
  return ret;
743,542✔
1253
}
1254

1255
int32_t taosFsyncFile(TdFilePtr pFile) {
2,172,253✔
1256
  if (pFile == NULL) {
2,172,253✔
1257
    return 0;
2,685✔
1258
  }
1259

1260
  int32_t code = 0;
2,169,568✔
1261
  // this implementation is WRONG
1262
  // fflush is not a replacement of fsync
1263
  if (pFile->fp != NULL) {
2,169,568✔
1264
    code = fflush(pFile->fp);
448,326✔
1265
    if (0 != code) {
448,326!
1266
      terrno = TAOS_SYSTEM_ERROR(errno);
×
1267
      return terrno;
×
1268
    }
1269

1270
    return 0;
448,326✔
1271
  }
1272

1273
#ifdef WINDOWS
1274
  if (pFile->hFile != NULL) {
1275
    if (pFile->tdFileOptions & TD_FILE_WRITE_THROUGH) {
1276
      return 0;
1277
    }
1278
    bool ret = FlushFileBuffers(pFile->hFile);
1279
    if (!ret) {
1280
      terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1281
      return terrno;
1282
    }
1283
    return 0;
1284
  }
1285
#else
1286
  if (pFile->fd >= 0) {
1,721,242!
1287
    code = fsync(pFile->fd);
1,721,276✔
1288
    if (-1 == code) {
1,721,763!
1289
      terrno = TAOS_SYSTEM_ERROR(errno);
×
1290
      return terrno;
×
1291
    }
1292
  }
1293
#endif
1294

1295
  return 0;
1,721,797✔
1296
}
1297

1298
void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
171,684,864✔
1299
  if (pFile == NULL || pFile->fp == NULL) {
171,684,864!
1300
    return;
61,810,150✔
1301
  }
1302
  va_list ap;
1303
  va_start(ap, format);
109,874,714✔
1304
  (void)vfprintf(pFile->fp, format, ap);
109,874,714✔
1305
  va_end(ap);
109,977,366✔
1306
}
1307

1308
bool taosValidFile(TdFilePtr pFile) {
×
1309
#ifdef WINDOWS
1310
  return pFile != NULL && pFile->hFile != NULL;
1311
#else
1312
  return pFile != NULL && pFile->fd > 0;
×
1313
#endif
1314
}
1315

1316
int32_t taosUmaskFile(int32_t maskVal) {
13,180✔
1317
#ifdef WINDOWS
1318
  return 0;
1319
#else
1320
  return umask(maskVal);
13,180✔
1321
#endif
1322
}
1323

1324
int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict ptrBuf) {
20,210,177✔
1325
  int64_t ret = -1;
20,210,177✔
1326
  int32_t code = 0;
20,210,177✔
1327

1328
#if FILE_WITH_LOCK
1329
  (void)taosThreadRwlockRdlock(&(pFile->rwlock));
20,210,177✔
1330
#endif
1331
  if (pFile == NULL || ptrBuf == NULL) {
20,210,177!
1332
    terrno = TSDB_CODE_INVALID_PARA;
×
1333
    goto END;
×
1334
  }
1335
  if (*ptrBuf != NULL) {
20,210,177✔
1336
    taosMemoryFreeClear(*ptrBuf);
20,210,004!
1337
  }
1338

1339
  if (pFile->fp == NULL) {
20,210,177!
1340
    terrno = TSDB_CODE_INVALID_PARA;
×
1341
    goto END;
×
1342
  }
1343

1344
#ifdef WINDOWS
1345
  size_t bufferSize = 512;
1346
  *ptrBuf = taosMemoryMalloc(bufferSize);
1347
  if (*ptrBuf == NULL) {
1348
    goto END;
1349
  }
1350

1351
  size_t bytesRead = 0;
1352
  size_t totalBytesRead = 0;
1353

1354
  while (1) {
1355
    char *result = fgets(*ptrBuf + totalBytesRead, bufferSize - totalBytesRead, pFile->fp);
1356
    if (result == NULL) {
1357
      if (feof(pFile->fp)) {
1358
        break;
1359
      } else {
1360
        ret = -1;
1361
        terrno = TAOS_SYSTEM_ERROR(ferror(pFile->fp));
1362
        taosMemoryFreeClear(*ptrBuf);
1363
        goto END;
1364
      }
1365
    }
1366
    bytesRead = strlen(*ptrBuf + totalBytesRead);
1367
    totalBytesRead += bytesRead;
1368

1369
    if (totalBytesRead < bufferSize - 1 || (*ptrBuf)[totalBytesRead - 1] == '\n') {
1370
      break;
1371
    }
1372

1373
    bufferSize += 512;
1374
    void *newBuf = taosMemoryRealloc(*ptrBuf, bufferSize);
1375
    if (newBuf == NULL) {
1376
      taosMemoryFreeClear(*ptrBuf);
1377
      goto END;
1378
    }
1379

1380
    *ptrBuf = newBuf;
1381
  }
1382

1383
  (*ptrBuf)[totalBytesRead] = '\0';
1384
  ret = totalBytesRead;
1385
#else
1386
  size_t len = 0;
20,210,177✔
1387
  ret = getline(ptrBuf, &len, pFile->fp);
20,210,177✔
1388
  if (-1 == ret) {
20,210,177✔
1389
    terrno = TAOS_SYSTEM_ERROR(errno);
111✔
1390
  }
1391
#endif
1392

1393
END:
20,210,066✔
1394

1395
#if FILE_WITH_LOCK
1396
  (void)taosThreadRwlockUnlock(&(pFile->rwlock));
20,210,177✔
1397
#endif
1398

1399
  return ret;
20,210,177✔
1400
}
1401

1402
int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf) {
7,010,819✔
1403
  if (pFile == NULL || buf == NULL) {
7,010,819!
1404
    terrno = TSDB_CODE_INVALID_PARA;
×
1405
    return terrno;
×
1406
  }
1407

1408
  if (pFile->fp == NULL) {
7,010,819!
1409
    terrno = TSDB_CODE_INVALID_PARA;
×
1410
    return terrno;
×
1411
  }
1412

1413
  if (fgets(buf, maxSize, pFile->fp) == NULL) {
7,010,819✔
1414
    if (feof(pFile->fp)) {
22,150!
1415
      return 0;
22,150✔
1416
    } else {
1417
      terrno = TAOS_SYSTEM_ERROR(ferror(pFile->fp));
×
1418
      return terrno;
×
1419
    }
1420
  }
1421

1422
  return strlen(buf);
6,988,669✔
1423
}
1424

1425
int32_t taosEOFFile(TdFilePtr pFile) {
1,173,739✔
1426
  if (pFile == NULL) {
1,173,739!
1427
    terrno = TSDB_CODE_INVALID_PARA;
×
1428
    return -1;
×
1429
  }
1430
  if (pFile->fp == NULL) {
1,173,739!
1431
    terrno = TSDB_CODE_INVALID_PARA;
×
1432
    return -1;
×
1433
  }
1434

1435
  return feof(pFile->fp);
1,173,739✔
1436
}
1437

1438
bool taosCheckAccessFile(const char *pathname, int32_t tdFileAccessOptions) {
540,187✔
1439
  if (pathname == NULL) {
540,187!
1440
    terrno = TSDB_CODE_INVALID_PARA;
×
1441
    return false;  // invalid parameter
×
1442
  }
1443
  int flags = 0;
540,187✔
1444

1445
  if (tdFileAccessOptions & TD_FILE_ACCESS_EXIST_OK) {
540,187!
1446
    flags |= F_OK;
540,249✔
1447
  }
1448

1449
  if (tdFileAccessOptions & TD_FILE_ACCESS_READ_OK) {
540,187✔
1450
    flags |= R_OK;
19,855✔
1451
  }
1452

1453
  if (tdFileAccessOptions & TD_FILE_ACCESS_WRITE_OK) {
540,187✔
1454
    flags |= W_OK;
19,855✔
1455
  }
1456
#ifdef WINDOWS
1457
  return _access(pathname, flags) == 0;
1458
#else
1459
  return access(pathname, flags) == 0;
540,187✔
1460
#endif
1461
}
1462

1463
bool taosCheckExistFile(const char *pathname) { return taosCheckAccessFile(pathname, TD_FILE_ACCESS_EXIST_OK); };
520,245✔
1464

1465
int32_t taosCompressFile(char *srcFileName, char *destFileName) {
×
1466
  OS_PARAM_CHECK(srcFileName);
×
1467
  OS_PARAM_CHECK(destFileName);
×
1468
  int32_t   compressSize = 163840;
×
1469
  int32_t   ret = 0;
×
1470
  int32_t   len = 0;
×
1471
  gzFile    dstFp = NULL;
×
1472
  TdFilePtr pSrcFile = NULL;
×
1473

1474
  char *data = taosMemoryMalloc(compressSize);
×
1475
  if (NULL == data) {
×
1476
    return terrno;
×
1477
  }
1478

1479
  pSrcFile = taosOpenFile(srcFileName, TD_FILE_READ | TD_FILE_STREAM);
×
1480
  if (pSrcFile == NULL) {
×
1481
    ret = terrno;
×
1482
    goto cmp_end;
×
1483
  }
1484

1485
  int access = O_BINARY | O_WRONLY | O_TRUNC | O_CREAT;
×
1486
#ifdef WINDOWS
1487
  int32_t pmode = _S_IREAD | _S_IWRITE;
1488
#else
1489
  int32_t pmode = S_IRWXU | S_IRWXG | S_IRWXO;
×
1490
#endif
1491
  int fd = open(destFileName, access, pmode);
×
1492
  if (-1 == fd) {
×
1493
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1494
    ret = terrno;
×
1495
    goto cmp_end;
×
1496
  }
1497

1498
  // Both gzclose() and fclose() will close the associated fd, so they need to have different fds.
1499
  FileFd gzFd = dup(fd);
×
1500
  if (-1 == gzFd) {
×
1501
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1502
    ret = terrno;
×
1503
    goto cmp_end;
×
1504
  }
1505
  dstFp = gzdopen(gzFd, "wb6f");
×
1506
  if (dstFp == NULL) {
×
1507
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1508
    ret = terrno;
×
1509
    (void)close(gzFd);
×
1510
    goto cmp_end;
×
1511
  }
1512

1513
  while (!feof(pSrcFile->fp)) {
×
1514
    len = (int32_t)fread(data, 1, compressSize, pSrcFile->fp);
×
1515
    if (len > 0) {
×
1516
      if (gzwrite(dstFp, data, len) == 0) {
×
1517
        terrno = TAOS_SYSTEM_ERROR(errno);
×
1518
        ret = terrno;
×
1519
        goto cmp_end;
×
1520
      }
1521
    }
1522
  }
1523

1524
cmp_end:
×
1525

1526
  if (fd >= 0) {
×
1527
    TAOS_SKIP_ERROR(close(fd));
×
1528
  }
1529
  if (pSrcFile) {
×
1530
    TAOS_SKIP_ERROR(taosCloseFile(&pSrcFile));
×
1531
  }
1532

1533
  if (dstFp) {
×
1534
    TAOS_SKIP_ERROR(gzclose(dstFp));
×
1535
  }
1536

1537
  taosMemoryFree(data);
×
1538

1539
  return ret;
×
1540
}
1541

1542
int32_t taosSetFileHandlesLimit() {
9,094✔
1543
#ifdef WINDOWS
1544
  const int max_handles = 8192;
1545
  int       res = _setmaxstdio(max_handles);
1546
  return res == max_handles ? 0 : -1;
1547
#endif
1548
  return 0;
9,094✔
1549
}
1550

1551
int32_t taosLinkFile(char *src, char *dst) {
126✔
1552
#ifndef WINDOWS
1553
  if (-1 == link(src, dst)) {
126!
1554
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1555
    return terrno;
×
1556
  }
1557
#endif
1558
  return 0;
126✔
1559
}
1560

1561
FILE *taosOpenCFile(const char *filename, const char *mode) {
836,537✔
1562
  if (filename == NULL || mode == NULL) {
836,537!
1563
    terrno = TSDB_CODE_INVALID_PARA;
×
1564
    return NULL;
×
1565
  }
1566
  STUB_RAND_IO_ERR(NULL)
1567
  FILE *f = fopen(filename, mode);
837,785✔
1568
  if (NULL == f) {
838,890!
1569
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1570
  }
1571
  return f;
838,890✔
1572
}
1573

1574
int taosSeekCFile(FILE *file, int64_t offset, int whence) {
520,633✔
1575
  if(NULL == file) {
520,633!
1576
    terrno = TSDB_CODE_INVALID_PARA;
×
1577
    return terrno;
×
1578
  }
1579
#ifdef WINDOWS
1580
  return _fseeki64(file, offset, whence);
1581
#else
1582
  int     code = fseeko(file, offset, whence);
520,633✔
1583
  if (-1 == code) {
520,631!
1584
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1585
    code = terrno;
×
1586
  }
1587
  return code;
520,641✔
1588
#endif
1589
}
1590

1591
size_t taosReadFromCFile(void *buffer, size_t size, size_t count, FILE *stream) {
520,628✔
1592
  if (buffer == NULL || stream == NULL) {
520,628!
1593
    terrno = TSDB_CODE_INVALID_PARA;
×
1594
    return 0;
×
1595
  }
1596
  STUB_RAND_IO_ERR(terrno)
1597
  return fread(buffer, size, count, stream);
520,639✔
1598
}
1599

1600
size_t taosWriteToCFile(const void *ptr, size_t size, size_t nitems, FILE *stream) {
×
1601
  STUB_RAND_IO_ERR(terrno)
1602
  return fwrite(ptr, size, nitems, stream);
×
1603
}
1604

1605
int taosCloseCFile(FILE *f) { return fclose(f); }
838,801✔
1606

1607
int taosSetAutoDelFile(char *path) {
838,890✔
1608
#ifdef WINDOWS
1609
  bool succ = SetFileAttributes(path, FILE_ATTRIBUTE_TEMPORARY);
1610
  if (succ) {
1611
    return 0;
1612
  } else {
1613
    terrno = TAOS_SYSTEM_WINAPI_ERROR(GetLastError());
1614
    return terrno;
1615
  }
1616
#else
1617
  if (-1 == unlink(path)) {
838,890!
1618
    terrno = TAOS_SYSTEM_ERROR(errno);
×
1619
    return terrno;
×
1620
  }
1621
  return 0;
838,890✔
1622
#endif
1623
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc