new command geturl

This commit is contained in:
Axel Kohlmeyer
2024-08-07 09:36:46 -04:00
parent 843e678a78
commit b645a0c4b1
3 changed files with 217 additions and 0 deletions

72
doc/src/geturl.rst Normal file
View File

@ -0,0 +1,72 @@
.. index:: geturl
geturl command
==============
Syntax
""""""
.. code-block:: LAMMPS
geturl url keyword args ...
* url = URL of the file to download
* zero or more keyword argument pairs may be provided
* keyword = *output* or *verify* or *overwrite*
.. parsed-literal::
*output* filename = write to *filename* instead of inferring the name from the URL
*verify* yes/no = verify SSL certificate and hostname if *yes*, do not if *no*
*overwrite* yes/no = if *yes* overwrite the output file in case it exists, do not if *no*
Examples
""""""""
.. code-block:: LAMMPS
geturl https://www.ctcms.nist.gov/potentials/Download/1990--Ackland-G-J-Vitek-V--Cu/2/Cu2.eam.fs
geturl https://github.com/lammps/lammps/blob/develop/bench/in.lj output in.bench-lj
Description
"""""""""""
Download a file from an URL to the local disk. This is implemented with
the `libcurl library <https:://curl.se/libcurl/>`_ which supports a
large variety of protocols including "http", "https", "ftp", "scp",
"sftp", "file". The transfer will only be performed on MPI rank 0.
The *output* keyword can be used to set the filename. By default, the last part
of the URL is used.
The *verify* keyword allows to turn on or off whether ``libcurl`` will validate
the SSL certificate and hostname for encrypted connections. Turning this off
may be required when using a proxy or connecting to a server with a self-signed
SSL certificate.
The *overwrite* keyword determines whether a file should be overwritten if it
already exists. If the argument is *no*, then the download will be skipped
if the file exists.
----------
Restrictions
""""""""""""
This command is part of the EXTRA-COMMAND package. It is only enabled
if LAMMPS was built with that package. See the :doc:`Build package
<Build_package>` page for more info. It also requires that LAMMPS was
built with support for `the libcurl library
<https://curl.se/libcurl/>`_. See the page about :ref:`Compiling LAMMPS
with libcurl support <libcurl>` for further info. If support for
libcurl is not included, using *geturl* will trigger an error.
Related commands
""""""""""""""""
:doc:`shell <shell>`
Default
"""""""
*verify* = yes, *overwrite* = yes

View File

@ -0,0 +1,111 @@
/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Axel Kohlmeyer (Temple U),
------------------------------------------------------------------------- */
#include "geturl.h"
#include "comm.h"
#include "error.h"
#if defined(LAMMPS_CURL)
#include <curl/curl.h>
#endif
using namespace LAMMPS_NS;
/* ---------------------------------------------------------------------- */
void GetURL::command(int narg, char **arg)
{
#if !defined(LAMMPS_CURL)
error->all(FLERR, "LAMMPS has not been compiled with libcurl support");
#else
if (narg < 1) utils::missing_cmd_args(FLERR, "geturl", error);
int verify = 1;
int overwrite = 1;
// process arguments
std::string url = arg[0];
// sanity check
if ((url.find(':') == std::string::npos) || (url.find('/') == std::string::npos))
error->all(FLERR, "URL '{}' is not a supported URL", url);
std::string output = url.substr(url.find_last_of('/') + 1);
if (output.empty()) error->all(FLERR, "URL '{}' must end in a file string", url);
int iarg = 1;
while (iarg < narg) {
if (strcmp(arg[iarg], "output") == 0) {
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "geturl output", error);
output = arg[iarg + 1];
++iarg;
} else if (strcmp(arg[iarg], "overwrite") == 0) {
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "geturl overwrite", error);
overwrite = utils::logical(FLERR, arg[iarg + 1], false, lmp);
++iarg;
} else if (strcmp(arg[iarg], "verify") == 0) {
if (iarg + 2 > narg) utils::missing_cmd_args(FLERR, "geturl verify", error);
verify = utils::logical(FLERR, arg[iarg + 1], false, lmp);
++iarg;
} else {
error->all(FLERR, "Unknown geturl keyword: {}", arg[iarg]);
}
++iarg;
}
// only download files from rank 0
if (comm->me != 0) return;
if (!overwrite && platform::file_is_readable(output)) return;
// open output file for writing
FILE *out = fopen(output.c_str(), "wb");
if (!out)
error->all(FLERR, "Cannot open output file {} for writing: {}", output, utils::getsyserror());
// initialize curl and perform download
CURL *curl;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) out);
curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
if (!verify) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
}
auto res = curl_easy_perform(curl);
if (res != CURLE_OK) {
long response = 0L;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
error->one(FLERR, "Download of {} failed with: {} {}", output, curl_easy_strerror(res),
response);
}
curl_easy_cleanup(curl);
}
curl_global_cleanup();
fclose(out);
#endif
}

View File

@ -0,0 +1,34 @@
/* -*- c++ -*- ----------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
#ifdef COMMAND_CLASS
// clang-format off
CommandStyle(geturl,GetURL);
// clang-format on
#else
#ifndef LMP_GETURL_H
#define LMP_GETURL_H
#include "command.h"
namespace LAMMPS_NS {
class GetURL : public Command {
public:
GetURL(class LAMMPS *lmp) : Command(lmp) {};
void command(int, char **) override;
};
} // namespace LAMMPS_NS
#endif
#endif