osFile.c 19.7 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) {
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) {
H
Hongze Cheng 已提交
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
L
Liu Jicong 已提交
467
  assert(pFile->fd >= 0);  // Please check if you have closed the file.
468

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#else

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

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

    leftbytes -= sentbytes;
  }

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

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

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

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

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

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

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

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

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