Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 3 for python-afs #5

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
15 changes: 8 additions & 7 deletions afs/_acl.pyx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# cython: c_string_type=str, c_string_encoding=ascii
from afs._util cimport *
from afs._util import pyafs_error
from afs._util import path_to_bytes

cdef extern from "afs/prs_fs.h":
enum:
Expand Down Expand Up @@ -34,15 +35,15 @@ USR7 = PRSFS_USR7

DEF MAXSIZE = 2048

def getAcl(char* dir, int follow=1):
def getAcl(dir, int follow=1):
cdef char space[MAXSIZE]
pioctl_read(dir, VIOCGETAL, space, MAXSIZE, follow)
pioctl_read(path_to_bytes(dir), VIOCGETAL, space, MAXSIZE, follow)
return space

def getCallerAccess(char *dir, int follow=1):
def getCallerAccess(dir, int follow=1):
cdef vcxstat2 stat
pioctl_read(dir, VIOC_GETVCXSTATUS2, <void*>&stat, sizeof(vcxstat2), follow)
pioctl_read(path_to_bytes(dir), VIOC_GETVCXSTATUS2, <void*>&stat, sizeof(vcxstat2), follow)
return stat.callerAccess

def setAcl(char* dir, char* acl, int follow=1):
pioctl_write(dir, VIOCSETAL, acl, NULL, 0, follow)
def setAcl(dir, char* acl, int follow=1):
pioctl_write(path_to_bytes(dir), VIOCSETAL, acl, NULL, 0, follow)
23 changes: 12 additions & 11 deletions afs/_fs.pyx
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
# cython: c_string_type=str, c_string_encoding=ascii
from afs._util cimport *
from afs._util import pyafs_error
from afs._util import path_to_bytes
import socket
import struct
import logging

log = logging.getLogger('afs._fs')

def whichcell(char* path):
def whichcell(path):
"""
whichcell(path) -> str

Determine which AFS cell a particular path is in.
"""
cdef char cell[MAXCELLCHARS]

pioctl_read(path, VIOC_FILE_CELL_NAME, cell, sizeof(cell), 1)
pioctl_read(path_to_bytes(path), VIOC_FILE_CELL_NAME, cell, sizeof(cell), 1)
return cell

def _lsmount(char* parent, char* path):
def _lsmount(parent, path):
"""
_lsmount(parent, path) -> str

Expand All @@ -26,10 +27,10 @@ def _lsmount(char* parent, char* path):
"""
cdef char mtpt[AFS_PIOCTL_MAXSIZE]

pioctl_write(parent, VIOC_AFS_STAT_MT_PT, path, mtpt, sizeof(mtpt), 1)
pioctl_write(path_to_bytes(parent), VIOC_AFS_STAT_MT_PT, path_to_bytes(path), mtpt, sizeof(mtpt), 1)
return mtpt

def _volume_status(char* path):
def _volume_status(path):
"""
_volume_status(path) -> tuple()

Expand All @@ -45,7 +46,7 @@ def _volume_status(char* path):
cdef char *name, *offmsg
cdef object py_volstat

pioctl_read(path, VIOCGETVOLSTAT, volstat_buf, sizeof(volstat_buf), 1)
pioctl_read(path_to_bytes(path), VIOCGETVOLSTAT, volstat_buf, sizeof(volstat_buf), 1)
volstat = <VolumeStatus *>volstat_buf
# You can't assign a char * to a temporary Python string
# (e.g. an array slice)
Expand All @@ -71,7 +72,7 @@ def _volume_status(char* path):
py_volstat['PartMaxBlocks'] = volstat.PartMaxBlocks
return (name, offmsg, py_volstat)

def _fid(char *path):
def _fid(path):
"""
_fid(path) -> dict()

Expand All @@ -80,15 +81,15 @@ def _fid(char *path):
cdef VenusFid vfid
cdef object py_fid

pioctl_read(path, VIOCGETFID, <char *>&vfid, sizeof(VenusFid), 1)
pioctl_read(path_to_bytes(path), VIOCGETFID, <char *>&vfid, sizeof(VenusFid), 1)
py_fid = dict()
py_fid['Volume'] = vfid.Fid.Volume
py_fid['Vnode'] = vfid.Fid.Vnode
py_fid['Unique'] = vfid.Fid.Unique
py_fid['Cell'] = vfid.Cell
return py_fid

