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

wafwerar's avatar
wafwerar 已提交
19
#ifdef WINDOWS
20
#include <io.h>
wafwerar's avatar
wafwerar 已提交
21 22 23
#define F_OK 0
#define W_OK 2
#define R_OK 4
24

wafwerar's avatar
wafwerar 已提交
25 26
#define _SEND_FILE_STEP_ 1000

27
#else
28 29
#include <fcntl.h>
#include <sys/file.h>
30 31

#if !defined(_TD_DARWIN_64)
L
Liu Jicong 已提交
32
#include <sys/sendfile.h>
33
#endif
34 35 36 37
#include <sys/stat.h>
#include <unistd.h>
#define LINUX_FILE_NO_TEXT_OPTION 0
#define O_TEXT                    LINUX_FILE_NO_TEXT_OPTION
wafwerar's avatar
wafwerar 已提交
38 39

#define _SEND_FILE_STEP_ 1000
40 41
#endif

wafwerar's avatar
wafwerar 已提交
42 43 44 45 46 47 48 49 50 51 52
#if defined(WINDOWS)
typedef int32_t FileFd;
typedef int32_t SocketFd;
#else
typedef int32_t FileFd;
typedef int32_t SocketFd;
#endif

typedef int32_t FileFd;

typedef struct TdFile {
wafwerar's avatar
wafwerar 已提交
53
  TdThreadRwlock rwlock;
L
Liu Jicong 已提交
54 55 56
  int            refId;
  FileFd         fd;
  FILE          *fp;
wafwerar's avatar
wafwerar 已提交
57 58
} * TdFilePtr, TdFile;

59 60
#define FILE_WITH_LOCK 1

H
Hongze Cheng 已提交
61
typedef struct AutoDelFile *AutoDelFilePtr;
wafwerar's avatar
wafwerar 已提交
62
typedef struct AutoDelFile {
H
Hongze Cheng 已提交
63 64
  char          *name;
  AutoDelFilePtr lastAutoDelFilePtr;
wafwerar's avatar
wafwerar 已提交
65
} AutoDelFile;
H
Hongze Cheng 已提交
66
static TdThreadMutex  autoDelFileLock;
wafwerar's avatar
wafwerar 已提交
67
static AutoDelFilePtr nowAutoDelFilePtr = NULL;
H
Hongze Cheng 已提交
68
static TdThreadOnce   autoDelFileInit = PTHREAD_ONCE_INIT;
wafwerar's avatar
wafwerar 已提交
69

70
void taosGetTmpfilePath(const char *inputTmpDir, const char *fileNamePrefix, char *dstPath) {
wafwerar's avatar
wafwerar 已提交
71
#ifdef WINDOWS
S
Shengliang Guan 已提交
72
  const char *tdengineTmpFileNamePrefix = "tdengine-";
S
TD-4088  
Shengliang Guan 已提交
73
  char        tmpPath[PATH_MAX];
S
Shengliang Guan 已提交
74

S
Shengliang Guan 已提交
75 76
  int32_t len = (int32_t)strlen(inputTmpDir);
  memcpy(tmpPath, inputTmpDir, len);
S
TD-4088  
Shengliang Guan 已提交
77 78 79

  if (tmpPath[len - 1] != '/' && tmpPath[len - 1] != '\\') {
    tmpPath[len++] = '\\';
80
  }
S
Shengliang Guan 已提交
81

82
  strcpy(tmpPath + len, tdengineTmpFileNamePrefix);
S
Shengliang Guan 已提交
83 84 85
  if (strlen(tmpPath) + strlen(fileNamePrefix) + strlen("-%d-%s") < PATH_MAX) {
    strcat(tmpPath, fileNamePrefix);
    strcat(tmpPath, "-%d-%s");
S
Shengliang Guan 已提交
86
  }
S
Shengliang Guan 已提交
87

S
TD-4088  
Shengliang Guan 已提交
88 89
  char rand[8] = {0};
  taosRandStr(rand, tListLen(rand) - 1);
S
Shengliang Guan 已提交
90
  snprintf(dstPath, PATH_MAX, tmpPath, getpid(), rand);
S
TD-1912  
Shengliang Guan 已提交
91

S
TD-4088  
Shengliang Guan 已提交
92
#else
S
Shengliang Guan 已提交
93

S
TD-4088  
Shengliang Guan 已提交
94
  const char *tdengineTmpFileNamePrefix = "tdengine-";
S
Shengliang Guan 已提交
95

96
  char    tmpPath[PATH_MAX];
S
Shengliang Guan 已提交
97 98
  int32_t len = strlen(inputTmpDir);
  memcpy(tmpPath, inputTmpDir, len);
S
TD-4088  
Shengliang Guan 已提交
99
  static uint64_t seqId = 0;
S
Shengliang Guan 已提交
100

S
TD-4088  
Shengliang Guan 已提交
101 102
  if (tmpPath[len - 1] != '/') {
    tmpPath[len++] = '/';
S
TD-1912  
Shengliang Guan 已提交
103
  }
S
Shengliang Guan 已提交
104

S
TD-4088  
Shengliang Guan 已提交
105 106 107 108
  strcpy(tmpPath + len, tdengineTmpFileNamePrefix);
  if (strlen(tmpPath) + strlen(fileNamePrefix) + strlen("-%d-%s") < PATH_MAX) {
    strcat(tmpPath, fileNamePrefix);
    strcat(tmpPath, "-%d-%s");
S
Shengliang Guan 已提交
109 110
  }

S
TD-4088  
Shengliang Guan 已提交
111 112 113
  char rand[32] = {0};

  sprintf(rand, "%" PRIu64, atomic_add_fetch_64(&seqId, 1));
S
Shengliang Guan 已提交
114

S
TD-4088  
Shengliang Guan 已提交
115
  snprintf(dstPath, PATH_MAX, tmpPath, getpid(), rand);
S
Shengliang Guan 已提交
116

S
TD-4088  
Shengliang Guan 已提交
117
#endif
S
Shengliang Guan 已提交
118
}
S
TD-4088  
Shengliang Guan 已提交
119

