1

My requirement is to append some line of statement to the end of /etc/ssh/sshd_config file, to create some sftp users. Eg:

. . .

Match User sammyfiles
ForceCommand internal-sftp
PasswordAuthentication yes
ChrootDirectory /var/sftp
PermitTunnel no
AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no

NOTE: Above ". . ." shows the continuation of /etc/ssh/sshd_config file. The content below ". . ." is to be appended by my program. There can be several users in my case. I have taken one for example.

To achieve this, i have created a hello.txt file with content as mentioned below:

_Hello Python3!_

I am using below code to edit the file:

import mmap

with open("hello.txt", "r+") as f:
    # memory-map the file, size 0 means whole file
    map = mmap.mmap(f.fileno(), 0)
    # read content via standard file methods
    print(map.readline())  # prints "Hello Python!"
    # read content via slice notation
    print(map[:5])  # prints "Hello"
    # update content using slice notation;
    # note that new content must have same size
    map[14:] = " world!\n"
    # ... and read again using standard file methods
    map.seek(0)
    print(map.readline())  # prints "Hello  world!"
    # close the map
    map.close()

Expected result after cat hello.txt should be Hello Python3! world!

But i am getting error in both python2 and python3. For python3 code is below:

import mmap

with open("hello.txt", "r+") as f:
    # memory-map the file, size 0 means whole file
    map = mmap.mmap(f.fileno(), 0)
    # read content via standard file methods
    print(map.readline())  # prints "Hello Python!"
    # read content via slice notation
    print(map[:5])  # prints "Hello"
    # update content using slice notation;
    # note that new content must have same size
    map[14:] = " world!\n".encode()
    # ... and read again using standard file methods
    map.seek(0)
    print(map.readline())  # prints "Hello  world!"
    # close the map
    map.close()

The Error is below:

root@debian:/python_code# python2 mmaptest4.py
Hello Python3!

Hello
Traceback (most recent call last):
  File "mmaptest4.py", line 14, in <module>
    map[6:] = " world!\n"
IndexError: mmap slice assignment is wrong size

References:
1)https://docs.python.org/3/library/mmap.html
2)https://pymotw.com/2/mmap/

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
Abhishek Verma
  • 396
  • 4
  • 14
  • Tried to explain all my requirements. Kindly let me know if still i missed few details which is not making the scenario clear? I am new to use mmap, need help on this. Thank you. – Abhishek Verma Sep 13 '19 at 13:01
  • 7
    Out of curiosity, why do you need mmap to achieve this? – Chris Sep 13 '19 at 13:02
  • 1
    Possible dup of [Increasing a file's size using mmap](https://stackoverflow.com/questions/17393288/increasing-a-files-size-using-mmap) – DaveStSomeWhere Sep 13 '19 at 13:22
  • @Chris: Agreed. If it's just appending new data, where you don't need to do anything with existing data (don't need to read it, don't need to rewrite any of it), just `with open('/etc/ssh/sshd_config', 'a') as f:` followed by however many `f.write` calls you need should do the trick. – ShadowRanger Sep 13 '19 at 16:20
  • Also, minor note: Your Python 3 code definitely won't have the behavior you claim it has. `print(map.readline())` and `print(map[:5])` should end up outputting `b'Hello Python!'` and `b'Hello'` respectively (the `repr` of `bytes` objects, not the text from a `str`), because `mmap` is `bytes` oriented, and you never `decode`d the `bytes` `readline` and slicing returned. – ShadowRanger Sep 13 '19 at 16:25
  • The comments in the code are pretty clear by the way: `# note that new content must have same size`. The file is 14-15 bytes in size (depending on whether it has a newline at the end), you mapped 14-15 bytes, and you tried to assign to bytes 14-22. mmap requires that any slice assignment overwrite bytes in place, no growing or shrinking allowed. So at most you can overwrite one byte (index 14, if there is a newline in the file), you can't write more because the slice is effectively `map[14:15]` (the `15` being implicit due to that being how much data was mapped). – ShadowRanger Sep 13 '19 at 16:32
  • @Chris, As i am thinking that the size of config file may increase and opening the file with mmap and perform operation may help in adding to performance as it uses the operating system virtual memory system to access the data on the filesystem directly, instead of using normal I/O functions. I got to know this from link **2** under __References__ in the post. – Abhishek Verma Sep 14 '19 at 05:36

0 Answers0