osFile.c 18.5 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

S
Shengliang Guan 已提交
19
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
#include <io.h>

#if defined(_MSDOS)
#define open _open
#endif

#if defined(_WIN32)
extern int openA(const char *, int, ...); /* MsvcLibX ANSI version of open */
extern int openU(const char *, int, ...); /* MsvcLibX UTF-8 version of open */
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
#define open openU
#else /* _ANSI_SOURCE */
#define open openA
#endif /* defined(_UTF8_SOURCE) */
#endif /* defined(_WIN32) */
35

36
#else
37 38
#include <fcntl.h>
#include <sys/file.h>
39 40 41 42

#if !defined(_TD_DARWIN_64)
    #include <sys/sendfile.h>
#endif
43 44 45 46
#include <sys/stat.h>
#include <unistd.h>
#define LINUX_FILE_NO_TEXT_OPTION 0
#define O_TEXT                    LINUX_FILE_NO_TEXT_OPTION
47 48
#endif

49 50
#define FILE_WITH_LOCK 1

51
void taosGetTmpfilePath(const char *inputTmpDir, const char *fileNamePrefix, char *dstPath) {
S
TD-4088  
Shengliang Guan 已提交
52
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
S
Shengliang Guan 已提交
53
  const char *tdengineTmpFileNamePrefix = "tdengine-";
S
TD-4088  
Shengliang Guan 已提交
54
  char        tmpPath[PATH_MAX];
S
Shengliang Guan 已提交
55

S
Shengliang Guan 已提交
56 57
  int32_t len = (int32_t)strlen(inputTmpDir);
  memcpy(tmpPath, inputTmpDir, len);
S
TD-4088  
Shengliang Guan 已提交
58 59 60

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

63
  strcpy(tmpPath + len, tdengineTmpFileNamePrefix);
S
TD-4088  
Shengliang Guan 已提交
64
  strcat(tmpPath, tdengineTmpFileNamePrefix);
S
Shengliang Guan 已提交
65 66 67
  if (strlen(tmpPath) + strlen(fileNamePrefix) + strlen("-%d-%s") < PATH_MAX) {
    strcat(tmpPath, fileNamePrefix);
    strcat(tmpPath, "-%d-%s");
S
Shengliang Guan 已提交
68
  }
S
Shengliang Guan 已提交
69

S
TD-4088  
Shengliang Guan 已提交
70 71
  char rand[8] = {0};
  taosRandStr(rand, tListLen(rand) - 1);
S
Shengliang Guan 已提交
72
  snprintf(dstPath, PATH_MAX, tmpPath, getpid(), rand);
S
TD-1912  
Shengliang Guan 已提交
73

S
TD-4088  
Shengliang Guan 已提交
74
#else
S
Shengliang Guan 已提交
75

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

78
  char    tmpPath[PATH_MAX];
S
Shengliang Guan 已提交
79 80
  int32_t len = strlen(inputTmpDir);
  memcpy(tmpPath, inputTmpDir, len);
S
TD-4088  
Shengliang Guan 已提交
81
  static uint64_t seqId = 0;
S
Shengliang Guan 已提交
82

S
TD-4088  
Shengliang Guan 已提交
83 84
  if (tmpPath[len - 1] != '/') {
    tmpPath[len++] = '/';
S
TD-1912  
Shengliang Guan 已提交
85
  }
S
Shengliang Guan 已提交
86

S
TD-4088  
Shengliang Guan 已提交
87 88 89 90
  strcpy(tmpPath + len, tdengineTmpFileNamePrefix);
  if (strlen(tmpPath) + strlen(fileNamePrefix) + strlen("-%d-%s") < PATH_MAX) {
    strcat(tmpPath, fileNamePrefix);
    strcat(tmpPath, "-%d-%s");
S
Shengliang Guan 已提交
91 92
  }

S
TD-4088  
Shengliang Guan 已提交
93 94 95
  char rand[32] = {0};

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

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

S
TD-4088  
Shengliang Guan 已提交
99
#endif
S
Shengliang Guan 已提交
100
}
S
TD-4088  
Shengliang Guan 已提交
101