120
int64_t taosCopyFile(const char *from, const char *to) {
wafwerar's avatar
wafwerar 已提交
121
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
122 123 124 125 126
  if (CopyFile(from, to, 0)) {
    return 1;
  } else {
    return -1;
  }
127 128 129 130 131 132
#else
  char    buffer[4096];
  int64_t size = 0;
  int64_t bytes;

  // fidfrom = open(from, O_RDONLY);
133
  TdFilePtr pFileFrom = taosOpenFile(from, TD_FILE_READ);
134 135 136
  if (pFileFrom == NULL) goto _err;

  // fidto = open(to, O_WRONLY | O_CREAT | O_EXCL, 0755);
137
  TdFilePtr pFileTo = taosOpenFile(to, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_EXCL);
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
  if (pFileTo == NULL) goto _err;

  while (true) {
    bytes = taosReadFile(pFileFrom, buffer, sizeof(buffer));
    if (bytes < 0) goto _err;
    if (bytes == 0) break;

    size += bytes;

    if (taosWriteFile(pFileTo, (void *)buffer, bytes) < bytes) goto _err;
    if (bytes < sizeof(buffer)) break;
  }

  taosFsyncFile(pFileTo);

  taosCloseFile(&pFileFrom);
  taosCloseFile(&pFileTo);
  return size;

_err:
  if (pFileFrom != NULL) taosCloseFile(&pFileFrom);
  if (pFileTo != NULL) taosCloseFile(&pFileTo);
160
  taosRemoveFile(to);
161 162 163 164
  return -1;
#endif
}

C
Cary Xu 已提交
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
TdFilePtr taosCreateFile(const char *path, int32_t tdFileOptions) {
  TdFilePtr fp = taosOpenFile(path, tdFileOptions);
  if (!fp) {
    if (errno == ENOENT) {
      // Try to create directory recursively
      char *s = strdup(path);
      if (taosMulMkDir(taosDirName(s)) != 0) {
        taosMemoryFree(s);
        return NULL;
      }
      taosMemoryFree(s);
      fp = taosOpenFile(path, tdFileOptions);
      if (!fp) {
        return NULL;
      }
    }
  }
  return fp;
}

185 186
int32_t taosRemoveFile(const char *path) { return remove(path); }

