Skip to content
Open
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
15 changes: 15 additions & 0 deletions models/yang/annotations/sonic-file-mgmt-annot.yang
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module sonic-file-mgmt-annot {
yang-version "1";

namespace "http://openconfig.net/Azure/sonic-file-mgmt-annot";
prefix "sfilemgmt-annot";

import sonic-extensions { prefix sonic-ext; }
import sonic-file-mgmt { prefix sfilemgmt; }

deviation /sfilemgmt:remove {
deviate add {
sonic-ext:rpc-callback "rpc_file_remove_cb";
}
}
}
31 changes: 31 additions & 0 deletions models/yang/sonic/sonic-file-mgmt.yang
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module sonic-file-mgmt {
namespace "http://github.com/Azure/sonic-file-mgmt";
prefix sfilemgmt;
yang-version 1.1;

organization
"SONiC";

contact
"SONiC";

description
"SONiC RPCs definition for file module";

revision 2025-01-23 {
description
"Initial revision.";
}

rpc remove {
description
"Remove removes the specified file from the target";
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

The rpc description text "Remove removes the specified file..." is grammatically awkward/redundant. Consider rewording to something like "Remove deletes the specified file from the target" to improve clarity in generated docs/clients.

Suggested change
"Remove removes the specified file from the target";
"Remove deletes the specified file from the target";

Copilot uses AI. Check for mistakes.
input {
leaf remote_file {
type string;
description
"Path of the file to remove";
}
}
}
}
61 changes: 61 additions & 0 deletions translib/transformer/xfmr_sonic_file_mgmt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
////////////////////////////////////////////////////////////////////////////////
// //
// Copyright 2025 Cisco. //
// //
// Licensed 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. //
// //
////////////////////////////////////////////////////////////////////////////////

package transformer

import (
"encoding/json"

"github.com/Azure/sonic-mgmt-common/translib/db"
"github.com/Azure/sonic-mgmt-common/translib/tlerr"
"github.com/golang/glog"
)

func init() {
XlateFuncBind("rpc_file_remove_cb", rpc_file_remove_cb)
}

var rpc_file_remove_cb RpcCallpoint = func(body []byte, _ [db.MaxDB]*db.DB) ([]byte, error) {
var err error
var output struct{}
var operand struct {
RemoteFile string `json:"remote_file"`
}
Comment on lines +36 to +38
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

RPC input unmarshalling doesn't match the JSON structure used by existing RPC callbacks (e.g., xfmr_showtech.go expects a top-level ":input" wrapper). With the current struct tags, operand.RemoteFile will remain empty for RFC7951-style payloads, causing the HostQuery to be invoked with an empty path. Update the operand struct to unmarshal the module-qualified input container and extract remote_file from there.

Copilot uses AI. Check for mistakes.
glog.Info("File Remove request - RPC callback")

err = json.Unmarshal(body, &operand)
if err != nil {
glog.Errorf("Error: Failed to parse rpc input; err=%v", err)
return nil, tlerr.InvalidArgs("Invalid rpc input")
}

result, _ := json.Marshal(&output)

host_output := HostQuery("file.remove", operand.RemoteFile)
if host_output.Err != nil {
glog.Errorf("Error: File Remove host Query failed: err=%v", host_output.Err)
return nil, host_output.Err
Comment on lines +47 to +52
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

remote_file is not validated after parsing. If the field is missing/empty (including due to input unmarshalling issues), the code will call HostQuery("file.remove", ""), which can lead to unintended behavior. Reject empty remote_file with tlerr.InvalidArgs (and ideally include which field is missing).

Copilot uses AI. Check for mistakes.
}
if host_output.Body[0].(int32) != 0 {
err = tlerr.New(host_output.Body[1].(string))
Comment on lines +54 to +55
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

The code assumes host_output.Body has at least two elements and that they are (int32, string). Since HostQuery returns a raw []interface{} from D-Bus, these direct index accesses and type assertions can panic if the host service returns a different signature or an empty body. Add length checks and safe type assertions (with an internal error if the response shape is unexpected).

Suggested change
if host_output.Body[0].(int32) != 0 {
err = tlerr.New(host_output.Body[1].(string))
if len(host_output.Body) < 2 {
err = tlerr.New("Internal error: unexpected response from file.remove host service")
glog.Errorf("Error: File Remove host Query returned invalid body length=%d", len(host_output.Body))
return nil, err
}
status, ok := host_output.Body[0].(int32)
if !ok {
err = tlerr.New("Internal error: unexpected response from file.remove host service")
glog.Errorf("Error: File Remove host Query returned invalid status type=%T", host_output.Body[0])
return nil, err
}
msg, ok := host_output.Body[1].(string)
if !ok {
err = tlerr.New("Internal error: unexpected response from file.remove host service")
glog.Errorf("Error: File Remove host Query returned invalid message type=%T", host_output.Body[1])
return nil, err
}
if status != 0 {
err = tlerr.New(msg)

Copilot uses AI. Check for mistakes.
glog.Errorf("Error: File Remove host Query failed: err=%v", err)
return nil, err
}

return result, nil
}