102 103 104 105 106 107 108 109 110
int64_t taosCopyFile(const char *from, const char *to) {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return 0;
#else
  char    buffer[4096];
  int64_t size = 0;
  int64_t bytes;

  // fidfrom = open(from, O_RDONLY);
111
  TdFilePtr pFileFrom = taosOpenFile(from, TD_FILE_READ);
112 113 114
  if (pFileFrom == NULL) goto _err;

  // fidto = open(to, O_WRONLY | O_CREAT | O_EXCL, 0755);
115
  TdFilePtr pFileTo = taosOpenFile(to, TD_FILE_CTEATE | TD_FILE_WRITE | TD_FILE_EXCL);
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
  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);
138
  taosRemoveFile(to);
139 140 141 142
  return -1;
#endif
}

143 144
int32_t taosRemoveFile(const char *path) { return remove(path); }

145 146 147 148
int32_t taosRenameFile(const char *oldName, const char *newName) {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  int32_t code = MoveFileEx(oldName, newName, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
  if (code < 0) {
149
    // printf("failed to rename file %s to %s, reason:%s", oldName, newName, strerror(errno));
150 151 152 153 154 155
  }

  return code;
#else
  int32_t code = rename(oldName, newName);
  if (code < 0) {
156
    // printf("failed to rename file %s to %s, reason:%s", oldName, newName, strerror(errno));
157 158 159 160 161 162 163 164 165 166 167
  }

  return code;
#endif
}

int32_t taosStatFile(const char *path, int64_t *size, int32_t *mtime) {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return 0;
#else
  struct stat fileStat;
168
  int32_t code = stat(path, &fileStat);
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
  if (code < 0) {
    return code;
  }

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

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

  return 0;
#endif
}
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
int32_t taosDevInoFile(const char *path, int64_t *stDev, int64_t *stIno) {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return 0;
#else
  struct stat fileStat;
  int32_t code = stat(path, &fileStat);
  if (code < 0) {
    return code;
  }

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

  if (stIno != NULL) {
    *stIno = fileStat.st_ino;
  }

  return 0;
#endif
}
205

206
void autoDelFileListAdd(const char *path) { return; }
207

208
TdFilePtr taosOpenFile(const char *path, int32_t tdFileOptions) {
209 210 211
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return NULL;
#else
212 213 214 215 216 217
  int fd = -1;
  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 已提交
218
    } else if (tdFileOptions & TD_FILE_TRUNC) {
219
      mode = (tdFileOptions & TD_FILE_TEXT) ? "wt+" : "wb+";
L
Liu Jicong 已提交
220
    } else if ((tdFileOptions & TD_FILE_READ) && !(tdFileOptions & TD_FILE_WRITE)) {
221
      mode = (tdFileOptions & TD_FILE_TEXT) ? "rt" : "rb";
L
Liu Jicong 已提交
222
    } else {
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
      mode = (tdFileOptions & TD_FILE_TEXT) ? "rt+" : "rb+";
    }
    assert(!(tdFileOptions & TD_FILE_EXCL));
    fp = fopen(path, mode);
    if (fp == NULL) {
      return NULL;
    }
  } else {
    int access = O_BINARY;
    access |= (tdFileOptions & TD_FILE_CTEATE) ? O_CREAT : 0;
    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;
    fd = open(path, access, S_IRWXU | S_IRWXG | S_IRWXO);
    if (fd == -1) {
      return NULL;
    }
  }

250
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
251 252
    autoDelFileListAdd(path);
  }
253

254 255
  TdFilePtr pFile = (TdFilePtr)malloc(sizeof(TdFile));
  if (pFile == NULL) {
256 257
    if (fd >= 0) close(fd);
    if (fp != NULL) fclose(fp);
258 259
    return NULL;
  }
260
#if FILE_WITH_LOCK
C
Cary Xu 已提交
261
  pthread_rwlock_init(&(pFile->rwlock), NULL);
262
#endif
263 264 265 266 267 268 269 270 271 272 273
  pFile->fd = fd;
  pFile->fp = fp;
  pFile->refId = 0;
  return pFile;
#endif
}