187
int32_t taosRenameFile(const char *oldName, const char *newName) {
wafwerar's avatar
wafwerar 已提交
188
#ifdef WINDOWS
189 190
  bool code = MoveFileEx(oldName, newName, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
  if (!code) {
C
Cary Xu 已提交
191
    printf("failed to rename file %s to %s, reason:%s\n", oldName, newName, strerror(errno));
192 193
  }

A
Alex Duan 已提交
194
  return code ? 0 : -1;
195 196 197
#else
  int32_t code = rename(oldName, newName);
  if (code < 0) {
C
Cary Xu 已提交
198
    printf("failed to rename file %s to %s, reason:%s\n", oldName, newName, strerror(errno));
199 200 201 202 203 204 205
  }

  return code;
#endif
}

int32_t taosStatFile(const char *path, int64_t *size, int32_t *mtime) {
wafwerar's avatar
wafwerar 已提交
206
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
207
  struct _stati64 fileStat;
H
Hongze Cheng 已提交
208
  int32_t         code = _stati64(path, &fileStat);
209
#else
wafwerar's avatar
wafwerar 已提交
210
  struct stat fileStat;
H
Hongze Cheng 已提交
211
  int32_t     code = stat(path, &fileStat);
212
#endif
213 214 215 216 217 218 219 220 221 222 223 224 225 226
  if (code < 0) {
    return code;
  }

  if (size != NULL) {
    *size = fileStat.st_size;
  }

  if (mtime != NULL) {
    *mtime = fileStat.st_mtime;
  }

  return 0;
}
wafwerar's avatar
wafwerar 已提交
227 228 229 230 231
int32_t taosDevInoFile(TdFilePtr pFile, int64_t *stDev, int64_t *stIno) {
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
232

wafwerar's avatar
wafwerar 已提交
233
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
234 235

  BY_HANDLE_FILE_INFORMATION bhfi;
236
  HANDLE                     handle = (HANDLE)_get_osfhandle(pFile->fd);
wafwerar's avatar
wafwerar 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249
  if (GetFileInformationByHandle(handle, &bhfi) == FALSE) {
    printf("taosFStatFile get file info fail.");
    return -1;
  }

  if (stDev != NULL) {
    *stDev = (int64_t)(bhfi.dwVolumeSerialNumber);
  }

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

250
#else
251

wafwerar's avatar
wafwerar 已提交
252 253
  struct stat fileStat;
  int32_t     code = fstat(pFile->fd, &fileStat);
254
  if (code < 0) {
wafwerar's avatar
wafwerar 已提交
255
    printf("taosFStatFile run fstat fail.");
256 257 258 259 260 261 262 263 264 265
    return code;
  }

  if (stDev != NULL) {
    *stDev = fileStat.st_dev;
  }

  if (stIno != NULL) {
    *stIno = fileStat.st_ino;
  }
wafwerar's avatar
wafwerar 已提交
266
#endif
267 268 269

  return 0;
}
270

wafwerar's avatar
wafwerar 已提交
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
void autoDelFileList() {
  taosThreadMutexLock(&autoDelFileLock);
  while (nowAutoDelFilePtr != NULL) {
    taosRemoveFile(nowAutoDelFilePtr->name);
    AutoDelFilePtr tmp = nowAutoDelFilePtr->lastAutoDelFilePtr;
    taosMemoryFree(nowAutoDelFilePtr->name);
    taosMemoryFree(nowAutoDelFilePtr);
    nowAutoDelFilePtr = tmp;
  }
  taosThreadMutexUnlock(&autoDelFileLock);
  taosThreadMutexDestroy(&autoDelFileLock);
}

void autoDelFileListInit() {
  taosThreadMutexInit(&autoDelFileLock, NULL);
  atexit(autoDelFileList);
}

void autoDelFileListAdd(const char *path) {
  taosThreadOnce(&autoDelFileInit, autoDelFileListInit);
  taosThreadMutexLock(&autoDelFileLock);
  AutoDelFilePtr tmp = taosMemoryMalloc(sizeof(AutoDelFile));
  tmp->lastAutoDelFilePtr = nowAutoDelFilePtr;
  tmp->name = taosMemoryStrDup(path);
  nowAutoDelFilePtr = tmp;
  taosThreadMutexUnlock(&autoDelFileLock);
}

299
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
L
Liu Jicong 已提交
300
  int   fd = -1;
301 302 303 304 305
  FILE *fp = NULL;
  if (tdFileOptions & TD_FILE_STREAM) {
    char *mode = NULL;
    if (tdFileOptions & TD_FILE_APPEND) {
      mode = (tdFileOptions & TD_FILE_TEXT) ? "at+" : "ab+";
L
Liu Jicong 已提交
306
    } else if (tdFileOptions & TD_FILE_TRUNC) {
307
      mode = (tdFileOptions & TD_FILE_TEXT) ? "wt+" : "wb+";
L
Liu Jicong 已提交
308
    } else if ((tdFileOptions & TD_FILE_READ) && !(tdFileOptions & TD_FILE_WRITE)) {
309
      mode = (tdFileOptions & TD_FILE_TEXT) ? "rt" : "rb";
L
Liu Jicong 已提交
310
    } else {
311 312 313 314 315
      mode = (tdFileOptions & TD_FILE_TEXT) ? "rt+" : "rb+";
    }
    assert(!(tdFileOptions & TD_FILE_EXCL));
    fp = fopen(path, mode);
    if (fp == NULL) {
S
Shengliang Guan 已提交
316
      // terrno = TAOS_SYSTEM_ERROR(errno);
317 318 319 320
      return NULL;
    }
  } else {
    int access = O_BINARY;
321
    access |= (tdFileOptions & TD_FILE_CREATE) ? O_CREAT : 0;
322 323 324 325 326 327 328 329 330 331 332
    if ((tdFileOptions & TD_FILE_WRITE) && (tdFileOptions & TD_FILE_READ)) {
      access |= O_RDWR;
    } else if (tdFileOptions & TD_FILE_WRITE) {
      access |= O_WRONLY;
    } else if (tdFileOptions & TD_FILE_READ) {
      access |= O_RDONLY;
    }
    access |= (tdFileOptions & TD_FILE_TRUNC) ? O_TRUNC : 0;
    access |= (tdFileOptions & TD_FILE_APPEND) ? O_APPEND : 0;
    access |= (tdFileOptions & TD_FILE_TEXT) ? O_TEXT : 0;
    access |= (tdFileOptions & TD_FILE_EXCL) ? O_EXCL : 0;
L
Liu Jicong 已提交
333 334 335
#ifdef WINDOWS
    fd = _open(path, access, _S_IREAD | _S_IWRITE);
#else
336
    fd = open(path, access, S_IRWXU | S_IRWXG | S_IRWXO);
L
Liu Jicong 已提交
337
#endif
338
    if (fd == -1) {
S
Shengliang Guan 已提交
339
      // terrno = TAOS_SYSTEM_ERROR(errno);
340 341 342 343
      return NULL;
    }
  }

wafwerar's avatar
wafwerar 已提交
344
  TdFilePtr pFile = (TdFilePtr)taosMemoryMalloc(sizeof(TdFile));
345
  if (pFile == NULL) {
S
Shengliang Guan 已提交
346
    // terrno = TSDB_CODE_OUT_OF_MEMORY;
347 348
    if (fd >= 0) close(fd);
    if (fp != NULL) fclose(fp);
349 350
    return NULL;
  }
351
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
352
  taosThreadRwlockInit(&(pFile->rwlock), NULL);
353
#endif
354 355 356
  pFile->fd = fd;
  pFile->fp = fp;
  pFile->refId = 0;
wafwerar's avatar
wafwerar 已提交
357
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
wafwerar's avatar
wafwerar 已提交
358
    autoDelFileListAdd(path);
wafwerar's avatar
wafwerar 已提交
359
  }
