1

While writing a python wrapper for the getmntent linux libc function, there is a strange difference between the behaviour between python 2.x and 3.x for the following code where most of the real work is done by the C library. Since I interface C code with python often, Can anyone explain or correct what is going wrong?

import ctypes
import sys

class mntent(ctypes.Structure):
    _fields_ = [("fsname", ctypes.c_char_p),
                ("dir", ctypes.c_char_p),
                ("type", ctypes.c_char_p),
                ("opts", ctypes.c_char_p),
                ("freq", ctypes.c_int),
                ("passno", ctypes.c_int)]

def main():
    libc = ctypes.cdll.LoadLibrary('libc.so.6')
    libc.getmntent.restype = ctypes.POINTER(mntent)
    libc.fopen.restype = ctypes.POINTER(ctypes.c_void_p)
    fp = libc.fopen('/etc/mtab', 'r')
    while True:
        mounts = libc.getmntent(fp)
        if bool(mounts) == False:
            libc.fclose(fp)
            break
        print("%30s   %10s    %s"%(mounts.contents.dir, mounts.contents.type, mounts.contents.fsname))

main()

The expected output contains all the mount devices listed with their types and mount points. On python 3.x it gives an empty list.

Luv
  • 386
  • 4
  • 15
  • 2
    In order to get a *libc* (which is already loaded) reference, you don't necessarily have to specify its name, you can use *None*. Check https://stackoverflow.com/questions/82831/how-do-i-check-whether-a-file-exists-without-exceptions/44661513#44661513 (the **Notes** at the end of *Section **#4.***). – CristiFati May 07 '19 at 14:30
  • This is brilliant, though not cause for the current problem but does improve code shippability. – Luv May 08 '19 at 05:33

1 Answers1

2

In Python 3, all strings are unicode, but libc.fopen() wants simple bytes strings as its arguments:

fp = libc.fopen(b'/etc/mtab', b'r')
Nils Werner
  • 34,832
  • 7
  • 76
  • 98