int64_t taosCloseFile(TdFilePtr *ppFile) {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return 0;
#else
274 275 276 277 278 279
  if (ppFile == NULL || *ppFile == NULL) {
    return 0;
  }
#if FILE_WITH_LOCK
  pthread_rwlock_wrlock(&((*ppFile)->rwlock));
#endif
280
  if (ppFile == NULL || *ppFile == NULL || (*ppFile)->fd == -1) {
281 282
    return 0;
  }
283 284 285 286 287 288 289 290 291 292
  if ((*ppFile)->fp != NULL) {
    fflush((*ppFile)->fp);
    fclose((*ppFile)->fp);
    (*ppFile)->fp = NULL;
  }
  if ((*ppFile)->fd >= 0) {
    fsync((*ppFile)->fd);
    close((*ppFile)->fd);
    (*ppFile)->fd = -1;
  }
293
  (*ppFile)->refId = 0;
294 295 296 297
#if FILE_WITH_LOCK
  pthread_rwlock_unlock(&((*ppFile)->rwlock));
  pthread_rwlock_destroy(&((*ppFile)->rwlock));
#endif
298 299 300 301 302 303 304
  free(*ppFile);
  *ppFile = NULL;
  return 0;
#endif
}

int64_t taosReadFile(TdFilePtr pFile, void *buf, int64_t count) {
305
  if (pFile == NULL) {
306 307
    return 0;
  }
308 309 310
#if FILE_WITH_LOCK
  pthread_rwlock_rdlock(&(pFile->rwlock));
#endif
311
  assert(pFile->fd >= 0);
S
TD-1912  
Shengliang Guan 已提交
312 313
  int64_t leftbytes = count;
  int64_t readbytes;
314
  char   *tbuf = (char *)buf;
S
Shengliang Guan 已提交
315 316

  while (leftbytes > 0) {
317
    readbytes = read(pFile->fd, (void *)tbuf, (uint32_t)leftbytes);
S
Shengliang Guan 已提交
318 319 320 321
    if (readbytes < 0) {
      if (errno == EINTR) {
        continue;
      } else {
322 323 324
#if FILE_WITH_LOCK
        pthread_rwlock_unlock(&(pFile->rwlock));
#endif
S
Shengliang Guan 已提交
325 326 327
        return -1;
      }
    } else if (readbytes == 0) {
328 329 330
#if FILE_WITH_LOCK
      pthread_rwlock_unlock(&(pFile->rwlock));
#endif
S
TD-1912  
Shengliang Guan 已提交
331
      return (int64_t)(count - leftbytes);
S
Shengliang Guan 已提交
332 333 334 335 336 337
    }

    leftbytes -= readbytes;
    tbuf += readbytes;
  }

338 339 340
#if FILE_WITH_LOCK
  pthread_rwlock_unlock(&(pFile->rwlock));
#endif
S
TD-1912  
Shengliang Guan 已提交
341
  return count;
S
Shengliang Guan 已提交
342 343
}

344
int64_t taosPReadFile(TdFilePtr pFile, void *buf, int64_t count, int64_t offset) {
345
  if (pFile == NULL) {
346 347
    return 0;
  }
348 349 350
#if FILE_WITH_LOCK
  pthread_rwlock_rdlock(&(pFile->rwlock));
#endif
351
  assert(pFile->fd >= 0);
352 353 354 355 356
  int64_t ret = pread(pFile->fd, buf, count, offset);
#if FILE_WITH_LOCK
  pthread_rwlock_unlock(&(pFile->rwlock));
#endif
  return ret;
357 358 359
}

int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
360 361 362
  if (pFile == NULL) {
    return 0;
  }
363 364 365
#if FILE_WITH_LOCK
  pthread_rwlock_wrlock(&(pFile->rwlock));
#endif
366 367
  assert(pFile->fd >= 0);

368
  int64_t nleft = count;
S
TD-1912  
Shengliang Guan 已提交
369
  int64_t nwritten = 0;
370
  char   *tbuf = (char *)buf;
S
Shengliang Guan 已提交
371 372

  while (nleft > 0) {
373
    nwritten = write(pFile->fd, (void *)tbuf, (uint32_t)nleft);
S
Shengliang Guan 已提交
374 375 376 377
    if (nwritten < 0) {
      if (errno == EINTR) {
        continue;
      }
378 379 380
#if FILE_WITH_LOCK
      pthread_rwlock_unlock(&(pFile->rwlock));
#endif
S
Shengliang Guan 已提交
381 382 383 384 385
      return -1;
    }
    nleft -= nwritten;
    tbuf += nwritten;
  }