360 361 362
  return pFile;
}

L
Liu Jicong 已提交
363 364
int32_t taosCloseFile(TdFilePtr *ppFile) {
  int32_t code = 0;
365 366 367 368
  if (ppFile == NULL || *ppFile == NULL) {
    return 0;
  }
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
369
  taosThreadRwlockWrlock(&((*ppFile)->rwlock));
370
#endif
371 372 373 374 375 376
  if ((*ppFile)->fp != NULL) {
    fflush((*ppFile)->fp);
    fclose((*ppFile)->fp);
    (*ppFile)->fp = NULL;
  }
  if ((*ppFile)->fd >= 0) {
377
#ifdef WINDOWS
378 379
    HANDLE h = (HANDLE)_get_osfhandle((*ppFile)->fd);
    !FlushFileBuffers(h);
380
#else
L
Liu Jicong 已提交
381 382
    // warning: never fsync silently in base lib
    /*fsync((*ppFile)->fd);*/
383
#endif
L
Liu Jicong 已提交
384
    code = close((*ppFile)->fd);
385 386
    (*ppFile)->fd = -1;
  }
387
  (*ppFile)->refId = 0;
388
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
389 390
  taosThreadRwlockUnlock(&((*ppFile)->rwlock));
  taosThreadRwlockDestroy(&((*ppFile)->rwlock));
391
#endif
wafwerar's avatar
wafwerar 已提交
392
  taosMemoryFree(*ppFile);
393
  *ppFile = NULL;
L
Liu Jicong 已提交
394
  return code;
395 396 397
}

int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
398
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
399
  taosThreadRwlockRdlock(&(pFile->rwlock));
400
#endif
L
Liu Jicong 已提交
401
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
S
TD-1912  
Shengliang Guan 已提交
402 403
  int64_t leftbytes = count;
  int64_t readbytes;
404
  char   *tbuf = (char *)buf;