def _whereis(char* path):
def _whereis(path):
"""
_whereis(path) -> list()

Expand All @@ -103,7 +104,7 @@ def _whereis(char* path):
cdef object py_result

py_result = list()
pioctl_read(path, VIOCWHEREIS, whereis_buf, sizeof(whereis_buf), 1)
pioctl_read(path_to_bytes(path), VIOCWHEREIS, whereis_buf, sizeof(whereis_buf), 1)
hosts = <afs_uint32 *>whereis_buf
for j in range(0, AFS_MAXHOSTS):
if hosts[j] == 0:
Expand Down
14 changes: 6 additions & 8 deletions afs/_pts.pyx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# cython: c_string_type=str, c_string_encoding=ascii
from afs._util cimport *
from afs._util import pyafs_error
import re
Expand Down Expand Up @@ -112,7 +113,6 @@ cdef class PTEntry:
cdef int _ptentry_from_c(PTEntry p_entry, prcheckentry * c_entry) except -1:
if p_entry is None:
raise TypeError
return -1

p_entry.flags = c_entry.flags
p_entry.id = c_entry.id
Expand All @@ -127,7 +127,6 @@ cdef int _ptentry_from_c(PTEntry p_entry, prcheckentry * c_entry) except -1:
cdef int _ptentry_to_c(prcheckentry * c_entry, PTEntry p_entry) except -1:
if p_entry is None:
raise TypeError
return -1

c_entry.flags = p_entry.flags
c_entry.id = p_entry.id
Expand Down Expand Up @@ -227,7 +226,9 @@ cdef class PTS:

self.cell = info.name

if sec > 0:
if sec == 0:
sc = rxnull_NewClientSecurityObject()
else:
strncpy(prin.cell, info.name, sizeof(prin.cell))
prin.instance[0] = 0
strncpy(prin.name, "afs", sizeof(prin.name))
Expand All @@ -237,6 +238,7 @@ cdef class PTS:
if sec >= 2:
# No really - we wanted authentication
pyafs_error(code)
sc = rxnull_NewClientSecurityObject()
sec = 0
else:
if sec == 3:
Expand All @@ -246,11 +248,7 @@ cdef class PTS:
sc = rxkad_NewClientSecurityObject(level, &token.sessionKey,
token.kvno, token.ticketLen,
token.ticket)

if sec == 0:
sc = rxnull_NewClientSecurityObject()
else:
sec = 2
sec = 2

memset(serverconns, 0, sizeof(serverconns))
for 0 <= i < info.numServers:
Expand Down
11 changes: 8 additions & 3 deletions afs/_util.pyx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
General PyAFS utilities, such as error handling
"""

# cython: c_string_type=str, c_string_encoding=ascii
import sys
import logging

Expand All @@ -17,7 +17,7 @@ cdef int _init = 0