386

387 388 389
#if FILE_WITH_LOCK
  pthread_rwlock_unlock(&(pFile->rwlock));
#endif
390
  return count;
S
Shengliang Guan 已提交
391 392
}

393
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
394 395 396
  if (pFile == NULL) {
    return 0;
  }
397 398 399
#if FILE_WITH_LOCK
  pthread_rwlock_rdlock(&(pFile->rwlock));
#endif
400
  assert(pFile->fd >= 0);
401 402 403 404 405
  int64_t ret = lseek(pFile->fd, (long)offset, whence);
#if FILE_WITH_LOCK
  pthread_rwlock_unlock(&(pFile->rwlock));
#endif
  return ret;
406
}
S
Shengliang Guan 已提交
407

408
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) {
S
Shengliang Guan 已提交
409 410 411
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return 0;
#else
412 413 414 415 416
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fd >= 0);

417
  struct stat fileStat;
418
  int32_t code = fstat(pFile->fd, &fileStat);
419 420 421
  if (code < 0) {
    return code;
  }
H
Hongze Cheng 已提交
422

423 424 425
  if (size != NULL) {
    *size = fileStat.st_size;
  }
H
Hongze Cheng 已提交
426

427 428 429
  if (mtime != NULL) {
    *mtime = fileStat.st_mtime;
  }
H
Hongze Cheng 已提交
430

431 432 433
  return 0;
#endif
}
H
Hongze Cheng 已提交
434

435 436 437 438
int32_t taosLockFile(TdFilePtr pFile) {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return 0;
#else
439 440 441 442 443
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fd >= 0);

444 445 446
  return (int32_t)flock(pFile->fd, LOCK_EX | LOCK_NB);
#endif
}
H
Hongze Cheng 已提交
447

448 449 450 451
int32_t taosUnLockFile(TdFilePtr pFile) {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return 0;
#else
452 453 454 455 456
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fd >= 0);

457 458 459 460 461 462 463 464 465 466
  return (int32_t)flock(pFile->fd, LOCK_UN | LOCK_NB);
#endif
}

int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  if (pFile->fd < 0) {
    errno = EBADF;
    uError("%s\n", "fd arg was negative");
    return -1;
H
Hongze Cheng 已提交
467 468
  }

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

471 472 473 474 475 476 477
  LARGE_INTEGER li_0;
  li_0.QuadPart = (int64_t)0;
  BOOL cur = SetFilePointerEx(h, li_0, NULL, FILE_CURRENT);
  if (!cur) {
    uError("SetFilePointerEx Error getting current position in file.\n");
    return -1;
  }
H
Hongze Cheng 已提交
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
  LARGE_INTEGER li_size;
  li_size.QuadPart = l_size;
  BOOL cur2 = SetFilePointerEx(h, li_size, NULL, FILE_BEGIN);
  if (cur2 == 0) {
    int error = GetLastError();
    uError("SetFilePointerEx GetLastError is: %d\n", error);
    switch (error) {
      case ERROR_INVALID_HANDLE:
        errno = EBADF;
        break;
      default:
        errno = EIO;
        break;
    }
    return -1;
  }

  if (!SetEndOfFile(h)) {
    int error = GetLastError();
    uError("SetEndOfFile GetLastError is:%d", error);
    switch (error) {
      case ERROR_INVALID_HANDLE:
        errno = EBADF;
        break;
      default:
        errno = EIO;
        break;
    }
    return -1;
  }

  return 0;
#else
512 513 514 515 516
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fd >= 0);

517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
  return ftruncate(pFile->fd, l_size);
#endif
}

int32_t taosFsyncFile(TdFilePtr pFile) {
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  if (pFile->fd < 0) {
    errno = EBADF;
    uError("%s\n", "fd arg was negative");
    return -1;
  }

  HANDLE h = (HANDLE)_get_osfhandle(pFile->fd);

  return FlushFileBuffers(h);
#else
533 534 535 536 537
  if (pFile == NULL) {
    return 0;
  }

  if (pFile->fp != NULL) return fflush(pFile->fp);
538
  if (pFile->fd >= 0) return fsync(pFile->fd);
539 540

  return 0;
S
Shengliang Guan 已提交
541
#endif
H
Hongze Cheng 已提交
542 543
}