S
Shengliang Guan 已提交
405 406

  while (leftbytes > 0) {
407
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
408
    readbytes = _read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
409
#else
410
    readbytes = read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
411
#endif
S
Shengliang Guan 已提交
412 413 414 415
    if (readbytes < 0) {
      if (errno == EINTR) {
        continue;
      } else {
416
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
417
        taosThreadRwlockUnlock(&(pFile->rwlock));
418
#endif
S
Shengliang Guan 已提交
419 420 421
        return -1;
      }
    } else if (readbytes == 0) {
422
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
423
      taosThreadRwlockUnlock(&(pFile->rwlock));
424
#endif
S
TD-1912  
Shengliang Guan 已提交
425
      return (int64_t)(count - leftbytes);
S
Shengliang Guan 已提交
426 427 428 429 430 431
    }

    leftbytes -= readbytes;
    tbuf += readbytes;
  }

432
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
433
  taosThreadRwlockUnlock(&(pFile->rwlock));
434
#endif
S
TD-1912  
Shengliang Guan 已提交
435
  return count;
S
Shengliang Guan 已提交
436 437
}

438
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) {
439
  if (pFile == NULL) {
440 441
    return 0;
  }
442
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
443
  taosThreadRwlockRdlock(&(pFile->rwlock));
444
#endif
L
Liu Jicong 已提交
445
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
wafwerar's avatar
wafwerar 已提交
446
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
447 448
  size_t pos = _lseeki64(pFile->fd, 0, SEEK_CUR);
  _lseeki64(pFile->fd, offset, SEEK_SET);
wafwerar's avatar
wafwerar 已提交
449
  int64_t ret = _read(pFile->fd, buf, count);
wafwerar's avatar
wafwerar 已提交
450
  _lseeki64(pFile->fd, pos, SEEK_SET);
wafwerar's avatar
wafwerar 已提交
451
#else
452
  int64_t ret = pread(pFile->fd, buf, count, offset);
wafwerar's avatar
wafwerar 已提交
453
#endif
454
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
455
  taosThreadRwlockUnlock(&(pFile->rwlock));
456 457
#endif
  return ret;
458 459 460
}

int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
wafwerar's avatar
wafwerar 已提交
461 462 463
  if (pFile == NULL) {
    return 0;
  }
464
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
465
  taosThreadRwlockWrlock(&(pFile->rwlock));
466
#endif
467 468 469
  if (pFile->fd < 0) {
    return 0;
  }
470

471
  int64_t nleft = count;
S
TD-1912  
Shengliang Guan 已提交
472
  int64_t nwritten = 0;
473
  char   *tbuf = (char *)buf;
S
Shengliang Guan 已提交
474 475

  while (nleft > 0) {
476
    nwritten = write(pFile->fd, (void *)tbuf, (uint32_t)nleft);
S
Shengliang Guan 已提交
477 478 479 480
    if (nwritten < 0) {
      if (errno == EINTR) {
        continue;
      }
481
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
482
      taosThreadRwlockUnlock(&(pFile->rwlock));
483
#endif
S
Shengliang Guan 已提交
484 485 486 487 488
      return -1;
    }
    nleft -= nwritten;
    tbuf += nwritten;
  }
489

490
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
491
  taosThreadRwlockUnlock(&(pFile->rwlock));
492
#endif
493
  return count;
S
Shengliang Guan 已提交
494 495
}

496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
int64_t taosPWriteFile(TdFilePtr pFile, const void *buf, int64_t count, int64_t offset) {
  if (pFile == NULL) {
    return 0;
  }
#if FILE_WITH_LOCK
  taosThreadRwlockWrlock(&(pFile->rwlock));
#endif
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
#ifdef WINDOWS
  size_t pos = _lseeki64(pFile->fd, 0, SEEK_CUR);
  _lseeki64(pFile->fd, offset, SEEK_SET);
  int64_t ret = _write(pFile->fd, buf, count);
  _lseeki64(pFile->fd, pos, SEEK_SET);
#else
  int64_t ret = pwrite(pFile->fd, buf, count, offset);
#endif
#if FILE_WITH_LOCK
  taosThreadRwlockUnlock(&(pFile->rwlock));
#endif
  return ret;
}

518
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
519
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
520
  taosThreadRwlockRdlock(&(pFile->rwlock));
521
#endif
L
Liu Jicong 已提交
522
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
wafwerar's avatar
wafwerar 已提交
523
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
524
  int64_t ret = _lseeki64(pFile->fd, offset, whence);
wafwerar's avatar
wafwerar 已提交
525
#else
L
Liu Jicong 已提交
526
  int64_t ret = lseek(pFile->fd, offset, whence);
