importd: add bus/varlink api for downloading OCIs
This commit is contained in:
@@ -136,6 +136,12 @@ node /org/freedesktop/import1 {
|
|||||||
in t flags,
|
in t flags,
|
||||||
out u transfer_id,
|
out u transfer_id,
|
||||||
out o transfer_path);
|
out o transfer_path);
|
||||||
|
PullOci(in s ref,
|
||||||
|
in s local_name,
|
||||||
|
in s class,
|
||||||
|
in t flags,
|
||||||
|
out u transfer_id,
|
||||||
|
out o transfer_path);
|
||||||
ListTransfers(out a(usssdo) transfers);
|
ListTransfers(out a(usssdo) transfers);
|
||||||
ListTransfersEx(in s class,
|
ListTransfersEx(in s class,
|
||||||
in t flags,
|
in t flags,
|
||||||
@@ -191,6 +197,8 @@ node /org/freedesktop/import1 {
|
|||||||
|
|
||||||
<variablelist class="dbus-method" generated="True" extra-ref="PullRawEx()"/>
|
<variablelist class="dbus-method" generated="True" extra-ref="PullRawEx()"/>
|
||||||
|
|
||||||
|
<variablelist class="dbus-method" generated="True" extra-ref="PullOci()"/>
|
||||||
|
|
||||||
<variablelist class="dbus-method" generated="True" extra-ref="ListTransfers()"/>
|
<variablelist class="dbus-method" generated="True" extra-ref="ListTransfers()"/>
|
||||||
|
|
||||||
<variablelist class="dbus-method" generated="True" extra-ref="ListTransfersEx()"/>
|
<variablelist class="dbus-method" generated="True" extra-ref="ListTransfersEx()"/>
|
||||||
@@ -290,6 +298,19 @@ node /org/freedesktop/import1 {
|
|||||||
export calls above, these calls return a pair of transfer identifier and object path for the ongoing
|
export calls above, these calls return a pair of transfer identifier and object path for the ongoing
|
||||||
download.</para>
|
download.</para>
|
||||||
|
|
||||||
|
<para><function>PullOci()</function> is similar to <function>PullTarEx()</function> or
|
||||||
|
<function>PullRawEx()</function> and may be used to download and import an OCI container image from an
|
||||||
|
OCI registry. It takes an OCI container reference as argument. The second argument is a local name for
|
||||||
|
the image (which will be generated as
|
||||||
|
<citerefentry><refentrytitle>systemd.mstack</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||||
|
directory referencing the OCI layers). It should be suitable as a hostname, similarly to the matching
|
||||||
|
argument of the <function>PullTar()</function>/<function>PullTarEx()</function> and
|
||||||
|
<function>PullRaw()</function>/<function>PullRawEx()</function> methods above. The last argument is a
|
||||||
|
64bit flags parameter, where bit 0 controls the <literal>force</literal> flag, bit 1 is a
|
||||||
|
<literal>read_only</literal> flag that controls whether the created image shall be marked
|
||||||
|
read-only. Like the pull calls above, this call return a pair of transfer identifier and object path
|
||||||
|
for the ongoing download.</para>
|
||||||
|
|
||||||
<para><function>ImportFileSystem()</function>/<function>ImportFileSystemEx()</function> are similar to
|
<para><function>ImportFileSystem()</function>/<function>ImportFileSystemEx()</function> are similar to
|
||||||
<function>ImportTar()</function>/<function>ImportTarEx()</function> but import a directory tree. The
|
<function>ImportTar()</function>/<function>ImportTarEx()</function> but import a directory tree. The
|
||||||
first argument must refer to a directory file descriptor for the source hierarchy to import.</para>
|
first argument must refer to a directory file descriptor for the source hierarchy to import.</para>
|
||||||
@@ -464,6 +485,7 @@ node /org/freedesktop/import1/transfer/_1 {
|
|||||||
<function>ExportRawEx()</function>, <function>PullTarEx()</function>, <function>PullRawEx()</function>,
|
<function>ExportRawEx()</function>, <function>PullTarEx()</function>, <function>PullRawEx()</function>,
|
||||||
<function>ListTransfersEx()</function>, <function>ListImages()</function> were added in version
|
<function>ListTransfersEx()</function>, <function>ListImages()</function> were added in version
|
||||||
256.</para>
|
256.</para>
|
||||||
|
<para><function>PullOci()</function> was added in version 260.</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Transfer Objects</title>
|
<title>Transfer Objects</title>
|
||||||
|
|||||||
+105
-61
@@ -29,6 +29,7 @@
|
|||||||
#include "json-util.h"
|
#include "json-util.h"
|
||||||
#include "main-func.h"
|
#include "main-func.h"
|
||||||
#include "notify-recv.h"
|
#include "notify-recv.h"
|
||||||
|
#include "oci-util.h"
|
||||||
#include "os-util.h"
|
#include "os-util.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "path-lookup.h"
|
#include "path-lookup.h"
|
||||||
@@ -58,6 +59,7 @@ typedef enum TransferType {
|
|||||||
TRANSFER_EXPORT_RAW,
|
TRANSFER_EXPORT_RAW,
|
||||||
TRANSFER_PULL_TAR,
|
TRANSFER_PULL_TAR,
|
||||||
TRANSFER_PULL_RAW,
|
TRANSFER_PULL_RAW,
|
||||||
|
TRANSFER_PULL_OCI,
|
||||||
_TRANSFER_TYPE_MAX,
|
_TRANSFER_TYPE_MAX,
|
||||||
_TRANSFER_TYPE_INVALID = -EINVAL,
|
_TRANSFER_TYPE_INVALID = -EINVAL,
|
||||||
} TransferType;
|
} TransferType;
|
||||||
@@ -127,6 +129,7 @@ static const char* const transfer_type_table[_TRANSFER_TYPE_MAX] = {
|
|||||||
[TRANSFER_EXPORT_RAW] = "export-raw",
|
[TRANSFER_EXPORT_RAW] = "export-raw",
|
||||||
[TRANSFER_PULL_TAR] = "pull-tar",
|
[TRANSFER_PULL_TAR] = "pull-tar",
|
||||||
[TRANSFER_PULL_RAW] = "pull-raw",
|
[TRANSFER_PULL_RAW] = "pull-raw",
|
||||||
|
[TRANSFER_PULL_OCI] = "pull-oci",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(transfer_type, TransferType);
|
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(transfer_type, TransferType);
|
||||||
@@ -497,6 +500,7 @@ static int transfer_start(Transfer *t) {
|
|||||||
|
|
||||||
case TRANSFER_PULL_TAR:
|
case TRANSFER_PULL_TAR:
|
||||||
case TRANSFER_PULL_RAW:
|
case TRANSFER_PULL_RAW:
|
||||||
|
case TRANSFER_PULL_OCI:
|
||||||
cmd[k++] = SYSTEMD_PULL_PATH;
|
cmd[k++] = SYSTEMD_PULL_PATH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -518,6 +522,10 @@ static int transfer_start(Transfer *t) {
|
|||||||
cmd[k++] = "raw";
|
cmd[k++] = "raw";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TRANSFER_PULL_OCI:
|
||||||
|
cmd[k++] = "oci";
|
||||||
|
break;
|
||||||
|
|
||||||
case TRANSFER_IMPORT_FS:
|
case TRANSFER_IMPORT_FS:
|
||||||
cmd[k++] = "run";
|
cmd[k++] = "run";
|
||||||
break;
|
break;
|
||||||
@@ -1053,7 +1061,7 @@ static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
|
static int method_pull_tar_or_raw_or_oci(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
|
||||||
_cleanup_(transfer_unrefp) Transfer *t = NULL;
|
_cleanup_(transfer_unrefp) Transfer *t = NULL;
|
||||||
ImageClass class = _IMAGE_CLASS_INVALID;
|
ImageClass class = _IMAGE_CLASS_INVALID;
|
||||||
const char *remote, *local, *verify;
|
const char *remote, *local, *verify;
|
||||||
@@ -1078,7 +1086,24 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
|
|||||||
return 1; /* Will call us back */
|
return 1; /* Will call us back */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (endswith(sd_bus_message_get_member(msg), "Ex")) {
|
if (streq(sd_bus_message_get_member(msg), "PullOci")) {
|
||||||
|
const char *sclass;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(msg, "ssst", &remote, &local, &sclass, &flags);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
class = image_class_from_string(sclass);
|
||||||
|
if (class < 0)
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||||
|
"Image class '%s' not known", sclass);
|
||||||
|
|
||||||
|
if (flags & ~(IMPORT_FORCE|IMPORT_READ_ONLY))
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||||
|
"Flags 0x%" PRIx64 " invalid", flags);
|
||||||
|
|
||||||
|
verify = NULL;
|
||||||
|
} else if (endswith(sd_bus_message_get_member(msg), "Ex")) {
|
||||||
const char *sclass;
|
const char *sclass;
|
||||||
|
|
||||||
r = sd_bus_message_read(msg, "sssst", &remote, &local, &sclass, &verify, &flags);
|
r = sd_bus_message_read(msg, "sssst", &remote, &local, &sclass, &verify, &flags);
|
||||||
@@ -1106,9 +1131,21 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
|
|||||||
SET_FLAG(flags, IMPORT_FORCE, force);
|
SET_FLAG(flags, IMPORT_FORCE, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!http_url_is_valid(remote) && !file_url_is_valid(remote))
|
type = startswith(sd_bus_message_get_member(msg), "PullTar") ? TRANSFER_PULL_TAR :
|
||||||
|
startswith(sd_bus_message_get_member(msg), "PullRaw") ? TRANSFER_PULL_RAW :
|
||||||
|
streq(sd_bus_message_get_member(msg), "PullOci") ? TRANSFER_PULL_OCI : _TRANSFER_TYPE_INVALID;
|
||||||
|
assert(type >= 0);
|
||||||
|
|
||||||
|
if (type == TRANSFER_PULL_OCI) {
|
||||||
|
r = oci_ref_valid(remote);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||||
|
"Reference '%s' is invalid", remote);
|
||||||
|
} else if (!http_url_is_valid(remote) && !file_url_is_valid(remote))
|
||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||||
"URL %s is invalid", remote);
|
"URL '%s' is invalid", remote);
|
||||||
|
|
||||||
if (isempty(local))
|
if (isempty(local))
|
||||||
local = NULL;
|
local = NULL;
|
||||||
@@ -1116,13 +1153,16 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
|
|||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||||
"Local image name %s is invalid", local);
|
"Local image name %s is invalid", local);
|
||||||
|
|
||||||
if (isempty(verify))
|
if (type == TRANSFER_PULL_OCI)
|
||||||
|
v = _IMPORT_VERIFY_INVALID;
|
||||||
|
else if (isempty(verify))
|
||||||
v = IMPORT_VERIFY_SIGNATURE;
|
v = IMPORT_VERIFY_SIGNATURE;
|
||||||
else
|
else {
|
||||||
v = import_verify_from_string(verify);
|
v = import_verify_from_string(verify);
|
||||||
if (v < 0)
|
if (v < 0)
|
||||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
|
||||||
"Unknown verification mode %s", verify);
|
"Unknown verification mode %s", verify);
|
||||||
|
}
|
||||||
|
|
||||||
if (class == IMAGE_MACHINE) {
|
if (class == IMAGE_MACHINE) {
|
||||||
r = image_setup_pool(m->runtime_scope, class, m->use_btrfs_subvol, m->use_btrfs_quota);
|
r = image_setup_pool(m->runtime_scope, class, m->use_btrfs_subvol, m->use_btrfs_quota);
|
||||||
@@ -1130,9 +1170,6 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
|
|||||||
return sd_bus_error_set_errnof(error, r, "Failed to set up machine pool: %m");
|
return sd_bus_error_set_errnof(error, r, "Failed to set up machine pool: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
type = startswith(sd_bus_message_get_member(msg), "PullTar") ?
|
|
||||||
TRANSFER_PULL_TAR : TRANSFER_PULL_RAW;
|
|
||||||
|
|
||||||
if (manager_find(m, type, remote))
|
if (manager_find(m, type, remote))
|
||||||
return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS,
|
return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS,
|
||||||
"Transfer for %s already in progress.", remote);
|
"Transfer for %s already in progress.", remote);
|
||||||
@@ -1613,52 +1650,53 @@ static const sd_bus_vtable manager_vtable[] = {
|
|||||||
SD_BUS_PARAM(transfer_path),
|
SD_BUS_PARAM(transfer_path),
|
||||||
method_export_tar_or_raw,
|
method_export_tar_or_raw,
|
||||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_METHOD_WITH_NAMES("PullTar",
|
SD_BUS_METHOD_WITH_ARGS("PullTar",
|
||||||
"sssb",
|
SD_BUS_ARGS("s", url,
|
||||||
SD_BUS_PARAM(url)
|
"s", local_name,
|
||||||
SD_BUS_PARAM(local_name)
|
"s", verify_mode,
|
||||||
SD_BUS_PARAM(verify_mode)
|
"b", force),
|
||||||
SD_BUS_PARAM(force),
|
SD_BUS_RESULT("u", transfer_id,
|
||||||
"uo",
|
"o", transfer_path),
|
||||||
SD_BUS_PARAM(transfer_id)
|
method_pull_tar_or_raw_or_oci,
|
||||||
SD_BUS_PARAM(transfer_path),
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
method_pull_tar_or_raw,
|
SD_BUS_METHOD_WITH_ARGS("PullTarEx",
|
||||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_ARGS("s", url,
|
||||||
SD_BUS_METHOD_WITH_NAMES("PullTarEx",
|
"s", local_name,
|
||||||
"sssst",
|
"s", class,
|
||||||
SD_BUS_PARAM(url)
|
"s", verify_mode,
|
||||||
SD_BUS_PARAM(local_name)
|
"t", flags),
|
||||||
SD_BUS_PARAM(class)
|
SD_BUS_RESULT("u", transfer_id,
|
||||||
SD_BUS_PARAM(verify_mode)
|
"o", transfer_path),
|
||||||
SD_BUS_PARAM(flags),
|
method_pull_tar_or_raw_or_oci,
|
||||||
"uo",
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_PARAM(transfer_id)
|
SD_BUS_METHOD_WITH_ARGS("PullRaw",
|
||||||
SD_BUS_PARAM(transfer_path),
|
SD_BUS_ARGS("s", url,
|
||||||
method_pull_tar_or_raw,
|
"s", local_name,
|
||||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
"s", verify_mode,
|
||||||
SD_BUS_METHOD_WITH_NAMES("PullRaw",
|
"b", force),
|
||||||
"sssb",
|
SD_BUS_RESULT("u", transfer_id,
|
||||||
SD_BUS_PARAM(url)
|
"o", transfer_path),
|
||||||
SD_BUS_PARAM(local_name)
|
method_pull_tar_or_raw_or_oci,
|
||||||
SD_BUS_PARAM(verify_mode)
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_PARAM(force),
|
SD_BUS_METHOD_WITH_ARGS("PullRawEx",
|
||||||
"uo",
|
SD_BUS_ARGS("s", url,
|
||||||
SD_BUS_PARAM(transfer_id)
|
"s", local_name,
|
||||||
SD_BUS_PARAM(transfer_path),
|
"s", class,
|
||||||
method_pull_tar_or_raw,
|
"s", verify_mode,
|
||||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
"t", flags),
|
||||||
SD_BUS_METHOD_WITH_NAMES("PullRawEx",
|
SD_BUS_RESULT("u", transfer_id,
|
||||||
"sssst",
|
"o", transfer_path),
|
||||||
SD_BUS_PARAM(url)
|
method_pull_tar_or_raw_or_oci,
|
||||||
SD_BUS_PARAM(local_name)
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_PARAM(class)
|
SD_BUS_METHOD_WITH_ARGS("PullOci",
|
||||||
SD_BUS_PARAM(verify_mode)
|
SD_BUS_ARGS("s", ref,
|
||||||
SD_BUS_PARAM(flags),
|
"s", local_name,
|
||||||
"uo",
|
"s", class,
|
||||||
SD_BUS_PARAM(transfer_id)
|
"t", flags),
|
||||||
SD_BUS_PARAM(transfer_path),
|
SD_BUS_RESULT("u", transfer_id,
|
||||||
method_pull_tar_or_raw,
|
"o", transfer_path),
|
||||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
method_pull_tar_or_raw_or_oci,
|
||||||
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_METHOD_WITH_NAMES("ListTransfers",
|
SD_BUS_METHOD_WITH_NAMES("ListTransfers",
|
||||||
NULL,,
|
NULL,,
|
||||||
"a(usssdo)",
|
"a(usssdo)",
|
||||||
@@ -1864,7 +1902,13 @@ static int vl_method_pull(sd_varlink *link, sd_json_variant *parameters, sd_varl
|
|||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (!http_url_is_valid(p.remote) && !file_url_is_valid(p.remote))
|
if (p.type == IMPORT_OCI) {
|
||||||
|
r = oci_ref_valid(p.remote);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
return sd_varlink_error_invalid_parameter_name(link, "remote");
|
||||||
|
} else if (!http_url_is_valid(p.remote) && !file_url_is_valid(p.remote))
|
||||||
return sd_varlink_error_invalid_parameter_name(link, "remote");
|
return sd_varlink_error_invalid_parameter_name(link, "remote");
|
||||||
|
|
||||||
if (p.local && !image_name_is_valid(p.local))
|
if (p.local && !image_name_is_valid(p.local))
|
||||||
@@ -1874,8 +1918,8 @@ static int vl_method_pull(sd_varlink *link, sd_json_variant *parameters, sd_varl
|
|||||||
|
|
||||||
TransferType tt =
|
TransferType tt =
|
||||||
p.type == IMPORT_TAR ? TRANSFER_PULL_TAR :
|
p.type == IMPORT_TAR ? TRANSFER_PULL_TAR :
|
||||||
p.type == IMPORT_RAW ? TRANSFER_PULL_RAW : _TRANSFER_TYPE_INVALID;
|
p.type == IMPORT_RAW ? TRANSFER_PULL_RAW :
|
||||||
|
p.type == IMPORT_OCI ? TRANSFER_PULL_OCI : _TRANSFER_TYPE_INVALID;
|
||||||
assert(tt >= 0);
|
assert(tt >= 0);
|
||||||
|
|
||||||
if (manager_find(m, tt, p.remote))
|
if (manager_find(m, tt, p.remote))
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ executables += [
|
|||||||
'dbus' : true,
|
'dbus' : true,
|
||||||
'sources' : files(
|
'sources' : files(
|
||||||
'importd.c',
|
'importd.c',
|
||||||
|
'oci-util.c',
|
||||||
),
|
),
|
||||||
'extract' : files(
|
'extract' : files(
|
||||||
'oci-util.c',
|
'oci-util.c',
|
||||||
|
|||||||
@@ -106,6 +106,10 @@
|
|||||||
send_interface="org.freedesktop.import1.Manager"
|
send_interface="org.freedesktop.import1.Manager"
|
||||||
send_member="PullRawEx"/>
|
send_member="PullRawEx"/>
|
||||||
|
|
||||||
|
<allow send_destination="org.freedesktop.import1"
|
||||||
|
send_interface="org.freedesktop.import1.Manager"
|
||||||
|
send_member="PullOci"/>
|
||||||
|
|
||||||
<allow send_destination="org.freedesktop.import1"
|
<allow send_destination="org.freedesktop.import1"
|
||||||
send_interface="org.freedesktop.import1.Transfer"
|
send_interface="org.freedesktop.import1.Transfer"
|
||||||
send_member="Cancel"/>
|
send_member="Cancel"/>
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ int import_url_change_suffix(
|
|||||||
static const char* const import_type_table[_IMPORT_TYPE_MAX] = {
|
static const char* const import_type_table[_IMPORT_TYPE_MAX] = {
|
||||||
[IMPORT_RAW] = "raw",
|
[IMPORT_RAW] = "raw",
|
||||||
[IMPORT_TAR] = "tar",
|
[IMPORT_TAR] = "tar",
|
||||||
|
[IMPORT_OCI] = "oci",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP(import_type, ImportType);
|
DEFINE_STRING_TABLE_LOOKUP(import_type, ImportType);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
typedef enum ImportType {
|
typedef enum ImportType {
|
||||||
IMPORT_RAW,
|
IMPORT_RAW,
|
||||||
IMPORT_TAR,
|
IMPORT_TAR,
|
||||||
|
IMPORT_OCI,
|
||||||
_IMPORT_TYPE_MAX,
|
_IMPORT_TYPE_MAX,
|
||||||
_IMPORT_TYPE_INVALID = -EINVAL,
|
_IMPORT_TYPE_INVALID = -EINVAL,
|
||||||
} ImportType;
|
} ImportType;
|
||||||
|
|||||||
Reference in New Issue
Block a user