# Function for "reading" data from a pioctl
# "outbuffer" will get populated with the data in question
cdef extern int pioctl_read(char *path, afs_int32 op, void *outbuffer,
cdef int pioctl_read(char *path, afs_int32 op, void *outbuffer,
unsigned short size, afs_int32 follow) except -1:
cdef ViceIoctl blob
cdef afs_int32 code
Expand All @@ -42,7 +42,7 @@ cdef extern int pioctl_read(char *path, afs_int32 op, void *outbuffer,
# Pass NULL for outbuffer in cases where we don't get anything
# back (e.g. VIOCSETAL)
# "outsize" will be ignored (forced to 0) if "outbuffer" is NULL
cdef extern int pioctl_write(char *path, afs_int32 op, char *inbuffer,
cdef int pioctl_write(char *path, afs_int32 op, char *inbuffer,
void *outbuffer, afs_int32 outsize,
afs_int32 follow) except -1:
cdef ViceIoctl blob
Expand Down Expand Up @@ -94,3 +94,8 @@ def pyafs_error(code):

if code != 0:
raise AFSException(code)

def path_to_bytes(path):
if isinstance(path, unicode):
return path.encode(sys.getfilesystemencoding(), 'surrogateescape')
return path
4 changes: 2 additions & 2 deletions afs/acl.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"none": "",
}

_reverseCanonical = dict((y, x) for (x, y) in _canonical.iteritems())
_reverseCanonical = dict((y, x) for (x, y) in _canonical.items())

_charBitAssoc = [
('r', READ),
Expand Down Expand Up @@ -119,7 +119,7 @@ def _clean(self):
def set(self, user, bitmask, negative=False):
"""Set the bitmask for a given user"""
if bitmask < 0 or bitmask > max(_char2bit.values()):
raise ValueError, "Invalid bitmask"
raise ValueError("Invalid bitmask")
if negative:
self.neg[user] = bitmask
else:
Expand Down
4 changes: 2 additions & 2 deletions afs/pts.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ class PTEntry(object):

groups: For users, this contains a collection class representing
the set of groups the user is a member of.
users: For groups, this contains a collection class representing
members: For groups, this contains a collection class representing
the members of this group.
"""
_attrs = ('id', 'name', 'count', 'flags', 'ngroups', 'nusers')
Expand Down Expand Up @@ -381,7 +381,7 @@ def getEntry(self, ident):
elt)
return ident

elif isinstance(ident, basestring):
elif isinstance(ident, (str, bytes)):
return PTEntry(self, name=ident)
else:
return PTEntry(self, id=ident)
Expand Down
63 changes: 34 additions & 29 deletions afs/tests/test__pts.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,50 @@
import os
from afs._pts import PTS
import nose
import unittest

def get_this_cell():
# Feel free to add more places ThisCell might show up
to_try = ['/private/var/db/openafs/etc/ThisCell',
'/opt/local/etc/openafs/ThisCell',
'/etc/openafs/ThisCell',
'/usr/vice/etc/ThisCell']
for f in to_try:
if os.path.isfile(f):
return open(f).read().strip()

def test_init_home_cell():
p = PTS()
assert p.cell == get_this_cell(), "PTS doesn't initialize to ThisCell when none specified."

def test_init_other_cell():
cell = 'zone.mit.edu'
p = PTS('zone.mit.edu')
assert p.cell == cell, "PTS doesn't initialize to provided cell."

def test_user_name_to_id():
p = PTS()
name = 'broder'
id = p._NameToId(name)
assert id == 41803, "PTS can't convert user name to ID."
assert p._IdToName(id) == name, "PTS can't convert user ID to name."

def test_group_name_to_id():
p = PTS()
name = 'system:administrators'
id = p._NameToId(name)
assert id == -204, "PTS can't convert group name to ID."
assert p._IdToName(id) == name, "PTS can't convert group ID to name."

def test_name_or_id():
p = PTS()
name = 'system:administrators'
id = -204
assert p._NameOrId(name) == id, "PTS._NameOrId can't identify name."
assert p._NameOrId(id) == id, "PTS._NameOrId can't identify ID."
class PTSTestCase(unittest.TestCase):

@unittest.skipUnless(get_this_cell(), "can't find ThisCell")
def test_init_home_cell(self):
p = PTS()
self.assertEqual(p.cell, get_this_cell(), "PTS doesn't initialize to ThisCell when none specified.")

def test_init_other_cell(self):
cell = 'zone.mit.edu'
p = PTS('zone.mit.edu')
self.assertEqual(p.cell, cell, "PTS doesn't initialize to provided cell.")

def test_user_name_to_id(self):
p = PTS()
name = 'broder'
id = p._NameToId(name)
self.assertEqual(id, 41803, "PTS can't convert user name to ID.")
self.assertEqual(p._IdToName(id), name, "PTS can't convert user ID to name.")

def test_group_name_to_id(self):
p = PTS()
name = 'system:administrators'
id = p._NameToId(name)
self.assertEqual(id, -204, "PTS can't convert group name to ID.")
self.assertEqual(p._IdToName(id), name, "PTS can't convert group ID to name.")

def test_name_or_id(self):
p = PTS()
name = 'system:administrators'
id = -204
self.assertEqual(p._NameOrId(name), id, "PTS._NameOrId can't identify name.")
self.assertEqual(p._NameOrId(id), id, "PTS._NameOrId can't identify ID.")

if __name__ == '__main__':
nose.main()
2 changes: 1 addition & 1 deletion afs/tests/test_acl.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def test_readRights():

def test_retrieve():
assert acl.ACL.retrieve('/afs/athena.mit.edu/contrib/bitbucket2').pos['system:anyuser'] & acl.WRITE
assert acl.ACL.retrieve('/afs/athena.mit.edu/user/t/a/tabbott').neg['yuranlu'] & acl.USR0
assert acl.ACL.retrieve('/afs/athena.mit.edu/astaff/project/macathena/.python-afs-test').neg['mrittenb'] & acl.USR0

def test_getCallerAccess():
assert acl.getCallerAccess('/afs/athena.mit.edu/contrib/bitbucket2') & acl.WRITE
Expand Down
7 changes: 4 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import os

for root in ['/Library/OpenAFS/Tools',
'/opt/local',
'/usr/local',
'/usr/afsws',
'/usr']:
Expand All @@ -20,11 +21,11 @@
'%s/include' % root]
library_dirs = ['%s/lib' % root,
'%s/lib/afs' % root]
if os.path.exists('%s/lib/libafsauthent_pic.a' % root):
if os.path.exists('%s/lib/libafsauthent_pic.a' % root) or os.path.exists('%s/lib64/libafsauthent_pic.a' % root):
suffix = '_pic'
else:
suffix = ''
libraries = ['afsauthent%s' % suffix, 'afsrpc%s' % suffix, 'resolv']
libraries = ['afsauthent%s' % suffix, 'afsrpc%s' % suffix, 'rokenafs', 'afshcrypto', 'resolv']
define_macros = [('AFS_PTHREAD_ENV', None)]

def PyAFSExtension(module, *args, **kwargs):
Expand All @@ -39,7 +40,7 @@ def PyAFSExtension(module, *args, **kwargs):

setup(
name="PyAFS",
version="0.2.2",
version="0.2.3",
description="PyAFS - Python bindings for AFS",
author="Evan Broder",
author_email="[email protected]",
Expand Down