wafwerar's avatar
wafwerar 已提交
527
#endif
528
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
529
  taosThreadRwlockUnlock(&(pFile->rwlock));
530 531
#endif
  return ret;
532
}
S
Shengliang Guan 已提交
533

534
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) {
535 536 537
  if (pFile == NULL) {
    return 0;
  }
L
Liu Jicong 已提交
538
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
539

540
  struct stat fileStat;
541
#ifdef WINDOWS
542
  int32_t code = _fstat(pFile->fd, &fileStat);
543
#else
544
  int32_t code = fstat(pFile->fd, &fileStat);
545
#endif
546 547 548
  if (code < 0) {
    return code;
  }
H
Hongze Cheng 已提交
549

550 551 552
  if (size != NULL) {
    *size = fileStat.st_size;
  }
H
Hongze Cheng 已提交
553

554 555 556
  if (mtime != NULL) {
    *mtime = fileStat.st_mtime;
  }
H
Hongze Cheng 已提交
557

558 559
  return 0;
}
H
Hongze Cheng 已提交
560

561
int32_t taosLockFile(TdFilePtr pFile) {
wafwerar's avatar
wafwerar 已提交
562
#ifdef WINDOWS
563 564
  return 0;
#else
L
Liu Jicong 已提交
565
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
566

567 568 569
  return (int32_t)flock(pFile->fd, LOCK_EX | LOCK_NB);
#endif
}
H
Hongze Cheng 已提交
570

571
int32_t taosUnLockFile(TdFilePtr pFile) {
wafwerar's avatar
wafwerar 已提交
572
#ifdef WINDOWS
573 574
  return 0;
#else
L
Liu Jicong 已提交
575
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
576

577 578 579 580 581
  return (int32_t)flock(pFile->fd, LOCK_UN | LOCK_NB);
#endif
}

int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
wafwerar's avatar
wafwerar 已提交
582
#ifdef WINDOWS
583 584
  if (pFile->fd < 0) {
    errno = EBADF;
585
    printf("Ftruncate file error, fd arg was negative\n");
586
    return -1;
H
Hongze Cheng 已提交
587 588
  }

589
  HANDLE h = (HANDLE)_get_osfhandle(pFile->fd);
H
Hongze Cheng 已提交
590

591 592 593 594
  LARGE_INTEGER li_0;
  li_0.QuadPart = (int64_t)0;
  BOOL cur = SetFilePointerEx(h, li_0, NULL, FILE_CURRENT);
  if (!cur) {
wafwerar's avatar
wafwerar 已提交
595
    printf("SetFilePointerEx Error getting current position in file.\n");
596 597
    return -1;
  }
H
Hongze Cheng 已提交
598

599 600 601 602 603
  LARGE_INTEGER li_size;
  li_size.QuadPart = l_size;
  BOOL cur2 = SetFilePointerEx(h, li_size, NULL, FILE_BEGIN);
  if (cur2 == 0) {
    int error = GetLastError();
wafwerar's avatar
wafwerar 已提交
604
    printf("SetFilePointerEx GetLastError is: %d\n", error);
605 606 607 608 609 610 611 612 613 614 615 616 617
    switch (error) {
      case ERROR_INVALID_HANDLE:
        errno = EBADF;
        break;
      default:
        errno = EIO;
        break;
    }
    return -1;
  }

  if (!SetEndOfFile(h)) {
    int error = GetLastError();
wafwerar's avatar
wafwerar 已提交
618
    printf("SetEndOfFile GetLastError is:%d", error);
619 620 621 622 623 624 625 626 627 628 629 630 631
    switch (error) {
      case ERROR_INVALID_HANDLE:
        errno = EBADF;
        break;
      default:
        errno = EIO;
        break;
    }
    return -1;
  }

  return 0;
#else
632 633 634
  if (pFile == NULL) {
    return 0;
  }
L
Liu Jicong 已提交
635
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
636

637 638 639 640 641
  return ftruncate(pFile->fd, l_size);
#endif
}

int32_t taosFsyncFile(TdFilePtr pFile) {
642 643 644 645
  if (pFile == NULL) {
    return 0;
  }

L
Liu Jicong 已提交
646 647
  // this implementation is WRONG
  // fflush is not a replacement of fsync
648
  if (pFile->fp != NULL) return fflush(pFile->fp);
649
  if (pFile->fd >= 0) {
650
#ifdef WINDOWS
651 652
    HANDLE h = (HANDLE)_get_osfhandle(pFile->fd);
    return !FlushFileBuffers(h);
653
#else
654
    return fsync(pFile->fd);
655
#endif
656
  }
657
  return 0;
H
Hongze Cheng 已提交
658 659
}

