xref: /third_party/curl/src/tool_xattr.c (revision 13498266)
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#include "tool_setup.h"
25#include "tool_xattr.h"
26
27#include "memdebug.h" /* keep this as LAST include */
28
29#ifdef USE_XATTR
30
31/* mapping table of curl metadata to extended attribute names */
32static const struct xattr_mapping {
33  const char *attr; /* name of the xattr */
34  CURLINFO info;
35} mappings[] = {
36  /* mappings proposed by
37   * https://freedesktop.org/wiki/CommonExtendedAttributes/
38   */
39  { "user.xdg.referrer.url", CURLINFO_REFERER },
40  { "user.mime_type",        CURLINFO_CONTENT_TYPE },
41  { NULL,                    CURLINFO_NONE } /* last element, abort here */
42};
43
44/* returns a new URL that needs to be freed */
45/* @unittest: 1621 */
46#ifdef UNITTESTS
47char *stripcredentials(const char *url);
48#else
49static
50#endif
51char *stripcredentials(const char *url)
52{
53  CURLU *u;
54  CURLUcode uc;
55  char *nurl;
56  u = curl_url();
57  if(u) {
58    uc = curl_url_set(u, CURLUPART_URL, url, 0);
59    if(uc)
60      goto error;
61
62    uc = curl_url_set(u, CURLUPART_USER, NULL, 0);
63    if(uc)
64      goto error;
65
66    uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0);
67    if(uc)
68      goto error;
69
70    uc = curl_url_get(u, CURLUPART_URL, &nurl, 0);
71    if(uc)
72      goto error;
73
74    curl_url_cleanup(u);
75
76    return nurl;
77  }
78error:
79  curl_url_cleanup(u);
80  return NULL;
81}
82
83static int xattr(int fd,
84                 const char *attr, /* name of the xattr */
85                 const char *value)
86{
87  int err = 0;
88  if(value) {
89#ifdef DEBUGBUILD
90    (void)fd;
91    if(getenv("CURL_FAKE_XATTR")) {
92      printf("%s => %s\n", attr, value);
93    }
94    return 0;
95#else
96#ifdef HAVE_FSETXATTR_6
97    err = fsetxattr(fd, attr, value, strlen(value), 0, 0);
98#elif defined(HAVE_FSETXATTR_5)
99    err = fsetxattr(fd, attr, value, strlen(value), 0);
100#elif defined(__FreeBSD_version) || defined(__MidnightBSD_version)
101    {
102      ssize_t rc = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER,
103                                  attr, value, strlen(value));
104      /* FreeBSD's extattr_set_fd returns the length of the extended
105         attribute */
106      err = (rc < 0 ? -1 : 0);
107    }
108#endif
109#endif
110  }
111  return err;
112}
113/* store metadata from the curl request alongside the downloaded
114 * file using extended attributes
115 */
116int fwrite_xattr(CURL *curl, const char *url, int fd)
117{
118  int i = 0;
119  int err = 0;
120
121  /* loop through all xattr-curlinfo pairs and abort on a set error */
122  while(!err && mappings[i].attr) {
123    char *value = NULL;
124    CURLcode result = curl_easy_getinfo(curl, mappings[i].info, &value);
125    if(!result && value)
126      err = xattr(fd, mappings[i].attr, value);
127    i++;
128  }
129  if(!err) {
130    char *nurl = stripcredentials(url);
131    if(!nurl)
132      return 1;
133    err = xattr(fd, "user.xdg.origin.url", nurl);
134    curl_free(nurl);
135  }
136  return err;
137}
138#endif
139