tool_xattr.c (3738B)
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 */ 32 static 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 UNITTEST char *stripcredentials(const char *url) 47 { 48 CURLU *u; 49 CURLUcode uc; 50 char *nurl; 51 u = curl_url(); 52 if(u) { 53 uc = curl_url_set(u, CURLUPART_URL, url, CURLU_GUESS_SCHEME); 54 if(uc) 55 goto error; 56 57 uc = curl_url_set(u, CURLUPART_USER, NULL, 0); 58 if(uc) 59 goto error; 60 61 uc = curl_url_set(u, CURLUPART_PASSWORD, NULL, 0); 62 if(uc) 63 goto error; 64 65 uc = curl_url_get(u, CURLUPART_URL, &nurl, 0); 66 if(uc) 67 goto error; 68 69 curl_url_cleanup(u); 70 71 return nurl; 72 } 73 error: 74 curl_url_cleanup(u); 75 return NULL; 76 } 77 78 static int xattr(int fd, 79 const char *attr, /* name of the xattr */ 80 const char *value) 81 { 82 int err = 0; 83 if(value) { 84 #ifdef DEBUGBUILD 85 if(getenv("CURL_FAKE_XATTR")) { 86 printf("%s => %s\n", attr, value); 87 return 0; 88 } 89 #endif 90 #ifdef HAVE_FSETXATTR_6 91 err = fsetxattr(fd, attr, value, strlen(value), 0, 0); 92 #elif defined(HAVE_FSETXATTR_5) 93 err = fsetxattr(fd, attr, value, strlen(value), 0); 94 #elif defined(__FreeBSD_version) || defined(__MidnightBSD_version) 95 { 96 ssize_t rc = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, 97 attr, value, strlen(value)); 98 /* FreeBSD's extattr_set_fd returns the length of the extended 99 attribute */ 100 err = (rc < 0 ? -1 : 0); 101 } 102 #endif 103 } 104 return err; 105 } 106 /* store metadata from the curl request alongside the downloaded 107 * file using extended attributes 108 */ 109 int fwrite_xattr(CURL *curl, const char *url, int fd) 110 { 111 int i = 0; 112 int err = xattr(fd, "user.creator", "curl"); 113 114 /* loop through all xattr-curlinfo pairs and abort on a set error */ 115 while(!err && mappings[i].attr) { 116 char *value = NULL; 117 CURLcode result = curl_easy_getinfo(curl, mappings[i].info, &value); 118 if(!result && value) 119 err = xattr(fd, mappings[i].attr, value); 120 i++; 121 } 122 if(!err) { 123 char *nurl = stripcredentials(url); 124 if(!nurl) 125 return 1; 126 err = xattr(fd, "user.xdg.origin.url", nurl); 127 curl_free(nurl); 128 } 129 return err; 130 } 131 #endif