wafwerar's avatar
wafwerar 已提交
660 661 662
int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
  if (pFileOut == NULL || pFileIn == NULL) {
    return 0;
S
TD-4088  
Shengliang Guan 已提交
663
  }
wafwerar's avatar
wafwerar 已提交
664
  assert(pFileIn->fd >= 0 && pFileOut->fd >= 0);
S
TD-4088  
Shengliang Guan 已提交
665

wafwerar's avatar
wafwerar 已提交
666
#ifdef WINDOWS
S
TD-4088  
Shengliang Guan 已提交
667

wafwerar's avatar
wafwerar 已提交
668
  _lseeki64(pFileIn->fd, *offset, 0);
S
TD-4088  
Shengliang Guan 已提交
669 670 671
  int64_t writeLen = 0;
  uint8_t buffer[_SEND_FILE_STEP_] = {0};

wafwerar's avatar
wafwerar 已提交
672
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
wafwerar's avatar
wafwerar 已提交
673
    size_t rlen = _read(pFileIn->fd, (void *)buffer, _SEND_FILE_STEP_);
S
TD-4088  
Shengliang Guan 已提交
674 675 676
    if (rlen <= 0) {
      return writeLen;
    } else if (rlen < _SEND_FILE_STEP_) {
wafwerar's avatar
wafwerar 已提交
677
      write(pFileOut->fd, (void *)buffer, (uint32_t)rlen);
S
TD-4088  
Shengliang Guan 已提交
678 679
      return (int64_t)(writeLen + rlen);
    } else {
wafwerar's avatar
wafwerar 已提交
680
      write(pFileOut->fd, (void *)buffer, _SEND_FILE_STEP_);
S
TD-4088  
Shengliang Guan 已提交
681 682 683 684
      writeLen += _SEND_FILE_STEP_;
    }
  }

wafwerar's avatar
wafwerar 已提交
685
  int64_t remain = size - writeLen;
S
TD-4088  
Shengliang Guan 已提交
686
  if (remain > 0) {
wafwerar's avatar
wafwerar 已提交
687
    size_t rlen = _read(pFileIn->fd, (void *)buffer, (size_t)remain);
S
TD-4088  
Shengliang Guan 已提交
688 689 690
    if (rlen <= 0) {
      return writeLen;
    } else {
wafwerar's avatar
wafwerar 已提交
691
      write(pFileOut->fd, (void *)buffer, (uint32_t)remain);
S
TD-4088  
Shengliang Guan 已提交
692 693 694 695 696 697
      writeLen += remain;
    }
  }
  return writeLen;

#elif defined(_TD_DARWIN_64)
S
TD-1912  
Shengliang Guan 已提交
698

wafwerar's avatar
wafwerar 已提交
699 700 701 702 703 704 705 706 707 708 709 710 711 712
  lseek(pFileIn->fd, (int32_t)(*offset), 0);
  int64_t writeLen = 0;
  uint8_t buffer[_SEND_FILE_STEP_] = {0};

  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
    size_t rlen = read(pFileIn->fd, (void *)buffer, _SEND_FILE_STEP_);
    if (rlen <= 0) {
      return writeLen;
    } else if (rlen < _SEND_FILE_STEP_) {
      write(pFileOut->fd, (void *)buffer, (uint32_t)rlen);
      return (int64_t)(writeLen + rlen);
    } else {
      write(pFileOut->fd, (void *)buffer, _SEND_FILE_STEP_);
      writeLen += _SEND_FILE_STEP_;
S
TD-4088  
Shengliang Guan 已提交
713
    }
wafwerar's avatar
wafwerar 已提交
714 715 716 717 718 719 720 721 722 723
  }

  int64_t remain = size - writeLen;
  if (remain > 0) {
    size_t rlen = read(pFileIn->fd, (void *)buffer, (size_t)remain);
    if (rlen <= 0) {
      return writeLen;
    } else {
      write(pFileOut->fd, (void *)buffer, (uint32_t)remain);
      writeLen += remain;
S
TD-4088  
Shengliang Guan 已提交
724 725
    }
  }
wafwerar's avatar
wafwerar 已提交
726
  return writeLen;
S
TD-4088  
Shengliang Guan 已提交
727 728 729

#else

S
TD-1912  
Shengliang Guan 已提交
730 731
  int64_t leftbytes = size;
  int64_t sentbytes;
