Coverage Report

Created: 2023-06-07 07:02

/src/curl/lib/fopen.c
Line
Count
Source (jump to first uncovered line)
1
/***************************************************************************
2
 *                                  _   _ ____  _
3
 *  Project                     ___| | | |  _ \| |
4
 *                             / __| | | | |_) | |
5
 *                            | (__| |_| |  _ <| |___
6
 *                             \___|\___/|_| \_\_____|
7
 *
8
 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9
 *
10
 * This software is licensed as described in the file COPYING, which
11
 * you should have received as part of this distribution. The terms
12
 * are also available at https://curl.se/docs/copyright.html.
13
 *
14
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15
 * copies of the Software, and permit persons to whom the Software is
16
 * furnished to do so, under the terms of the COPYING file.
17
 *
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
 * KIND, either express or implied.
20
 *
21
 * SPDX-License-Identifier: curl
22
 *
23
 ***************************************************************************/
24
25
#include "curl_setup.h"
26
27
#if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) ||  \
28
  !defined(CURL_DISABLE_HSTS)
29
30
#ifdef HAVE_FCNTL_H
31
#include <fcntl.h>
32
#endif
33
34
#include "urldata.h"
35
#include "rand.h"
36
#include "fopen.h"
37
/* The last 3 #include files should be in this order */
38
#include "curl_printf.h"
39
#include "curl_memory.h"
40
#include "memdebug.h"
41
42
/*
43
 * Curl_fopen() opens a file for writing with a temp name, to be renamed
44
 * to the final name when completed. If there is an existing file using this
45
 * name at the time of the open, this function will clone the mode from that
46
 * file.  if 'tempname' is non-NULL, it needs a rename after the file is
47
 * written.
48
 */
49
CURLcode Curl_fopen(struct Curl_easy *data, const char *filename,
50
                    FILE **fh, char **tempname)
51
1.41k
{
52
1.41k
  CURLcode result = CURLE_WRITE_ERROR;
53
1.41k
  unsigned char randsuffix[9];
54
1.41k
  char *tempstore = NULL;
55
1.41k
  struct_stat sb;
56
1.41k
  int fd = -1;
57
1.41k
  *tempname = NULL;
58
59
1.41k
  if(stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode)) {
60
    /* a non-regular file, fallback to direct fopen() */
61
1.41k
    *fh = fopen(filename, FOPEN_WRITETEXT);
62
1.41k
    if(*fh)
63
1.41k
      return CURLE_OK;
64
0
    goto fail;
65
1.41k
  }
66
67
0
  result = Curl_rand_hex(data, randsuffix, sizeof(randsuffix));
68
0
  if(result)
69
0
    goto fail;
70
71
0
  tempstore = aprintf("%s.%s.tmp", filename, randsuffix);
72
0
  if(!tempstore) {
73
0
    result = CURLE_OUT_OF_MEMORY;
74
0
    goto fail;
75
0
  }
76
77
0
  result = CURLE_WRITE_ERROR;
78
0
  fd = open(tempstore, O_WRONLY | O_CREAT | O_EXCL, 0600);
79
0
  if(fd == -1)
80
0
    goto fail;
81
82
0
#ifdef HAVE_FCHMOD
83
0
  {
84
0
    struct_stat nsb;
85
0
    if((fstat(fd, &nsb) != -1) &&
86
0
       (nsb.st_uid == sb.st_uid) && (nsb.st_gid == sb.st_gid)) {
87
      /* if the user and group are the same, clone the original mode */
88
0
      if(fchmod(fd, sb.st_mode) == -1)
89
0
        goto fail;
90
0
    }
91
0
  }
92
0
#endif
93
94
0
  *fh = fdopen(fd, FOPEN_WRITETEXT);
95
0
  if(!*fh)
96
0
    goto fail;
97
98
0
  *tempname = tempstore;
99
0
  return CURLE_OK;
100
101
0
fail:
102
0
  if(fd != -1) {
103
0
    close(fd);
104
0
    unlink(tempstore);
105
0
  }
106
107
0
  free(tempstore);
108
109
0
  return result;
110
0
}
111
112
#endif /* ! disabled */