MYNEWT-569 Move file cmds from imgr to new grp: fs
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/1dc3d2c8 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/1dc3d2c8 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/1dc3d2c8 Branch: refs/heads/develop Commit: 1dc3d2c848beb983673481abcabeb719d1bbe5ea Parents: 7c2c84d Author: Christopher Collins <[email protected]> Authored: Thu Jan 26 19:03:05 2017 -0800 Committer: Christopher Collins <[email protected]> Committed: Thu Jan 26 19:03:05 2017 -0800 ---------------------------------------------------------------------- fs/fs/include/fs/fs.h | 5 + fs/fs/src/fs_mount.c | 13 +- fs/fs/src/fs_nmgr.c | 270 +++++++++++++++++++++++++++++++++++++ fs/fs/src/fs_priv.h | 4 + fs/fs/syscfg.yml | 4 + fs/nffs/src/nffs.c | 2 - mgmt/imgmgr/src/imgmgr.c | 9 -- mgmt/imgmgr/src/imgmgr_fs.c | 233 -------------------------------- mgmt/imgmgr/src/imgmgr_priv.h | 2 - mgmt/mgmt/include/mgmt/mgmt.h | 3 +- sys/log/full/src/log.c | 6 +- 11 files changed, 301 insertions(+), 250 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1dc3d2c8/fs/fs/include/fs/fs.h ---------------------------------------------------------------------- diff --git a/fs/fs/include/fs/fs.h b/fs/fs/include/fs/fs.h index b44f624..ce5da94 100644 --- a/fs/fs/include/fs/fs.h +++ b/fs/fs/include/fs/fs.h @@ -79,6 +79,11 @@ int fs_dirent_is_dir(const struct fs_dirent *); #define FS_EACCESS 12 /* Operation prohibited by file open mode */ #define FS_EUNINIT 13 /* File system not initialized */ +#define FS_NMGR_ID_FILE 0 + +#define FS_NMGR_MAX_MSG 400 +#define FS_NMGR_MAX_NAME 64 + #ifdef __cplusplus } #endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1dc3d2c8/fs/fs/src/fs_mount.c ---------------------------------------------------------------------- diff --git a/fs/fs/src/fs_mount.c b/fs/fs/src/fs_mount.c index d79854e..022ea29 100644 --- a/fs/fs/src/fs_mount.c +++ b/fs/fs/src/fs_mount.c @@ -26,7 +26,11 @@ static SLIST_HEAD(, fs_ops) root_fops = SLIST_HEAD_INITIALIZER(); #if MYNEWT_VAL(FS_CLI) -static int g_cli_initialized = 0; +static uint8_t g_cli_initialized; +#endif + +#if MYNEWT_VAL(FS_NMGR) +static uint8_t g_nmgr_initialized; #endif int @@ -49,6 +53,13 @@ fs_register(struct fs_ops *fops) } #endif +#if MYNEWT_VAL(FS_NMGR) + if (!g_nmgr_initialized) { + fs_nmgr_init(); + g_nmgr_initialized = 1; + } +#endif + return FS_EOK; } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1dc3d2c8/fs/fs/src/fs_nmgr.c ---------------------------------------------------------------------- diff --git a/fs/fs/src/fs_nmgr.c b/fs/fs/src/fs_nmgr.c new file mode 100644 index 0000000..d04d768 --- /dev/null +++ b/fs/fs/src/fs_nmgr.c @@ -0,0 +1,270 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "syscfg/syscfg.h" + +#if MYNEWT_VAL(FS_NMGR) + +#include <limits.h> +#include <assert.h> +#include <string.h> +#include <stdio.h> + +#include "os/os.h" +#include "os/endian.h" +#include "newtmgr/newtmgr.h" +#include "bootutil/image.h" +#include "fs/fs.h" +#include "cborattr/cborattr.h" +#include "bsp/bsp.h" +#include "mgmt/mgmt.h" + +#include "fs/fs.h" +#include "fs_priv.h" + +static struct { + struct { + uint32_t off; + uint32_t size; + const struct flash_area *fa; + struct fs_file *file; + } upload; +} fs_nmgr_state; + +static int fs_nmgr_file_download(struct mgmt_cbuf *cb); +static int fs_nmgr_file_upload(struct mgmt_cbuf *cb); + +static const struct mgmt_handler fs_nmgr_handlers[] = { + [FS_NMGR_ID_FILE] = { + .mh_read = fs_nmgr_file_download, + .mh_write = fs_nmgr_file_upload + }, +}; + +#define FS_NMGR_HANDLER_CNT \ + sizeof(fs_nmgr_handlers) / sizeof(fs_nmgr_handlers[0]) + +static struct mgmt_group fs_nmgr_group = { + .mg_handlers = fs_nmgr_handlers, + .mg_handlers_count = FS_NMGR_HANDLER_CNT, + .mg_group_id = MGMT_GROUP_ID_FS, +}; + +static int +fs_nmgr_file_download(struct mgmt_cbuf *cb) +{ + long long unsigned int off = UINT_MAX; + char tmp_str[FS_NMGR_MAX_NAME + 1]; + uint8_t img_data[FS_NMGR_MAX_MSG]; + const struct cbor_attr_t dload_attr[3] = { + [0] = { + .attribute = "off", + .type = CborAttrUnsignedIntegerType, + .addr.uinteger = &off + }, + [1] = { + .attribute = "name", + .type = CborAttrTextStringType, + .addr.string = tmp_str, + .len = sizeof(tmp_str) + }, + [2] = { 0 }, + }; + int rc; + uint32_t out_len; + struct fs_file *file; + CborError g_err = CborNoError; + CborEncoder *penc = &cb->encoder; + CborEncoder rsp; + + rc = cbor_read_object(&cb->it, dload_attr); + if (rc || off == UINT_MAX) { + rc = MGMT_ERR_EINVAL; + goto err; + } + + rc = fs_open(tmp_str, FS_ACCESS_READ, &file); + if (rc || !file) { + rc = MGMT_ERR_ENOMEM; + goto err; + } + + rc = fs_seek(file, off); + if (rc) { + rc = MGMT_ERR_EUNKNOWN; + goto err_close; + } + rc = fs_read(file, 32, img_data, &out_len); + if (rc) { + rc = MGMT_ERR_EUNKNOWN; + goto err_close; + } + + g_err |= cbor_encoder_create_map(penc, &rsp, CborIndefiniteLength); + + g_err |= cbor_encode_text_stringz(&rsp, "off"); + g_err |= cbor_encode_uint(&rsp, off); + + g_err |= cbor_encode_text_stringz(&rsp, "data"); + g_err |= cbor_encode_byte_string(&rsp, img_data, out_len); + + g_err |= cbor_encode_text_stringz(&rsp, "rc"); + g_err |= cbor_encode_int(&rsp, MGMT_ERR_EOK); + if (off == 0) { + rc = fs_filelen(file, &out_len); + g_err |= cbor_encode_text_stringz(&rsp, "len"); + g_err |= cbor_encode_uint(&rsp, out_len); + } + g_err |= cbor_encoder_close_container(penc, &rsp); + + fs_close(file); + if (g_err) { + return MGMT_ERR_ENOMEM; + } + return 0; + +err_close: + fs_close(file); +err: + mgmt_cbuf_setoerr(cb, rc); + return 0; +} + +static int +fs_nmgr_file_upload(struct mgmt_cbuf *cb) +{ + uint8_t img_data[FS_NMGR_MAX_MSG]; + char file_name[FS_NMGR_MAX_NAME + 1]; + size_t img_len; + long long unsigned int off = UINT_MAX; + long long unsigned int size = UINT_MAX; + const struct cbor_attr_t off_attr[5] = { + [0] = { + .attribute = "off", + .type = CborAttrUnsignedIntegerType, + .addr.uinteger = &off, + .nodefault = true + }, + [1] = { + .attribute = "data", + .type = CborAttrByteStringType, + .addr.bytestring.data = img_data, + .addr.bytestring.len = &img_len, + .len = sizeof(img_data) + }, + [2] = { + .attribute = "len", + .type = CborAttrUnsignedIntegerType, + .addr.uinteger = &size, + .nodefault = true + }, + [3] = { + .attribute = "name", + .type = CborAttrTextStringType, + .addr.string = file_name, + .len = sizeof(file_name) + }, + [4] = { 0 }, + }; + CborError g_err = CborNoError; + CborEncoder *penc = &cb->encoder; + CborEncoder rsp; + int rc; + + rc = cbor_read_object(&cb->it, off_attr); + if (rc || off == UINT_MAX) { + rc = MGMT_ERR_EINVAL; + goto err; + } + + if (off == 0) { + /* + * New upload. + */ + fs_nmgr_state.upload.off = 0; + fs_nmgr_state.upload.size = size; + + if (!strlen(file_name)) { + rc = MGMT_ERR_EINVAL; + goto err; + } + if (fs_nmgr_state.upload.file) { + fs_close(fs_nmgr_state.upload.file); + fs_nmgr_state.upload.file = NULL; + } + rc = fs_open(file_name, FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE, + &fs_nmgr_state.upload.file); + if (rc) { + rc = MGMT_ERR_EINVAL; + goto err; + } + } else if (off != fs_nmgr_state.upload.off) { + /* + * Invalid offset. Drop the data, and respond with the offset we're + * expecting data for. + */ + goto out; + } + + if (!fs_nmgr_state.upload.file) { + rc = MGMT_ERR_EINVAL; + goto err; + } + if (img_len) { + rc = fs_write(fs_nmgr_state.upload.file, img_data, img_len); + if (rc) { + rc = MGMT_ERR_EINVAL; + goto err_close; + } + fs_nmgr_state.upload.off += img_len; + if (fs_nmgr_state.upload.size == fs_nmgr_state.upload.off) { + /* Done */ + fs_close(fs_nmgr_state.upload.file); + fs_nmgr_state.upload.file = NULL; + } + } +out: + g_err |= cbor_encoder_create_map(penc, &rsp, CborIndefiniteLength); + g_err |= cbor_encode_text_stringz(&rsp, "rc"); + g_err |= cbor_encode_int(&rsp, MGMT_ERR_EOK); + g_err |= cbor_encode_text_stringz(&rsp, "off"); + g_err |= cbor_encode_uint(&rsp, fs_nmgr_state.upload.off); + g_err |= cbor_encoder_close_container(penc, &rsp); + if (g_err) { + return MGMT_ERR_ENOMEM; + } + return 0; + +err_close: + fs_close(fs_nmgr_state.upload.file); + fs_nmgr_state.upload.file = NULL; +err: + mgmt_cbuf_setoerr(cb, rc); + return 0; +} + +int +fs_nmgr_init(void) +{ + int rc; + + rc = mgmt_group_register(&fs_nmgr_group); + return rc; +} +#endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1dc3d2c8/fs/fs/src/fs_priv.h ---------------------------------------------------------------------- diff --git a/fs/fs/src/fs_priv.h b/fs/fs/src/fs_priv.h index d9cbd2d..80211dc 100644 --- a/fs/fs/src/fs_priv.h +++ b/fs/fs/src/fs_priv.h @@ -33,6 +33,10 @@ struct fs_ops *safe_fs_ops_for(const char *fs_name); void fs_cli_init(void); #endif +#if MYNEWT_VAL(FS_NMGR) +int fs_nmgr_init(void); +#endif + #ifdef __cplusplus } #endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1dc3d2c8/fs/fs/syscfg.yml ---------------------------------------------------------------------- diff --git a/fs/fs/syscfg.yml b/fs/fs/syscfg.yml index 487d10c..d919f35 100644 --- a/fs/fs/syscfg.yml +++ b/fs/fs/syscfg.yml @@ -24,3 +24,7 @@ syscfg.defs: value: 0 restrictions: - SHELL_TASK + + FS_NMGR: + description: 'Enables file system newtmgr commands.' + value: 0 http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1dc3d2c8/fs/nffs/src/nffs.c ---------------------------------------------------------------------- diff --git a/fs/nffs/src/nffs.c b/fs/nffs/src/nffs.c index 83c75d1..7b5c128 100644 --- a/fs/nffs/src/nffs.c +++ b/fs/nffs/src/nffs.c @@ -747,8 +747,6 @@ nffs_init(void) return rc; } - NFFS_LOG(DEBUG, "nffs_init"); - fs_register(&nffs_ops); return 0; } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1dc3d2c8/mgmt/imgmgr/src/imgmgr.c ---------------------------------------------------------------------- diff --git a/mgmt/imgmgr/src/imgmgr.c b/mgmt/imgmgr/src/imgmgr.c index 8c1d2c9..32744e2 100644 --- a/mgmt/imgmgr/src/imgmgr.c +++ b/mgmt/imgmgr/src/imgmgr.c @@ -45,15 +45,6 @@ static const struct mgmt_handler imgr_nmgr_handlers[] = { .mh_read = NULL, .mh_write = imgr_upload }, - [IMGMGR_NMGR_ID_FILE] = { -#if MYNEWT_VAL(IMGMGR_FS) - .mh_read = imgr_file_download, - .mh_write = imgr_file_upload -#else - .mh_read = NULL, - .mh_write = NULL -#endif - }, [IMGMGR_NMGR_ID_CORELIST] = { #if MYNEWT_VAL(IMGMGR_COREDUMP) .mh_read = imgr_core_list, http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1dc3d2c8/mgmt/imgmgr/src/imgmgr_fs.c ---------------------------------------------------------------------- diff --git a/mgmt/imgmgr/src/imgmgr_fs.c b/mgmt/imgmgr/src/imgmgr_fs.c deleted file mode 100644 index 2685669..0000000 --- a/mgmt/imgmgr/src/imgmgr_fs.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "syscfg/syscfg.h" - -#if MYNEWT_VAL(IMGMGR_FS) - -#include <limits.h> -#include <assert.h> -#include <string.h> -#include <stdio.h> - -#include "os/os.h" -#include "os/endian.h" -#include "newtmgr/newtmgr.h" -#include "bootutil/image.h" -#include "fs/fs.h" -#include "cborattr/cborattr.h" -#include "bsp/bsp.h" -#include "mgmt/mgmt.h" - -#include "imgmgr/imgmgr.h" -#include "imgmgr_priv.h" - -int -imgr_file_download(struct mgmt_cbuf *cb) -{ - long long unsigned int off = UINT_MAX; - char tmp_str[IMGMGR_NMGR_MAX_NAME + 1]; - uint8_t img_data[IMGMGR_NMGR_MAX_MSG]; - const struct cbor_attr_t dload_attr[3] = { - [0] = { - .attribute = "off", - .type = CborAttrUnsignedIntegerType, - .addr.uinteger = &off - }, - [1] = { - .attribute = "name", - .type = CborAttrTextStringType, - .addr.string = tmp_str, - .len = sizeof(tmp_str) - }, - [2] = { 0 }, - }; - int rc; - uint32_t out_len; - struct fs_file *file; - CborError g_err = CborNoError; - CborEncoder *penc = &cb->encoder; - CborEncoder rsp; - - rc = cbor_read_object(&cb->it, dload_attr); - if (rc || off == UINT_MAX) { - rc = MGMT_ERR_EINVAL; - goto err; - } - - rc = fs_open(tmp_str, FS_ACCESS_READ, &file); - if (rc || !file) { - rc = MGMT_ERR_ENOMEM; - goto err; - } - - rc = fs_seek(file, off); - if (rc) { - rc = MGMT_ERR_EUNKNOWN; - goto err_close; - } - rc = fs_read(file, 32, img_data, &out_len); - if (rc) { - rc = MGMT_ERR_EUNKNOWN; - goto err_close; - } - - g_err |= cbor_encoder_create_map(penc, &rsp, CborIndefiniteLength); - - g_err |= cbor_encode_text_stringz(&rsp, "off"); - g_err |= cbor_encode_uint(&rsp, off); - - g_err |= cbor_encode_text_stringz(&rsp, "data"); - g_err |= cbor_encode_byte_string(&rsp, img_data, out_len); - - g_err |= cbor_encode_text_stringz(&rsp, "rc"); - g_err |= cbor_encode_int(&rsp, MGMT_ERR_EOK); - if (off == 0) { - rc = fs_filelen(file, &out_len); - g_err |= cbor_encode_text_stringz(&rsp, "len"); - g_err |= cbor_encode_uint(&rsp, out_len); - } - g_err |= cbor_encoder_close_container(penc, &rsp); - - fs_close(file); - if (g_err) { - return MGMT_ERR_ENOMEM; - } - return 0; - -err_close: - fs_close(file); -err: - mgmt_cbuf_setoerr(cb, rc); - return 0; -} - -int -imgr_file_upload(struct mgmt_cbuf *cb) -{ - uint8_t img_data[IMGMGR_NMGR_MAX_MSG]; - char file_name[IMGMGR_NMGR_MAX_NAME + 1]; - size_t img_len; - long long unsigned int off = UINT_MAX; - long long unsigned int size = UINT_MAX; - const struct cbor_attr_t off_attr[5] = { - [0] = { - .attribute = "off", - .type = CborAttrUnsignedIntegerType, - .addr.uinteger = &off, - .nodefault = true - }, - [1] = { - .attribute = "data", - .type = CborAttrByteStringType, - .addr.bytestring.data = img_data, - .addr.bytestring.len = &img_len, - .len = sizeof(img_data) - }, - [2] = { - .attribute = "len", - .type = CborAttrUnsignedIntegerType, - .addr.uinteger = &size, - .nodefault = true - }, - [3] = { - .attribute = "name", - .type = CborAttrTextStringType, - .addr.string = file_name, - .len = sizeof(file_name) - }, - [4] = { 0 }, - }; - CborError g_err = CborNoError; - CborEncoder *penc = &cb->encoder; - CborEncoder rsp; - int rc; - - rc = cbor_read_object(&cb->it, off_attr); - if (rc || off == UINT_MAX) { - rc = MGMT_ERR_EINVAL; - goto err; - } - - if (off == 0) { - /* - * New upload. - */ - imgr_state.upload.off = 0; - imgr_state.upload.size = size; - - if (!strlen(file_name)) { - rc = MGMT_ERR_EINVAL; - goto err; - } - if (imgr_state.upload.file) { - fs_close(imgr_state.upload.file); - imgr_state.upload.file = NULL; - } - rc = fs_open(file_name, FS_ACCESS_WRITE | FS_ACCESS_TRUNCATE, - &imgr_state.upload.file); - if (rc) { - rc = MGMT_ERR_EINVAL; - goto err; - } - } else if (off != imgr_state.upload.off) { - /* - * Invalid offset. Drop the data, and respond with the offset we're - * expecting data for. - */ - goto out; - } - - if (!imgr_state.upload.file) { - rc = MGMT_ERR_EINVAL; - goto err; - } - if (img_len) { - rc = fs_write(imgr_state.upload.file, img_data, img_len); - if (rc) { - rc = MGMT_ERR_EINVAL; - goto err_close; - } - imgr_state.upload.off += img_len; - if (imgr_state.upload.size == imgr_state.upload.off) { - /* Done */ - fs_close(imgr_state.upload.file); - imgr_state.upload.file = NULL; - } - } -out: - g_err |= cbor_encoder_create_map(penc, &rsp, CborIndefiniteLength); - g_err |= cbor_encode_text_stringz(&rsp, "rc"); - g_err |= cbor_encode_int(&rsp, MGMT_ERR_EOK); - g_err |= cbor_encode_text_stringz(&rsp, "off"); - g_err |= cbor_encode_uint(&rsp, imgr_state.upload.off); - g_err |= cbor_encoder_close_container(penc, &rsp); - if (g_err) { - return MGMT_ERR_ENOMEM; - } - return 0; - -err_close: - fs_close(imgr_state.upload.file); - imgr_state.upload.file = NULL; -err: - mgmt_cbuf_setoerr(cb, rc); - return 0; -} -#endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1dc3d2c8/mgmt/imgmgr/src/imgmgr_priv.h ---------------------------------------------------------------------- diff --git a/mgmt/imgmgr/src/imgmgr_priv.h b/mgmt/imgmgr/src/imgmgr_priv.h index 2e75e37..dbedd53 100644 --- a/mgmt/imgmgr/src/imgmgr_priv.h +++ b/mgmt/imgmgr/src/imgmgr_priv.h @@ -105,8 +105,6 @@ struct nmgr_jbuf; int imgr_boot2_read(struct mgmt_cbuf *); int imgr_boot2_write(struct mgmt_cbuf *); -int imgr_file_upload(struct mgmt_cbuf *); -int imgr_file_download(struct mgmt_cbuf *); int imgr_core_list(struct mgmt_cbuf *); int imgr_core_load(struct mgmt_cbuf *); int imgr_core_erase(struct mgmt_cbuf *); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1dc3d2c8/mgmt/mgmt/include/mgmt/mgmt.h ---------------------------------------------------------------------- diff --git a/mgmt/mgmt/include/mgmt/mgmt.h b/mgmt/mgmt/include/mgmt/mgmt.h index a6a1c99..9b79723 100644 --- a/mgmt/mgmt/include/mgmt/mgmt.h +++ b/mgmt/mgmt/include/mgmt/mgmt.h @@ -47,7 +47,8 @@ extern "C" { #define MGMT_GROUP_ID_LOGS (4) #define MGMT_GROUP_ID_CRASH (5) #define MGMT_GROUP_ID_SPLIT (6) -#define MGMT_GROUP_ID_RUN (7) +#define MGMT_GROUP_ID_RUN (7) +#define MGMT_GROUP_ID_FS (8) #define MGMT_GROUP_ID_PERUSER (64) /** http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1dc3d2c8/sys/log/full/src/log.c ---------------------------------------------------------------------- diff --git a/sys/log/full/src/log.c b/sys/log/full/src/log.c index 66b0fca..ab2e827 100644 --- a/sys/log/full/src/log.c +++ b/sys/log/full/src/log.c @@ -196,8 +196,10 @@ log_append(struct log *log, uint16_t module, uint16_t level, void *data, struct os_timeval tv; uint32_t idx; - /* Remember that a log entry has been written since boot. */ - log_written = 1; + if (log->l_log->log_type == LOG_TYPE_STORAGE) { + /* Remember that a log entry has been persisted since boot. */ + log_written = 1; + } if (log->l_name == NULL || log->l_log == NULL) { rc = -1;