S
Shengliang Guan 已提交
732 733

  while (leftbytes > 0) {
H
Hongze Cheng 已提交
734 735 736
#ifdef _TD_ARM_32
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, (long int *)offset, leftbytes);
#else
737
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, offset, leftbytes);
H
Hongze Cheng 已提交
738
#endif
S
Shengliang Guan 已提交
739
    if (sentbytes == -1) {
S
TD-1985  
Shengliang Guan 已提交
740
      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
S
Shengliang Guan 已提交
741 742 743 744 745
        continue;
      } else {
        return -1;
      }
    } else if (sentbytes == 0) {
S
TD-1912  
Shengliang Guan 已提交
746
      return (int64_t)(size - leftbytes);
S
Shengliang Guan 已提交
747 748 749 750 751 752
    }

    leftbytes -= sentbytes;
  }

  return size;
S
Shengliang Guan 已提交
753
#endif
wafwerar's avatar
wafwerar 已提交
754
}
S
Shengliang Guan 已提交
755

756
void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
757 758 759 760 761
  if (pFile == NULL) {
    return;
  }
  assert(pFile->fp != NULL);

762
  va_list ap;
763
  va_start(ap, format);
764
  vfprintf(pFile->fp, format, ap);
765
  va_end(ap);
S
Shengliang Guan 已提交
766 767
}

768
bool taosValidFile(TdFilePtr pFile) { return pFile != NULL && pFile->fd > 0; }
S
Shengliang Guan 已提交
769

770
int32_t taosUmaskFile(int32_t maskVal) {
wafwerar's avatar
wafwerar 已提交
771
#ifdef WINDOWS
S
Shengliang Guan 已提交
772 773
  return 0;
#else
774
  return umask(maskVal);
S
TD-4088  
Shengliang Guan 已提交
775
#endif
776 777
}

778
int32_t taosGetErrorFile(TdFilePtr pFile) { return errno; }
wafwerar's avatar
wafwerar 已提交
779
int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict ptrBuf) {
L
Liu Jicong 已提交
780
  if (pFile == NULL || ptrBuf == NULL) {
781 782
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
783 784 785
  if (*ptrBuf != NULL) {
    taosMemoryFreeClear(*ptrBuf);
  }
786
  assert(pFile->fp != NULL);
wafwerar's avatar
wafwerar 已提交
787 788 789 790 791 792 793 794 795 796
#ifdef WINDOWS
  *ptrBuf = taosMemoryMalloc(1024);
  if (*ptrBuf == NULL) return -1;
  if (fgets(*ptrBuf, 1023, pFile->fp) == NULL) {
    taosMemoryFreeClear(*ptrBuf);
    return -1;
  }
  (*ptrBuf)[1023] = 0;
  return strlen(*ptrBuf);
#else
797 798
  size_t len = 0;
  return getline(ptrBuf, &len, pFile->fp);
wafwerar's avatar
wafwerar 已提交
799
#endif
800
}
H
Haojun Liao 已提交
801

wafwerar's avatar
wafwerar 已提交
802
int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf) {
L
Liu Jicong 已提交
803
  if (pFile == NULL || buf == NULL) {
wafwerar's avatar
wafwerar 已提交
804 805 806 807 808 809 810 811
    return -1;
  }
  assert(pFile->fp != NULL);
  if (fgets(buf, maxSize, pFile->fp) == NULL) {
    return -1;
  }
  return strlen(buf);
}
H
Haojun Liao 已提交
812

L
Liu Jicong 已提交
813
int32_t taosEOFFile(TdFilePtr pFile) {
814 815 816 817 818
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fp != NULL);

L
Liu Jicong 已提交
819
  return feof(pFile->fp);
L
fix  
Liu Jicong 已提交
820
}
821

822 823 824 825 826 827 828 829 830 831 832 833 834 835
bool taosCheckAccessFile(const char *pathname, int32_t tdFileAccessOptions) {
  int flags = 0;

  if (tdFileAccessOptions & TD_FILE_ACCESS_EXIST_OK) {
    flags |= F_OK;
  }

  if (tdFileAccessOptions & TD_FILE_ACCESS_READ_OK) {
    flags |= R_OK;
  }

  if (tdFileAccessOptions & TD_FILE_ACCESS_WRITE_OK) {
    flags |= W_OK;
  }
wafwerar's avatar
wafwerar 已提交
836 837 838
#ifdef WINDOWS
  return _access(pathname, flags) == 0;
#else
839
  return access(pathname, flags) == 0;
wafwerar's avatar
wafwerar 已提交
840
#endif
841
}
842 843

bool taosCheckExistFile(const char *pathname) { return taosCheckAccessFile(pathname, TD_FILE_ACCESS_EXIST_OK); };