Blob Blame History Raw
From 4f6611ed208b6029b4523ca7760a802e82b6a199 Mon Sep 17 00:00:00 2001
From: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
Date: Fri, 3 Apr 2020 20:06:48 +0530
Subject: [PATCH] Use temp file objects for temporary storage area

happen to see yet another issue after we switch to stringIO/bytesIO:

$ targetcli ls
'unicode' does not have the buffer interface

After which I felt like dealing with StringIO/BytesIO is like a
wild goose chase and we are after all attempting to deal with python
incompatible apis.

Technically speaking, the rtslib and configshell libraries are expecting a
string IO stream, but then for python2 with ByteIO() we are passing a
bytestream, and stringIO() is behaving a bit different in python2 than
expected as explained in my previous patch.

Lets simply switch to temporary file in the most secure manner possible,
opening files in string mode will assure the compatibility across the platforms.

At the end we wish to have a consistent behaviour across all python versions.

Signed-off-by: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
---
 daemon/targetclid | 26 +++++++++++++-------------
 scripts/targetcli |  3 ++-
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/daemon/targetclid b/daemon/targetclid
index 5df6ca2..329cede 100755
--- a/daemon/targetclid
+++ b/daemon/targetclid
@@ -26,19 +26,16 @@ from configshell_fb import ConfigShell
 from os import getuid, getenv, unlink
 from threading import Thread
 
+import os
 import sys
 import socket
 import struct
 import fcntl
 import signal
 import errno
+import tempfile
 
 
-if sys.version_info < (3, 0):
-    from io import BytesIO as StringIO
-else:
-    from io import StringIO
-
 err = sys.stderr
 
 class TargetCLI:
@@ -158,26 +155,29 @@ class TargetCLI:
                 connection.close()
                 still_listen = False
             else:
-                self.con._stdout = self.con._stderr = f = StringIO()
+                self.con._stdout = self.con._stderr = f = tempfile.NamedTemporaryFile(mode='w', delete=False)
                 try:
                     # extract multiple commands delimited with '%'
                     list_data = data.decode().split('%')
                     for cmd in list_data:
                         self.shell.run_cmdline(cmd)
                 except Exception as e:
-                    print(str(e).encode(), file=f) # push error to stream
+                    print(str(e), file=f) # push error to stream
 
                 # Restore
                 self.con._stdout = self.con_stdout_
                 self.con._stderr = self.con_stderr_
-                output = f.getvalue().encode()
-                var = struct.pack('i', len(output))
-                connection.sendall(var) # length of string
-                if len(output):
-                    connection.sendall(output) # actual string
-
                 f.close()
 
+                with open(f.name, 'r') as f:
+                    output = f.read()
+                    var = struct.pack('i', len(output))
+                    connection.sendall(var) # length of string
+                    if len(output):
+                        connection.sendall(output.encode()) # actual string
+
+                os.unlink(f.name)
+
 
 def usage():
     print("Usage: %s [--version|--help]" % sys.argv[0], file=err)
diff --git a/scripts/targetcli b/scripts/targetcli
index 04e5aba..f11ece4 100755
--- a/scripts/targetcli
+++ b/scripts/targetcli
@@ -154,8 +154,9 @@ def call_daemon(shell, req):
     # get the actual data in chunks
     while amount_received < amount_expected:
         data = sock.recv(1024)
+        data = data.decode()
         amount_received += len(data)
-        print(data.decode(), end ="")
+        print(data, end ="")
 
     sock.send(b'-END@OF@DATA-')
     sock.close()
-- 
2.21.0