Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions native/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
- `c`: Added the `getInfo` RPC to retrieve the middleware version and build information. [#922](https://github.com/zowe/zowex/pull/922)
- `c`: Added a DCB abend exit for handling edge cases around PDS member open, write, and close operations. When an abend is encountered, it is either delayed or ignored (when applicable) and an error is returned gracefully via the diagnostic structure (`ZDIAG`) rather than terminating the process. Refer to [DCB abend exits](doc/dcb-abend-exit.md) for more information on how and when abends are handled. **Note:** In the event of an end-of-space (end-of-volume) abend, the operating system closes the DCB if the ignore request is honored from the abend exit. However, the abend might still percolate during end-of-volume `CLOSE` routines. An ESTAE/ESTAEX recovery routine should be used to gracefully handle these cases. [#839](https://github.com/zowe/zowex/issues/839)
- `c`: Fixed an issue where listing the members of a protected, partitioned data set resulted in an unclear error message. Now, the error messages are more specific and include information about insufficient permissions when applicable. [#297](https://github.com/zowe/zowex/issues/297)
- `c`: Fixed an issue where the `zowex ds create-member` command would overwrite an existing member. Added an `--overwrite` flag to the command that defaults to false. [#642](https://github.com/zowe/zowex/issues/642)

## `0.4.0`

Expand Down
23 changes: 15 additions & 8 deletions native/c/commands/ds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ int process_data_set_create_result(InvocationContext &context, ZDS *zds, int rc,
rc = zds_write(write_opts, data);
if (0 != rc)
{
context.output_stream() << "Error: could not write to data set: '" << dsn << "' rc: '" << rc << "'" << std::endl;
context.output_stream() << " Details: " << zds->diag.e_msg << std::endl;
context.error_stream() << "Error: could not write to data set: '" << dsn << "' rc: '" << rc << "'" << std::endl;
context.error_stream() << " Details: " << zds->diag.e_msg << std::endl;
Comment on lines +51 to +52
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for making sure we output to the right stream. We recently saw what could happen if we don't (npm pack 👀 ) 😋

return RTNCD_FAILURE;
}
context.output_stream() << "Data set and/or member created: '" << dsn << "'" << std::endl;
Expand Down Expand Up @@ -305,26 +305,32 @@ int handle_data_set_create_member(InvocationContext &context)
rc = zds_list_data_sets(&zds, dataset_name, entries);
if (RTNCD_WARNING < rc || entries.size() == 0)
{
context.output_stream() << "Error: could not create data set member: '" << dataset_name << "' rc: '" << rc << "'" << std::endl;
context.output_stream() << " Details:\n"
<< zds.diag.e_msg << std::endl;
context.error_stream() << "Error: could not create data set member: '" << dataset_name << "' rc: '" << rc << "'" << std::endl;
context.error_stream() << " Details: " << zds.diag.e_msg << std::endl;
return RTNCD_FAILURE;
}

bool overwrite = context.get<bool>("overwrite", false);
if (!overwrite && zds_member_exists(dataset_name, member_name))
{
context.error_stream() << "Warning: Data set member already exists: '" << dsn << "'" << std::endl;
return RTNCD_WARNING;
}

std::string data = "";
ZDSWriteOpts write_opts{.zds = &zds, .dsname = dsn};
rc = zds_write(write_opts, data);
if (0 != rc)
{
context.output_stream() << "Error: could not write to data set: '" << dsn << "' rc: '" << rc << "'" << std::endl;
context.output_stream() << " Details: " << zds.diag.e_msg << std::endl;
context.error_stream() << "Error: could not write to data set: '" << dsn << "' rc: '" << rc << "'" << std::endl;
context.error_stream() << " Details: " << zds.diag.e_msg << std::endl;
return RTNCD_FAILURE;
}
context.output_stream() << "Data set and/or member created: '" << dsn << "'" << std::endl;
}
else
{
context.output_stream() << "Error: could not find member name in dsn: '" << dsn << "'" << std::endl;
context.error_stream() << "Error: could not find member name in dsn: '" << dsn << "'" << std::endl;
return RTNCD_FAILURE;
}

Expand Down Expand Up @@ -1072,6 +1078,7 @@ void register_commands(parser::Command &root_command)
auto ds_create_member_cmd = command_ptr(new Command("create-member", "create member in data set"));
ds_create_member_cmd->add_alias("cre-m");
ds_create_member_cmd->add_positional_arg("dsn", "data set name with member specified", ArgType_Single, true);
ds_create_member_cmd->add_keyword_arg("overwrite", make_aliases("--overwrite", "--ow"), "overwrite existing member", ArgType_Flag, false, ArgValue(false));
ds_create_member_cmd->set_handler(handle_data_set_create_member);
data_set_cmd->add_command(ds_create_member_cmd);

Expand Down
31 changes: 16 additions & 15 deletions native/c/commands/uss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ int handle_uss_create_file(InvocationContext &context)
std::string file_path = context.get<std::string>("file-path", "");

long long mode = context.get<long long>("mode", 644);
bool overwrite = context.get<bool>("overwrite", false);

if (mode == 0)
{
Expand All @@ -78,12 +79,16 @@ int handle_uss_create_file(InvocationContext &context)
}

ZUSF zusf{};
rc = zusf_create_uss_file_or_dir(&zusf, file_path, cf_mode, false);
if (0 != rc)
rc = zusf_create_uss_file_or_dir(&zusf, file_path, cf_mode, CreateOptions(false, overwrite));
if (RTNCD_WARNING == rc)
{
context.error_stream() << "Warning: " << zusf.diag.e_msg << std::endl;
return RTNCD_WARNING;
}
else if (0 != rc)
{
context.error_stream() << "Error: could not create USS file: '" << file_path << "' rc: '" << rc << "'" << std::endl;
context.error_stream() << " Details:\n"
<< zusf.diag.e_msg << std::endl;
context.error_stream() << " Details: " << zusf.diag.e_msg << std::endl;
return RTNCD_FAILURE;
}

Expand Down Expand Up @@ -120,12 +125,11 @@ int handle_uss_create_dir(InvocationContext &context)
}

ZUSF zusf{};
rc = zusf_create_uss_file_or_dir(&zusf, file_path, cf_mode, true);
rc = zusf_create_uss_file_or_dir(&zusf, file_path, cf_mode, CreateOptions(true));
if (0 != rc)
{
context.error_stream() << "Error: could not create USS directory: '" << file_path << "' rc: '" << rc << "'" << std::endl;
context.error_stream() << " Details:\n"
<< zusf.diag.e_msg << std::endl;
context.error_stream() << " Details: " << zusf.diag.e_msg << std::endl;
return RTNCD_FAILURE;
}

Expand All @@ -145,8 +149,7 @@ int handle_uss_move(InvocationContext &context)
if (0 != rc)
{
context.error_stream() << "Error: could not move USS file or directory: '" << source << "' to '" << target << "' rc: '" << rc << "'" << std::endl;
context.error_stream() << " Details:\n"
<< zusf.diag.e_msg << std::endl;
context.error_stream() << " Details: " << zusf.diag.e_msg << std::endl;
return RTNCD_FAILURE;
}
context.output_stream() << "USS file or directory '" << source << "' moved to '" << target << "'" << std::endl;
Expand Down Expand Up @@ -457,8 +460,7 @@ int handle_uss_chmod(InvocationContext &context)
if (0 != rc)
{
context.error_stream() << "Error: could not chmod USS path: '" << file_path << "' rc: '" << rc << "'" << std::endl;
context.error_stream() << " Details:\n"
<< zusf.diag.e_msg << std::endl;
context.error_stream() << " Details: " << zusf.diag.e_msg << std::endl;
return RTNCD_FAILURE;
}

Expand All @@ -479,8 +481,7 @@ int handle_uss_chown(InvocationContext &context)
if (0 != rc)
{
context.error_stream() << "Error: could not chown USS path: '" << path << "' rc: '" << rc << "'" << std::endl;
context.error_stream() << " Details:\n"
<< zusf.diag.e_msg << std::endl;
context.error_stream() << " Details: " << zusf.diag.e_msg << std::endl;
return RTNCD_FAILURE;
}

Expand Down Expand Up @@ -512,8 +513,7 @@ int handle_uss_chtag(InvocationContext &context)
if (0 != rc)
{
context.error_stream() << "Error: could not chtag USS path: '" << path << "' rc: '" << rc << "'" << std::endl;
context.error_stream() << " Details:\n"
<< zusf.diag.e_msg << std::endl;
context.error_stream() << " Details: " << zusf.diag.e_msg << std::endl;
return RTNCD_FAILURE;
}

Expand Down Expand Up @@ -568,6 +568,7 @@ void register_commands(parser::Command &root_command)
auto uss_create_file_cmd = command_ptr(new Command("create-file", "create a USS file"));
uss_create_file_cmd->add_positional_arg(FILE_PATH);
uss_create_file_cmd->add_keyword_arg("mode", make_aliases("--mode"), "permissions", ArgType_Single, false);
uss_create_file_cmd->add_keyword_arg("overwrite", make_aliases("--overwrite", "--ow"), "overwrite existing file", ArgType_Flag, false, ArgValue(false));
uss_create_file_cmd->set_handler(handle_uss_create_file);
uss_group->add_command(uss_create_file_cmd);

Expand Down
6 changes: 4 additions & 2 deletions native/c/server/schemas/requests.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/**
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
Expand Down Expand Up @@ -53,7 +53,8 @@

struct CreateMemberRequest {};
ZJSON_SCHEMA(CreateMemberRequest,
FIELD_REQUIRED(dsname, STRING)
FIELD_REQUIRED(dsname, STRING),
FIELD_OPTIONAL(overwrite, BOOL)
);

struct DeleteDatasetRequest {};
Expand Down Expand Up @@ -234,7 +235,8 @@
ZJSON_SCHEMA(CreateFileRequest,
FIELD_OPTIONAL(permissions, STRING),
FIELD_REQUIRED(fspath, STRING),
FIELD_OPTIONAL(isDir, BOOL)
FIELD_OPTIONAL(isDir, BOOL),
FIELD_OPTIONAL(overwrite, BOOL)
);

struct DeleteFileRequest {};
Expand Down
94 changes: 63 additions & 31 deletions native/c/test/zowex.ds.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,42 +496,74 @@ void zowex_ds_tests()
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("Data set and/or member created");
});
it("should not overwrite existing members",
[&]() -> void
{
std::string ds = "'" + _ds.back() + "(TEST)'";
std::string response;
std::string command = zowex_command + " data-set create-member " + ds;
int rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("Data set and/or member created");

// TODO: https://github.com/zowe/zowex/issues/643
xit("should not overwrite existing members",
[&]() -> void
{
std::string ds = "'" + _ds.back() + "(TEST)'";
std::string response;
std::string command = zowex_command + " data-set create-member " + ds;
int rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("Data set and/or member created");
// Write "test" data
command = "echo test | " + zowex_command + " data-set write " + ds;
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("Wrote data to");

// Write "test" data
command = "echo test | " + zowex_command + " data-set write " + ds;
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("Wrote data to");
// Read "test" data to confirm
command = zowex_command + " data-set view " + ds;
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("test");

// Read "test" data to confirm
command = "echo test | " + zowex_command + " data-set view " + ds;
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("test");
// Create the same TEST member
command = zowex_command + " data-set create-member " + ds;
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).Not().ToBe(0);
Expect(response).ToContain("Warning");

// Create the same TEST member
command = "echo test | " + zowex_command + " data-set create-member " + ds;
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).Not().ToBe(0);
Expect(response).ToContain("ERROR");
// Read "test" data to confirm
command = zowex_command + " data-set view " + ds;
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("test");
});
it("should overwrite existing members if --overwrite is specified",
[&]() -> void
{
std::string ds = "'" + _ds.back() + "(TEST)'";
std::string response;
std::string command = zowex_command + " data-set create-member " + ds;
int rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("Data set and/or member created");

// Read "test" data to confirm
command = "echo test | " + zowex_command + " data-set view " + ds;
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("test");
});
// Write "test" data
command = "echo test | " + zowex_command + " data-set write " + ds;
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("Wrote data to");

// Read "test" data to confirm
command = zowex_command + " data-set view " + ds;
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("test");

// Create the same TEST member
command = zowex_command + " data-set create-member " + ds + " --overwrite";
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).ToContain("Data set and/or member created");

// Read to confirm data was overwritten
command = zowex_command + " data-set view " + ds;
rc = execute_command_with_output(command, response);
ExpectWithContext(rc, response).ToBe(0);
Expect(response).Not().ToContain("test");
});
});
describe("create-vb",
[&]() -> void
Expand Down
Loading
Loading