S
TD-4088  
Shengliang Guan 已提交
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
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)

#define _SEND_FILE_STEP_ 1000

int64_t taosFSendFile(FILE *out_file, FILE *in_file, int64_t *offset, int64_t count) {
  fseek(in_file, (int32_t)(*offset), 0);
  int64_t writeLen = 0;
  uint8_t buffer[_SEND_FILE_STEP_] = {0};

  for (int64_t len = 0; len < (count - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
    size_t rlen = fread(buffer, 1, _SEND_FILE_STEP_, in_file);
    if (rlen <= 0) {
      return writeLen;
    } else if (rlen < _SEND_FILE_STEP_) {
      fwrite(buffer, 1, rlen, out_file);
      return (int64_t)(writeLen + rlen);
    } else {
      fwrite(buffer, 1, _SEND_FILE_STEP_, in_file);
      writeLen += _SEND_FILE_STEP_;
    }
  }

  int64_t remain = count - writeLen;
  if (remain > 0) {
    size_t rlen = fread(buffer, 1, (size_t)remain, in_file);
    if (rlen <= 0) {
      return writeLen;
    } else {
      fwrite(buffer, 1, (size_t)remain, out_file);
      writeLen += remain;
    }
  }

  return writeLen;
}

int64_t taosSendFile(SocketFd dfd, FileFd sfd, int64_t *offset, int64_t count) {
  if (offset != NULL) lseek(sfd, (int32_t)(*offset), 0);

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

  for (int64_t len = 0; len < (count - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
    int32_t rlen = (int32_t)read(sfd, buffer, _SEND_FILE_STEP_);
    if (rlen <= 0) {
      return writeLen;
    } else if (rlen < _SEND_FILE_STEP_) {
      taosWriteSocket(dfd, buffer, rlen);
      return (int64_t)(writeLen + rlen);
    } else {
      taosWriteSocket(dfd, buffer, _SEND_FILE_STEP_);
      writeLen += _SEND_FILE_STEP_;
    }
  }

  int64_t remain = count - writeLen;
  if (remain > 0) {
    int32_t rlen = read(sfd, buffer, (int32_t)remain);
    if (rlen <= 0) {
      return writeLen;
    } else {
      taosWriteSocket(sfd, buffer, (int32_t)remain);
      writeLen += remain;
    }
  }

  return writeLen;
}

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

S
TD-4088  
Shengliang Guan 已提交
615 616 617 618 619 620 621 622
int64_t taosFSendFile(FILE *out_file, FILE *in_file, int64_t *offset, int64_t count) {
  int r = 0;
  if (offset) {
    r = fseek(in_file, *offset, SEEK_SET);
    if (r == -1) return -1;
  }
  off_t len = count;
  while (len > 0) {
623
    char buf[1024 * 16];
S
TD-4088  
Shengliang Guan 已提交
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
    off_t n = sizeof(buf);
    if (len < n) n = len;
    size_t m = fread(buf, 1, n, in_file);
    if (m < n) {
      int e = ferror(in_file);
      if (e) return -1;
    }
    if (m == 0) break;
    if (m != fwrite(buf, 1, m, out_file)) {
      return -1;
    }
    len -= m;
  }
  return count - len;
}

int64_t taosSendFile(SocketFd dfd, FileFd sfd, int64_t *offset, int64_t count) {
  int r = 0;
  if (offset) {
    r = lseek(sfd, *offset, SEEK_SET);
    if (r == -1) return -1;
  }
  off_t len = count;
  while (len > 0) {
648
    char buf[1024 * 16];
S
TD-4088  
Shengliang Guan 已提交
649 650 651 652 653 654 655 656 657 658 659 660 661 662
    off_t n = sizeof(buf);
    if (len < n) n = len;
    size_t m = read(sfd, buf, n);
    if (m == -1) return -1;
    if (m == 0) break;
    size_t l = write(dfd, buf, m);
    if (l == -1) return -1;
    len -= l;
  }
  return count - len;
}

#else

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
// int64_t taosSendFile(int fdDst, TdFilePtr pFileSrc, int64_t *offset, int64_t size) {
//   if (pFileSrc == NULL) {
//     return 0;
//   }
//   assert(pFileSrc->fd >= 0);

//   int64_t leftbytes = size;
//   int64_t sentbytes;

//   while (leftbytes > 0) {
//     sentbytes = sendfile(fdDst, pFileSrc->fd, offset, leftbytes);
//     if (sentbytes == -1) {
//       if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
//         continue;
//       } else {
//         return -1;
//       }
//     } else if (sentbytes == 0) {
//       return (int64_t)(size - leftbytes);
//     }

//     leftbytes -= sentbytes;
//   }

//   return size;
// }

int64_t taosFSendFile(TdFilePtr pFileOut, TdFilePtr pFileIn, int64_t *offset, int64_t size) {
  if (pFileOut == NULL || pFileIn == NULL) {
692 693
    return 0;
  }
694
  assert(pFileIn->fd >= 0 && pFileOut->fd >= 0);
S
TD-1912  
Shengliang Guan 已提交
695 696
  int64_t leftbytes = size;
  int64_t sentbytes;
S
Shengliang Guan 已提交
697 698

  while (leftbytes > 0) {
699
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, offset, leftbytes);
S
Shengliang Guan 已提交
700
    if (sentbytes == -1) {
S
TD-1985  
Shengliang Guan 已提交
701
      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
S
Shengliang Guan 已提交
702 703 704 705 706
        continue;
      } else {
        return -1;
      }
    } else if (sentbytes == 0) {
S
TD-1912  
Shengliang Guan 已提交
707
      return (int64_t)(size - leftbytes);
S
Shengliang Guan 已提交
708 709 710 711 712 713 714
    }

    leftbytes -= sentbytes;
  }

  return size;
}
S
TD-1912  
Shengliang Guan 已提交
715

