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

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

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
  }

194
  return !code;
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 208
  struct _stati64 fileStat;
  int32_t code = _stati64(path, &fileStat);
209
#else
wafwerar's avatar
wafwerar 已提交
210
  struct stat fileStat;
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) {
wafwerar's avatar
wafwerar 已提交
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) {
wafwerar's avatar
wafwerar 已提交
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) {
346 347
    if (fd >= 0) close(fd);
    if (fp != NULL) fclose(fp);
348 349
    return NULL;
  }
350
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
351
  taosThreadRwlockInit(&(pFile->rwlock), NULL);
352
#endif
353 354 355
  pFile->fd = fd;
  pFile->fp = fp;
  pFile->refId = 0;
wafwerar's avatar
wafwerar 已提交
356
  if (tdFileOptions & TD_FILE_AUTO_DEL) {
wafwerar's avatar
wafwerar 已提交
357
    autoDelFileListAdd(path);
wafwerar's avatar
wafwerar 已提交
358
  }
359 360 361
  return pFile;
}

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

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

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

    leftbytes -= readbytes;
    tbuf += readbytes;
  }

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

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

int64_t taosWriteFile(TdFilePtr pFile, const void *buf, int64_t count) {
wafwerar's avatar
wafwerar 已提交
460 461 462
  if (pFile == NULL) {
    return 0;
  }
463
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
464
  taosThreadRwlockWrlock(&(pFile->rwlock));
465
#endif
L
Liu Jicong 已提交
466
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
467

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

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

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

493
int64_t taosLSeekFile(TdFilePtr pFile, int64_t offset, int32_t whence) {
494
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
495
  taosThreadRwlockRdlock(&(pFile->rwlock));
496
#endif
L
Liu Jicong 已提交
497
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
wafwerar's avatar
wafwerar 已提交
498
#ifdef WINDOWS
wafwerar's avatar
wafwerar 已提交
499
  int64_t ret = _lseeki64(pFile->fd, offset, whence);
wafwerar's avatar
wafwerar 已提交
500
#else
L
Liu Jicong 已提交
501
  int64_t ret = lseek(pFile->fd, offset, whence);
wafwerar's avatar
wafwerar 已提交
502
#endif
503
#if FILE_WITH_LOCK
wafwerar's avatar
wafwerar 已提交
504
  taosThreadRwlockUnlock(&(pFile->rwlock));
505 506
#endif
  return ret;
507
}
S
Shengliang Guan 已提交
508

509
int32_t taosFStatFile(TdFilePtr pFile, int64_t *size, int32_t *mtime) {
510 511 512
  if (pFile == NULL) {
    return 0;
  }
L
Liu Jicong 已提交
513
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
514

515
  struct stat fileStat;
516
#ifdef WINDOWS
517
  int32_t code = _fstat(pFile->fd, &fileStat);
518
#else
519
  int32_t code = fstat(pFile->fd, &fileStat);
520
#endif
521 522 523
  if (code < 0) {
    return code;
  }
H
Hongze Cheng 已提交
524

525 526 527
  if (size != NULL) {
    *size = fileStat.st_size;
  }
H
Hongze Cheng 已提交
528

529 530 531
  if (mtime != NULL) {
    *mtime = fileStat.st_mtime;
  }
H
Hongze Cheng 已提交
532

533 534
  return 0;
}
H
Hongze Cheng 已提交
535

536
int32_t taosLockFile(TdFilePtr pFile) {
wafwerar's avatar
wafwerar 已提交
537
#ifdef WINDOWS
538 539
  return 0;
#else
L
Liu Jicong 已提交
540
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
541

542 543 544
  return (int32_t)flock(pFile->fd, LOCK_EX | LOCK_NB);
#endif
}
H
Hongze Cheng 已提交
545

546
int32_t taosUnLockFile(TdFilePtr pFile) {
wafwerar's avatar
wafwerar 已提交
547
#ifdef WINDOWS
548 549
  return 0;
#else
L
Liu Jicong 已提交
550
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
551

552 553 554 555 556
  return (int32_t)flock(pFile->fd, LOCK_UN | LOCK_NB);
#endif
}

int32_t taosFtruncateFile(TdFilePtr pFile, int64_t l_size) {
wafwerar's avatar
wafwerar 已提交
557
#ifdef WINDOWS
558 559
  if (pFile->fd < 0) {
    errno = EBADF;
560
    printf("Ftruncate file error, fd arg was negative\n");
561
    return -1;
H
Hongze Cheng 已提交
562 563
  }

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

566 567 568 569
  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 已提交
570
    printf("SetFilePointerEx Error getting current position in file.\n");
571 572
    return -1;
  }
H
Hongze Cheng 已提交
573

574 575 576 577 578
  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 已提交
579
    printf("SetFilePointerEx GetLastError is: %d\n", error);
580 581 582 583 584 585 586 587 588 589 590 591 592
    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 已提交
593
    printf("SetEndOfFile GetLastError is:%d", error);
594 595 596 597 598 599 600 601 602 603 604 605 606
    switch (error) {
      case ERROR_INVALID_HANDLE:
        errno = EBADF;
        break;
      default:
        errno = EIO;
        break;
    }
    return -1;
  }

  return 0;
