return bRC_Error;
}
- // if (!backend.ctx->read_ack(ctx)){
- // strip_trailing_newline(cmd.c_str());
- // DMSG(ctx, DERROR, "Wrong backend response to %s command.\n", cmd.c_str());
- // JMSG(ctx, backend.ctx->jmsg_err_level(), "Wrong backend response to %s command.\n", cmd.c_str());
- // return bRC_Error;
- // }
-
int32_t status;
while ((status = backend.ctx->read_command(ctx, cmd)) != 0)
{
if (scan_parameter_str(cmd, "CHECK:", fname))
{
/* got accurate check query */
- metaplugin::accurate::perform_accurate_check(ctx, backend.ctx, fname, accurate_mode, accurate_mode_err);
+ metaplugin::accurate::perform_accurate_check(ctx, backend.ctx, fname, lname, accurate_mode, accurate_mode_err);
continue;
}
if (scan_parameter_str(cmd, "CHECKGET:", fname))
{
/* got accurate get query */
- metaplugin::accurate::perform_accurate_check_get(ctx, backend.ctx, fname, accurate_mode, accurate_mode_err);
+ metaplugin::accurate::perform_accurate_check_get(ctx, backend.ctx, fname, lname, accurate_mode, accurate_mode_err);
continue;
}
if (scan_parameter_str(cmd, "ACCEPT:", fname))
struct save_pkt sp;
memset(&sp, 0, sizeof(sp));
- metaplugin::attributes::Status status = metaplugin::attributes::read_attributes_command(ctx, backend.ctx, cmd, &sp);
+ metaplugin::attributes::Status status = metaplugin::attributes::read_attributes_command(ctx, backend.ctx, cmd, &sp, lname);
switch(status)
{
case metaplugin::attributes::Invalid_File_Type:
while (backend.ctx->read_command(ctx, cmd) > 0)
{
DMSG(ctx, DINFO, "read_command(2): %s\n", cmd.c_str());
- metaplugin::attributes::Status status = metaplugin::attributes::read_scan_stat_command(ctx, cmd, sp);
+
+ metaplugin::attributes::Status status = metaplugin::attributes::read_scan_stat_command(ctx, cmd, sp, lname);
switch (status)
{
+ case metaplugin::attributes::Status_Error:
+ return bRC_Error;
+
case metaplugin::attributes::Invalid_File_Type:
JMSG2(ctx, M_ERROR, "Invalid file type: %c for %s\n", sp->type, fname.c_str());
return bRC_Error;
reqparams--;
}
continue;
+
case metaplugin::attributes::Status_Handled:
reqparams--;
continue;
+
default:
break;
}
+
status = metaplugin::attributes::read_scan_tstamp_command(ctx, cmd, sp);
switch (status)
{
default:
break;
}
- if (scan_parameter_str(cmd, "LSTAT:", lname) == 1) {
+
+ if (scan_parameter_str(cmd, "LSTAT:", lname) == 1)
+ {
sp->link = lname.c_str();
reqparams--;
DMSG(ctx, DINFO, "LSTAT:%s\n", lname.c_str());
continue;
}
+
POOL_MEM tmp(PM_FNAME);
if (scan_parameter_str(cmd, "PIPE:", tmp)) {
/* handle PIPE command */
* @param accurate_mode_err when accurate mode error handled
* @return bRC bRC_OK when success, bRC_Error if not
*/
- bRC perform_accurate_check(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &fname, bool accurate_mode, bool &accurate_mode_err)
+ bRC perform_accurate_check(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &fname, POOL_MEM &lname, bool accurate_mode, bool &accurate_mode_err)
{
if (strlen(fname.c_str()) == 0){
// input variable is not valid
return bRC_Error;
}
- metaplugin::attributes::Status status = metaplugin::attributes::read_scan_stat_command(ctx, cmd, &sp);
+ metaplugin::attributes::Status status = metaplugin::attributes::read_scan_stat_command(ctx, cmd, &sp, lname);
if (status == metaplugin::attributes::Status_OK) {
if (ptcomm->read_command(ctx, cmd) < 0) {
// error
* @param accurate_mode_err when accurate mode error handled
* @return bRC bRC_OK when success, bRC_Error if not
*/
- bRC perform_accurate_check_get(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &fname, bool accurate_mode, bool &accurate_mode_err)
+ bRC perform_accurate_check_get(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &fname, POOL_MEM &lname, bool accurate_mode, bool &accurate_mode_err)
{
POOL_MEM cmd(PM_FNAME);
{
namespace accurate
{
- bRC perform_accurate_check(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &fname, bool accurate_mode, bool &accurate_mode_err);
- bRC perform_accurate_check_get(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &fname, bool accurate_mode, bool &accurate_mode_err);
+ bRC perform_accurate_check(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &fname, POOL_MEM &lname, bool accurate_mode, bool &accurate_mode_err);
+ bRC perform_accurate_check_get(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &fname, POOL_MEM &lname, bool accurate_mode, bool &accurate_mode_err);
} // namespace accurate
} // namespace metaplugin
* Status_Handled when data managed and TSTAMP command is not required
* Not_Command when it was not this command
*/
- Status read_scan_stat_command(bpContext *ctx, POOL_MEM &cmd, struct save_pkt *sp)
+ Status read_scan_stat_command(bpContext *ctx, POOL_MEM &cmd, struct save_pkt *sp, POOL_MEM &lname)
{
char type;
size_t size;
// handle stat(2) for this file
scan_parameter_str(cmd, "STAT:", param);
DMSG1(ctx, DDEBUG, "read_scan_stat_command():stat:%s\n", param.c_str());
- int rc = stat(param.c_str(), &sp->statp);
+ int rc = lstat(param.c_str(), &sp->statp);
if (rc < 0)
{
// error
case S_IFREG:
sp->type = FT_REG;
break;
+ case S_IFLNK:
+ {
+ sp->type = FT_LNK;
+ ssize_t rc = readlink(param.c_str(), lname.c_str(), lname.size());
+ if (rc < 0)
+ {
+ berrno be;
+ // error reading link value
+ DMSG2(ctx, DERROR, "Error reading link value. Err=%s (%d)", be.bstrerror(), be.code());
+ JMSG3(ctx, M_ERROR, "Error reading link value: %s, Err=%s (%d)", param.c_str(), be.bstrerror(), be.code());
+ return Status_Error;
+ }
+ lname.c_str()[rc] = '\0';
+ sp->link = lname.c_str();
+ DMSG1(ctx, DDEBUG, "read_scan_stat_command():readlink:%s\n", sp->link);
+ }
+ break;
default:
DMSG1(ctx, DERROR, "Unsupported file type: %o\n", sp->statp.st_mode & S_IFMT);
return Invalid_Stat_Packet;
* @param sp save packet to fill when file attributes handled
* @return Status Status_OK when file attributes commands handled, Status_Error on any error, other depends on enum.
*/
- Status read_attributes_command(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &cmd, struct save_pkt *sp)
+ Status read_attributes_command(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &cmd, struct save_pkt *sp, POOL_MEM &lname)
{
DMSG0(ctx, DDEBUG, "read_attributes_command()\n");
return Status_Error;
}
- Status status = read_scan_stat_command(ctx, cmd, sp);
+ Status status = read_scan_stat_command(ctx, cmd, sp, lname);
switch(status)
{
case Status_OK:
Status_Error,
} Status;
- Status read_scan_stat_command(bpContext *ctx, POOL_MEM &cmd, struct save_pkt *sp);
+ Status read_scan_stat_command(bpContext *ctx, POOL_MEM &cmd, struct save_pkt *sp, POOL_MEM &lname);
Status make_stat_command(bpContext *ctx, POOL_MEM &cmd, const restore_pkt *rp);
Status read_scan_tstamp_command(bpContext *ctx, POOL_MEM &cmd, struct save_pkt *sp);
Status make_tstamp_command(bpContext *ctx, POOL_MEM &cmd, const restore_pkt *rp);
- Status read_attributes_command(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &cmd, struct save_pkt *sp);
+ Status read_attributes_command(bpContext *ctx, PTCOMM *ptcomm, POOL_MEM &cmd, struct save_pkt *sp, POOL_MEM &lname);
} // attributes
} // metaplugin
int logfd;
pid_t mypid;
-char * buf;
-char * buflog;
+char *buf;
+char *buflog;
+char symlink_fname[32];
bool regress_error_plugin_params = false;
bool regress_error_start_job = false;
signal_eod();
write_plugin('I', "TEST18Data");
+ // now test `STAT:/path/to/file` using symbolic link
+ snprintf(symlink_fname, 32, "/tmp/passwd.%d", mypid);
+ symlink("/etc/passwd", symlink_fname);
+
+ // the file with external stat(2) packet
+ snprintf(buf, BIGBUFLEN, "FNAME:%s/java/%d/stat.symlink\n", PLUGINPREFIX, mypid);
+ write_plugin('C', buf);
+ snprintf(buf, BIGBUFLEN, "STAT:%s\n", symlink_fname);
+ write_plugin('C', buf);
+ write_plugin('I', "TEST18S");
+ signal_eod();
+ // here comes a file data contents
+ write_plugin('C', "DATA\n");
+ write_plugin('D', "/* here comes a file data contents */");
+ write_plugin('D', "/* here comes another file line */");
+ write_plugin('D', "/* here comes another file line */");
+ write_plugin('D', "/* here comes another file line */");
+ write_plugin('D', "/* here comes another file line */");
+ signal_eod();
+ write_plugin('I', "TEST18S_Data");
+
// this plugin object should be the latest item to backup
if (regress_backup_plugin_objects)
{
Term:
signal_term();
+ // LOG("#> Unlink symlink_fname.");
+ // unlink(symlink_fname);
LOG("#> Terminating backend.");
close(logfd);
free(buf);