S
Shengliang Guan 已提交
716 717
#endif

718
void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
719 720 721 722 723
  if (pFile == NULL) {
    return;
  }
  assert(pFile->fp != NULL);

724
  va_list ap;
725
  va_start(ap, format);
726
  vfprintf(pFile->fp, format, ap);
727 728
  va_end(ap);
  fflush(pFile->fp);
S
Shengliang Guan 已提交
729 730
}

731
#if !defined(WINDOWS)
732
void *taosMmapReadOnlyFile(TdFilePtr pFile, int64_t length) {
733 734 735 736
  if (pFile == NULL) {
    return NULL;
  }
  assert(pFile->fd >= 0);
S
Shengliang Guan 已提交
737

738 739
  void *ptr = mmap(NULL, length, PROT_READ, MAP_SHARED, pFile->fd, 0);
  return ptr;
S
Shengliang Guan 已提交
740
}
741
#endif
S
Shengliang Guan 已提交
742

743
bool taosValidFile(TdFilePtr pFile) { return pFile != NULL; }
S
Shengliang Guan 已提交
744

745
int32_t taosUmaskFile(int32_t maskVal) {
S
Shengliang Guan 已提交
746 747 748
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
  return 0;
#else
749
  return umask(maskVal);
S
TD-4088  
Shengliang Guan 已提交
750
#endif
751 752
}

753 754
int32_t taosGetErrorFile(TdFilePtr pFile) { return errno; }
int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict__ ptrBuf) {
755 756 757 758 759
  if (pFile == NULL) {
    return -1;
  }
  assert(pFile->fp != NULL);

760 761
  size_t len = 0;
  return getline(ptrBuf, &len, pFile->fp);
762
}
L
Liu Jicong 已提交
763
int32_t taosEOFFile(TdFilePtr pFile) {
764 765 766 767 768
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fp != NULL);

L
Liu Jicong 已提交
769
  return feof(pFile->fp);
L
fix  
Liu Jicong 已提交
770
}
771 772 773

#if !defined(WINDOWS)

774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
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;
  }

  return access(pathname, flags) == 0;
}
791 792 793 794

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

#endif // WINDOWS