#else
607 608 609
  if (pFile == NULL) {
    return 0;
  }
L
Liu Jicong 已提交
610
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
611

612 613 614 615 616
  return ftruncate(pFile->fd, l_size);
#endif
}

int32_t taosFsyncFile(TdFilePtr pFile) {
617 618 619 620
  if (pFile == NULL) {
    return 0;
  }

L
Liu Jicong 已提交
621 622
  // this implementation is WRONG
  // fflush is not a replacement of fsync
623
  if (pFile->fp != NULL) return fflush(pFile->fp);
624
  if (pFile->fd >= 0) {
625
#ifdef WINDOWS
626 627
    HANDLE h = (HANDLE)_get_osfhandle(pFile->fd);
    return !FlushFileBuffers(h);
628
#else
629
    return fsync(pFile->fd);
630
#endif
631
  }
632
  return 0;
H
Hongze Cheng 已提交
633 634
}

wafwerar's avatar
wafwerar 已提交
635 636 637
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 已提交
638
  }
wafwerar's avatar
wafwerar 已提交
639
  assert(pFileIn->fd >= 0 && pFileOut->fd >= 0);
S
TD-4088  
Shengliang Guan 已提交
640

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

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

wafwerar's avatar
wafwerar 已提交
647
  for (int64_t len = 0; len < (size - _SEND_FILE_STEP_); len += _SEND_FILE_STEP_) {
wafwerar's avatar
wafwerar 已提交
648
    size_t rlen = _read(pFileIn->fd, (void *)buffer, _SEND_FILE_STEP_);
S
TD-4088  
Shengliang Guan 已提交
649 650 651
    if (rlen <= 0) {
      return writeLen;
    } else if (rlen < _SEND_FILE_STEP_) {
wafwerar's avatar
wafwerar 已提交
652
      write(pFileOut->fd, (void *)buffer, (uint32_t)rlen);
S
TD-4088  
Shengliang Guan 已提交
653 654
      return (int64_t)(writeLen + rlen);
    } else {
wafwerar's avatar
wafwerar 已提交
655
      write(pFileOut->fd, (void *)buffer, _SEND_FILE_STEP_);
S
TD-4088  
Shengliang Guan 已提交
656 657 658 659
      writeLen += _SEND_FILE_STEP_;
    }
  }

wafwerar's avatar
wafwerar 已提交
660
  int64_t remain = size - writeLen;
S
TD-4088  
Shengliang Guan 已提交
661
  if (remain > 0) {
wafwerar's avatar
wafwerar 已提交
662
    size_t rlen = _read(pFileIn->fd, (void *)buffer, (size_t)remain);
S
TD-4088  
Shengliang Guan 已提交
663 664 665
    if (rlen <= 0) {
      return writeLen;
    } else {
wafwerar's avatar
wafwerar 已提交
666
      write(pFileOut->fd, (void *)buffer, (uint32_t)remain);
S
TD-4088  
Shengliang Guan 已提交
667 668 669 670 671 672
      writeLen += remain;
    }
  }
  return writeLen;

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

wafwerar's avatar
wafwerar 已提交
674 675 676 677 678 679 680 681 682 683 684 685 686 687
  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 已提交
688
    }
wafwerar's avatar
wafwerar 已提交
689 690 691 692 693 694 695 696 697 698
  }

  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 已提交
