#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
"Solaris-specific library wrappers and functions"
from ctypes import *
import copy
import gettext
import errno
import platform
import os
try:
except:
try:
except:
_ = lambda x : x
) = range(1)
_msgs = {
LIBZFS_INIT_FAILURE: _('libzfs initialization failure')
}
#
#
# print 'platwidth = `%s\' | _syscall = `%s\'' % (_platwidth, _syscall)
dictresult = {}
# A very important side-effect of calling getattr() here is
# that the ctypes API creates copies of the data we're
# retrieving from the "structure". If it did not do that,
# calling libc APIs that use static data areas would cause
# the resulting Python strings to refer to the same storage
# area.
for x in [x for (x, y) in ctype_struct_instance._fields_]:
return dictresult
# ==============================[ statvfs ]===============================
"""From the manpage:
int statvfs(const char *restrict path, struct statvfs *restrict buf);
u_long f_bsize; /* preferred file system block size */
u_long f_frsize; /* fundamental filesystem block
(size if supported) */
fsblkcnt_t f_blocks; /* total # of blocks on file system
in units of f_frsize */
fsblkcnt_t f_bfree; /* total # of free blocks */
fsblkcnt_t f_bavail; /* # of free blocks avail to
non-privileged user */
fsfilcnt_t f_files; /* total # of file nodes (inodes) */
fsfilcnt_t f_ffree; /* total # of free file nodes */
fsfilcnt_t f_favail; /* # of inodes avail to
non-privileged user*/
u_long f_fsid; /* file system id (dev for now) */
char f_basetype[FSTYPSZ]; /* target fs type name,
null-terminated */
u_long f_flag; /* bit mask of flags */
u_long f_namemax; /* maximum file name length */
char f_fstr[32]; /* file system specific string */
if not 64-bit process
u_long f_filler[16]; /* reserved for future expansion */
endif
We always use the 64-bit statvfs variant (statvfs64 in 32-bit
processes and statvfs in 64-bit processes)
"""
("f_frsize", c_ulong),
("f_blocks", c_ulonglong),
("f_bfree", c_ulonglong),
("f_bavail", c_ulonglong),
("f_files", c_ulonglong),
("f_ffree", c_ulonglong),
("f_favail", c_ulonglong),
("f_fsid", c_ulong),
("f_flag", c_ulong),
("f_namemax", c_ulong),
"""Returns a dictionary whose members are the result of the Solaris
statvfs() call"""
result = StatVFS_Result()
return ctype2dict(result)
# ===========================[ mnttab functions ]============================
"Python ctype expression of the Solaris mnttab structure"
('mnt_mountp', c_char_p),
('mnt_fstype', c_char_p),
('mnt_mntopts', c_char_p),
('mnt_time', c_char_p)]
"Python ctype expression of the Solaris extmnttab structure"
('mnt_mountp', c_char_p),
('mnt_fstype', c_char_p),
('mnt_mntopts', c_char_p),
('mnt_time', c_char_p),
('mnt_major', c_uint),
('mnt_minor', c_uint)]
"""Decodes the following error codes from mnttab.h:
#define MNT_TOOLONG 1 /* entry exceeds MNT_LINE_MAX */
#define MNT_TOOMANY 2 /* too many fields in line */
#define MNT_TOOFEW 3 /* too few fields in line */
"""
if code == 1:
return 'Entry exceeds 1024 characters'
elif code == 2:
return 'Too many fields in line'
elif code == 3:
return 'Too few fields in line'
else:
return 'Unknown mnttab error'
global _mnttab_FILE
if _mnttab_FILE.value is None:
def getmntent():
"""Returns the next mnttab entry as a dictionary whose keys
are:
mnt_special
mnt_mountp
mnt_fstype
mnt_mntopts
mnt_time
or None if there are no more entries
"""
mntent = SolarisMntTab()
if r < 0: # EOF
return None
elif r > 0: # Error
raise IOError(r, mnttab_err_decode(r))
return ctype2dict(mntent)
"""Returns a mnttab entry matching the attributes passed in, or
None if no entry matches.
"""
mntent = SolarisMntTab()
if r < 0: # EOF
return None
elif r > 0:
raise IOError(r, mnttab_err_decode(r))
return ctype2dict(mntmatch)
def getextmntent():
"""Returns the next extmnttab entry as a dictionary whose keys
are:
mnt_special
mnt_mountp
mnt_fstype
mnt_mntopts
mnt_time
mnt_major
mnt_minor
or None if there are no more entries.
"""
if r < 0: # EOF
return None
elif r > 0:
raise IOError(r, mnttab_err_decode(r))
return ctype2dict(extmnt)
"""Rewinds the mnttab file to the beginning
if reopen is True, the mnttab file is closed, then reopened
"""
else:
def mnttab_close():
('time_mid', c_ushort),
('time_hi_and_version', c_ushort),
('clock_seq_hi_and_reserved', c_ubyte),
('clock_seq_low', c_ubyte),
]
try:
except ValueError:
return
if not isinstance(b, Sol_uuid):
return False
return False
return False
return True
s = '%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X'
return s
('p_size', c_ulonglong),
('p_guid', Sol_uuid),
('p_tag', c_ushort),
('p_flag', c_ushort),
('p_uguid', Sol_uuid),
]
('efi_nparts', c_uint),
('efi_part_size', c_uint),
('efi_lbasize', c_uint),
('efi_last_lba', c_ulonglong),
('efi_first_u_lba', c_ulonglong),
('efi_last_u_lba', c_ulonglong),
('efi_disk_uguid', Sol_uuid),
('efi_flags', c_uint),
('efi_reserved1', c_uint),
('efi_altern_lba', c_ulonglong),
('efi_parts', Dk_part)
]
"""Returns True if the character device node 'wholedisk' is a GPT-
partitioned disk.
"""
if rval >= 0:
return True
return False
"""
"""
import sys
partno = -1
if rval >= 0:
# Now comes the tricky part. Since Dk_gpt_t was declared with a single
# partition's worth of storage in efi_parts, we need to declare a new
# type that can hold all of the partitions actually stored in the dk_gpt_t
# returned from efi_alloc_and_read():
# Now look for the desired partition guid:
break
return partno
# =======================[libfdisk and DOS partitioning]=====================
"""
struct ipart {
unsigned char bootid; /* bootable or not */
unsigned char beghead; /* beginning head, sector, cylinder */
unsigned char begsect; /* begcyl is a 10-bit number. High 2 bits */
unsigned char begcyl; /* are in begsect. */
unsigned char systid; /* OS type */
unsigned char endhead; /* ending head, sector, cylinder */
unsigned char endsect; /* endcyl is a 10-bit number. High 2 bits */
unsigned char endcyl; /* are in endsect. */
uint32_t relsect; /* first sector relative to start of disk */
uint32_t numsect; /* number of sectors in partition */
};
"""
('beghead', c_ubyte),
('begsect', c_ubyte),
('begcyl', c_ubyte),
('systid', c_ubyte),
('endhead', c_ubyte),
('endsect', c_ubyte),
('endcyl', c_ubyte),
('relsect', c_uint),
('numsect', c_uint)
]
"""
typedef struct fdisk_disk_geom {
ushort_t phys_cyl;
ushort_t phys_sec;
ushort_t phys_heads;
ushort_t alt_cyl;
ushort_t virt_cyl;
ushort_t virt_sec;
ushort_t virt_heads;
ushort_t sectsize;
} fdisk_disk_geom_t;
"""
('phys_sec', c_ushort),
('phys_heads', c_ushort),
('alt_cyl', c_ushort),
('virt_cyl', c_ushort),
('virt_sec', c_ushort),
('virt_heads', c_ushort),
('sectsize', c_ushort)
]
pass
('abs_secnum', c_uint32),
('logdrive_offset', c_uint32),
('numsect', c_uint32),
('begcyl', c_uint32),
('endcyl', c_uint32),
('modified', c_int),
]
# on x86, the max is 32:
('dev_fd', c_int),
('op_flag', c_int),
('ext_beg_cyl', c_uint),
('ext_end_cyl', c_uint),
('ext_beg_sec', c_uint),
('ext_end_sec', c_uint),
('logical_drive_count', c_int),
('first_ebr_is_null', c_int),
('corrupt_logical_drives', c_int),
]
# from libfdisk.h:
try:
except OSError:
_libfdisk = None
"""Searches the main and extended partition tables for the specified
partition id (0 < id < 256).
"""
if not _libfdisk:
return -1
# XXX -
# If this is needed on large sector disks, read the first 512 bytes from
# the block device node and pass the ipart array to libfdisk_init().
if rval != 0:
return -1
part_index = -1
# First check the 4-slot main partition table
break
if rval != 0:
continue
break
return part_index
# ==============================[devlink walking]============================
# The walker function returns an int and takes 2 void *'s: the di_devlink_t,
# and the arg
# from <libdevinfo.h>:
"""Initialize the libdevinfo devlink interfaces"""
return hdl
"""Return a string that is the path corresponding to the devlink
passed in
"""
if r is None:
return r
"""Conduct a walk of all devlinks that patch the given pattern and
that pertain to the given path. Note that since ctypes passes
arguments to callbacks as 'int's, those arguments must be converted
into a useful Python type (passing a string, then reconstituting
a list from that string, for example).
"""
if r < 0:
"""Performs cleanup after use of the devlink interfaces"""
# ==========================[ libdevinfo subset ]=============================
# from <sys/devinfo_impl.h>:
# from src/lib/libdevinfo/device_info.h
# error return values for libdevinfo functions
-1: 'operation not successful',
-2: 'invalid argument',
-3: 'out of memory',
-4: 'permission denied - not root',
-5: 'operation not supported',
-6: 'exceeded maximum size of property value',
-7: 'request not found'
}
# The devfs_bootdev_get/set_list APIs are NOT public. DO NOT USE RELY
# ON THEIR STABILITY. There are no man pages for them FOR A REASON.
# perform no translation on the input device path
# convert the input device path only a prom device path; not an alias
# overwrite the existing entry in boot-device - default is to prepend
# from <sys/ddipropdefs.h>
"""Returns the type (block or char) of the special node whose minor
info is passed in
"""
def di_prom_init():
"""Initialize the prom for property access.
"""
return hdl
"""Initialize the device tree snapshot, starting from the device path
specified. flags are (DINFOPATH|DINFOCPYALL) by default.
"""
return hdl
"Returns the string name of the minor passed in"
"Returns the string name of the node passed in"
if r.value is None:
return rs
"""Returns the next minor node, relative to the minor passed in.
If minor isn't specified, or is passed in as None, the first minor
associated with the node is returned. None is returned when no
more minors exist.
"""
if r.value is None:
e = get_errno()
# NXIO is a special case-- an indicator of no more minors
return None
else:
return r
"""Perform a walk of all minor nodes attached to device nodes
in a subtree rooted at `root'. walkargs should be a simple Python
type, since it will need to be reconstituted in the walkfunc callback.
"""
print r
if r < 0:
def devfs_bootdev_get_list():
# No exception is raised on error, because there is no errno
# value that accompanies the failure
return None
i = 0
bootdevs = []
j = 0
logicals = []
j += 1
i += 1
"""Set the boot device list to the given list.
"""
return rv
if rv < 0:
return rv
propval = None
try:
# This is a bit tricky, since di_prop_lookup_strings returns ONE
# string with several embedded NUL terminators (if multiple strings
# are returned). To deal with this in ctypes, we use a pointer to
# a c_void_p as the last parameter and manually pull out each string
# To pull out each string, we cast the c_void_p to a c_char_p, which
# automatically gets us the first string (ctypes extracts it for us)
# To get subsequent strings, we need to manually index the pointer,
# adding the length of the previous string + 1 (since len() includes
# the NUL and one to get us past it).
if rv == 1:
elif rv > 1:
rv -= 1
while rv > 0:
rv -= 1
except IOError as e:
propval = None
else:
raise
finally:
return propval
"""
"""
if rv < 0:
return rv
"""
"""
"""
"""
"""
"""
return rv
"""
"""
while child:
return child
return None
"""
"""
phdl = di_prom_init()
propval = None
try:
for component in prop_components:
if component == '':
continue
except IOError as e:
finally:
return propval
# ==============================[ libfstyp ]==================================
"Returns a handle that can be used with other fstyp functions"
if r != 0:
return handle
if r == 1: # No Match Found
return None
elif r != 0:
# ================================[ isalist ]=================================
_isalist_cache = None
def isalist():
"Returns a list of ISAs supported on the currently-running system"
global _isalist_cache
if not _isalist_cache is None:
return _isalist_cache
if r < 0:
return _isalist_cache
_platform_name_cache = None
def platform_name():
global _platform_name_cache
if not _platform_name_cache is None:
return _platform_name_cache
if r < 0:
return b.value
_machine_name_cache = None
def machine_name():
global _machine_name_cache
if not _machine_name_cache is None:
return _machine_name_cache
if r < 0:
return b.value
# =================================[ libscf ]=================================
"Wrap for smf errors"
"Returns the current state of the specified service"
# Need to store the result in a c_void_p because if a c_char_p were
# specified as the return type, it would be automatically converted
# to a Python string and we'd love the original pointer value, which
# we need for the call to free()
return None
return result
"Enables the given smf service with the specified flags"
if ret == -1:
else:
return ret
# =================================[ libzfs ]=================================
c_int ]
# zprop_source_t values:
# ZFS_PROP values:
ZFS_PROP_CREATETXG, # not exposed to the user
ZFS_PROP_NAME, # not exposed to the user
ZFS_PROP_ISCSIOPTIONS, # not exposed to the user
ZFS_PROP_NUMCLONES, # not exposed to the user
ZFS_PROP_USERACCOUNTING, # not exposed to the user
ZFS_PROP_STMF_SHAREINFO, # not exposed to the user
ZFS_PROP_UNIQUE, # not exposed to the user
ZFS_PROP_OBJSETID, # not exposed to the user
ZFS_PROP_HASRECVD, # not exposed to the user
ZFS_PROP_SALT, # not exposed to the user
ZFS_PROP_SHARE2, # not exposed to the user
# ZPOOL_PROP values:
def libzfs_init():
if hdl is None:
if hdl is None:
if hdl is None:
if not ret is 0:
if get_source is True:
else:
srcp = None
srcp)
if not ret is 0:
if get_source is True:
else:
if get_source is True:
else:
srcp = None
if not ret is 0:
if get_source is True:
else:
"mnttab_open",
"mnttab_close",
"getmntent",
"getmntany",
"getextmntent",
"resetmnttab",
"DI_MAKE_LINK",
"DI_PRIMARY_LINK",
"DI_SECONDARY_LINK",
"DI_WALK_CONTINUE",
"DI_WALK_TERMINATE",
"di_devlink_init",
"di_devlink_path",
"di_devlink_walk",
"di_devlink_fini",
"DDI_NT_BLOCK",
"DINFOPATH",
"DINFOCPYALL",
"di_init",
"di_minor_is_block",
"di_minor_name",
"di_devfs_path",
"di_minor_next",
"di_walk_minor",
"di_fini",
"devfs_bootdev_get_list",
"fstyp_init",
"fstyp_ident",
"fstyp_fini",
"isalist",
"platform_name",
"machine_name",
"ZFS_TYPE_FILESYSTEM",
"ZFS_TYPE_POOL",
"ZPOOL_PROP_BOOTFS",
"libzfs_init",
"libzfs_fini",
"zfs_open",
"zfs_close",
"zpool_open",
"zpool_close",
"zfs_get_type",
"zfs_get_name",
"zfs_name_valid",
"zpool_get_physpath",
"zpool_get_prop",
"zpool_set_prop"]