699 700
    }
  }
wafwerar's avatar
wafwerar 已提交
701
  return writeLen;
S
TD-4088  
Shengliang Guan 已提交
702 703 704

#else

S
TD-1912  
Shengliang Guan 已提交
705 706
  int64_t leftbytes = size;
  int64_t sentbytes;
S
Shengliang Guan 已提交
707 708

  while (leftbytes > 0) {
wafwerar's avatar
wafwerar 已提交
709 710 711
  #ifdef _TD_ARM_32
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, (long int*)offset, leftbytes);
  #else
712
    sentbytes = sendfile(pFileOut->fd, pFileIn->fd, offset, leftbytes);
wafwerar's avatar
wafwerar 已提交
713
  #endif
S
Shengliang Guan 已提交
714
    if (sentbytes == -1) {
S
TD-1985  
Shengliang Guan 已提交
715
      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
S
Shengliang Guan 已提交
716 717 718 719 720
        continue;
      } else {
        return -1;
      }
    } else if (sentbytes == 0) {
S
TD-1912  
Shengliang Guan 已提交
721
      return (int64_t)(size - leftbytes);
S
Shengliang Guan 已提交
722 723 724 725 726 727
    }

    leftbytes -= sentbytes;
  }

  return size;
S
Shengliang Guan 已提交
728
#endif
wafwerar's avatar
wafwerar 已提交
729
}
S
Shengliang Guan 已提交
730

731
void taosFprintfFile(TdFilePtr pFile, const char *format, ...) {
732 733 734 735 736
  if (pFile == NULL) {
    return;
  }
  assert(pFile->fp != NULL);

737
  va_list ap;
738
  va_start(ap, format);
739
  vfprintf(pFile->fp, format, ap);
740 741
  va_end(ap);
  fflush(pFile->fp);
S
Shengliang Guan 已提交
742 743
}

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

746
int32_t taosUmaskFile(int32_t maskVal) {
wafwerar's avatar
wafwerar 已提交
747
#ifdef WINDOWS
S
Shengliang Guan 已提交
748 749
  return 0;
#else
750
  return umask(maskVal);
S
TD-4088  
Shengliang Guan 已提交
751
#endif
752 753
}

754
int32_t taosGetErrorFile(TdFilePtr pFile) { return errno; }
wafwerar's avatar
wafwerar 已提交
755
int64_t taosGetLineFile(TdFilePtr pFile, char **__restrict ptrBuf) {
L
Liu Jicong 已提交
756
  if (pFile == NULL || ptrBuf == NULL) {
757 758
    return -1;
  }
wafwerar's avatar
wafwerar 已提交
759 760 761
  if (*ptrBuf != NULL) {
    taosMemoryFreeClear(*ptrBuf);
  }
762
  assert(pFile->fp != NULL);
wafwerar's avatar
wafwerar 已提交
763 764 765 766 767 768 769 770 771 772
#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
773 774
  size_t len = 0;
  return getline(ptrBuf, &len, pFile->fp);
wafwerar's avatar
wafwerar 已提交
775
#endif
776
}
wafwerar's avatar
wafwerar 已提交
777
int64_t taosGetsFile(TdFilePtr pFile, int32_t maxSize, char *__restrict buf) {
L
Liu Jicong 已提交
778
  if (pFile == NULL || buf == NULL) {
wafwerar's avatar
wafwerar 已提交
779 780 781 782 783 784 785 786
    return -1;
  }
  assert(pFile->fp != NULL);
  if (fgets(buf, maxSize, pFile->fp) == NULL) {
    return -1;
  }
  return strlen(buf);
}
L
Liu Jicong 已提交
787
int32_t taosEOFFile(TdFilePtr pFile) {
788 789 790 791 792
  if (pFile == NULL) {
    return 0;
  }
  assert(pFile->fp != NULL);

L
Liu Jicong 已提交
793
  return feof(pFile->fp);
L
fix  
Liu Jicong 已提交
794
}
795

796 797 798 799 800 801 802 803 804 805 806 807 808 809
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 已提交
810 811 812
#ifdef WINDOWS
  return _access(pathname, flags) == 0;
#else
813
  return access(pathname, flags) == 0;
wafwerar's avatar
wafwerar 已提交
814
#endif
815
}
816 817

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