Kaydet (Commit) 69eb52fe authored tarafından Suleyman Poyraz's avatar Suleyman Poyraz

add system literals for cross-platform package managing

üst 75b4291d
## Module 'strutils'
----------------------------------------
# string/list/functional utility functions
* any (pred,seq)
* concat (l):
Concatenate a list of lists.
* every (pred,seq)
* human_readable_rate (size)
* human_readable_size (size)
* multisplit (str,chars):
Split str with any of the chars.
* prefix (a,b):
Check if sequence a is a prefix of sequence b.
* remove_prefix (a,b):
Remove prefix a from sequence b.
* same (l):
Check if all elements of a sequence are equal.
* strlist (l):
Concatenate string reps of l's elements.
* unzip (seq)
## Module 'dirutils'
----------------------------------------
# dirutils module provides basic directory functions.
* dir_size (dir)
Calculate the size of files under a directory.
* remove_dir (path)
Remove all content of a directory.
## Module 'sysutils'
----------------------------------------
# sysutils module provides basic system utilities.
* FileLock class:
Create a file lock for operations
* find_executable (exec_name)
* find the given executable in PATH
* getKernelOption (option):
Get a dictionary of args for the given kernel command line option
* touch (filename):
Update file modification date, create file if necessary
* capture ()
Capture output of the command without running a shell
* run ()
Run a command without running a shell, only output errors
* run_full ()
Run a command without running a shell, with full output
* run_quiet ()
Run the command without running a shell and no output
## Module 'csapi'
----------------------------------------
# csapi module provides basic system configuration utility function.
* atoi():
Convert a string into an integer.
* settimeofday():
Set system date.
* changeroute():
Change the route table.
## Module 'iniutils'
----------------------------------------
# initutils module provides ini style configuration file utils.
## Module 'diskutils'
----------------------------------------
# diskutils module provides EDD class to query device boot order and device information utilities.
## Module 'localedata'
----------------------------------------
# localedata module provides locale information.
## Module 'localedata'
----------------------------------------
# network utility functions
#-*- coding: utf-8 -*-
#
# Copyright (C) 2006-2010 TUBITAK/UEKAE
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#
_all__ = ["csapi",
"diskutils",
"fileutils",
"fstabutils",
"grubutils",
"iniutils",
"localedata",
"netutils",
"shellutils",
"strutils",
"sysutils"]
/*
** Copyright (c) 2005, TUBITAK/UEKAE
**
** This program is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the
** Free Software Foundation; either version 2 of the License, or (at your
** option) any later version. Please read the COPYING file.
*/
#include <Python.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <net/route.h>
#include <unistd.h>
#include <string.h>
static PyObject *
csapi_atoi(PyObject *self, PyObject *args)
{
char *str;
int i;
if (!PyArg_ParseTuple(args, "s", &str))
return NULL;
i = atoi(str);
return Py_BuildValue("i", i);
}
static PyObject *
csapi_settimeofday(PyObject *self, PyObject *args)
{
struct timeval tv;
double t;
if (!PyArg_ParseTuple(args, "d", &t))
return NULL;
tv.tv_sec = t;
tv.tv_usec = 0;
if (0 != settimeofday(&tv, NULL))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
csapi_changeroute(PyObject *self, PyObject *args)
{
struct rtentry route;
struct sockaddr_in gw, dst, mask;
int skfd, func;
char *gw_ip, *dst_ip, *mask_ip;
if (!PyArg_ParseTuple(args, "isss", &func, &gw_ip, &dst_ip, &mask_ip))
return NULL;
skfd = socket(AF_INET, SOCK_DGRAM, 0);
if (skfd < 0)
return NULL;
memset(&gw, 0, sizeof(struct sockaddr));
memset(&dst, 0, sizeof(struct sockaddr));
memset(&mask, 0, sizeof(struct sockaddr));
gw.sin_family = AF_INET;
dst.sin_family = AF_INET;
mask.sin_family = AF_INET;
gw.sin_addr.s_addr = inet_addr(gw_ip);
dst.sin_addr.s_addr = inet_addr(dst_ip);
mask.sin_addr.s_addr = inet_addr(mask_ip);
memset(&route, 0, sizeof(struct rtentry));
route.rt_dst = *(struct sockaddr *)&dst;
route.rt_gateway = *(struct sockaddr *)&gw;
route.rt_genmask = *(struct sockaddr *)&mask;
route.rt_flags = RTF_UP | RTF_GATEWAY;
if(ioctl(skfd, func, &route) < 0) {
return NULL;
}
close(skfd);
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef methods[] = {
{ "atoi", csapi_atoi, METH_VARARGS,
"Convert a string into an integer." },
{ "settimeofday", csapi_settimeofday, METH_VARARGS,
"Set system date." },
{ "changeroute", csapi_changeroute, METH_VARARGS,
"Change the route table."},
{ NULL, NULL, 0, NULL }
};
static struct PyModuleDef csapimodule ={
PyModuleDef_HEAD_INIT,
"csapi",
NULL,
-1,
methods
};
PyMODINIT_FUNC
PyInit_csapi(void)
{
return PyModule_Create(&csapimodule);
}
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#
"""diskutils module provides EDD class to query device boot order."""
import os
import struct
import binascii
import subprocess
sysfs_path = "/sys"
def sysValue(*paths):
path = os.path.join(sysfs_path, *paths)
f = open(path)
data = f.read().rstrip("\n")
f.close()
return data
def idsQuery(name, vendor, device):
f = file(name)
flag = 0
company = ""
for line in f.readlines():
if flag == 0:
if line.startswith(vendor):
flag = 1
company = line[5:].strip()
else:
if line.startswith("\t"):
if line.startswith("\t" + device):
return "%s - %s" % (line[6:].strip(), company)
elif not line.startswith("#"):
flag = 0
if company != "":
return "%s (%s)" % (company, device)
else:
return "Unknown (%s:%s)" % (vendor, device)
class EDD:
def __init__(self):
self.edd_dir = "/sys/firmware/edd"
self.edd_offset = 440
self.edd_len = 4
def blockDevices(self):
devices = []
for sysfs_dev in [dev for dev in os.listdir("/sys/block") \
if not dev.startswith(("fd", "loop", "ram", "sr"))]:
dev_name = os.path.basename(sysfs_dev).replace("!", "/")
devices.append("/dev/" + dev_name)
devices.sort()
return devices
def match_sys(self, _a):
b = struct.unpack("2s2s2s2s", _a)
return "0x"+b[3]+b[2]+b[1]+b[0]
def get_edd_sig(self, _n):
sigfile = "%s/int13_dev%s/mbr_signature" % (self.edd_dir, _n)
if os.path.exists(sigfile):
sig = open(sigfile).read().strip("\n")
else:
sig = None
return sig
def get_mbr_sig(self, _f):
f = open(_f)
f.seek(self.edd_offset)
a = f.read(self.edd_len)
f.close()
sig = self.match_sys(binascii.b2a_hex(a))
return sig
def list_edd_signatures(self):
sigs = {}
if os.path.exists(self.edd_dir):
for d in os.listdir(self.edd_dir):
bios_num = d[9:]
sig = self.get_edd_sig(bios_num)
if sig:
sigs[bios_num] = sig
else:
print("please insert edd module")
return sigs
def list_mbr_signatures(self):
sigs = {}
for d in self.blockDevices():
try:
sigs[self.get_mbr_sig(d)] = d
except IOError:
pass
return sigs
def getDeviceMap():
"""
Returns list of devices and their GRUB reprensentations.
Returns:
List of devices in ("hd0", "/dev/sda") format.
"""
# edd module is required
subprocess.call(["/sbin/modprobe", "edd"])
# get signatures
edd = EDD()
mbr_list = edd.list_mbr_signatures()
edd_list = edd.list_edd_signatures()
# sort keys
edd_keys = list(edd_list.keys())
edd_keys.sort()
devices = []
# build device map
i = 0
for bios_num in edd_keys:
edd_sig = edd_list[bios_num]
if edd_sig in mbr_list:
devices.append(("hd%s" % i, mbr_list[edd_sig]))
i += 1
return devices
def parseLinuxDevice(device):
"""
Parses Linux device address and returns disk, partition and their GRUB representations.
Arguments:
device: Linux device address (e.g. "/dev/sda1")
Returns:
None on error, (LinuxDisk, PartNo, GrubDev, GrubPartNo) on success
"""
for grub_disk, linux_disk in getDeviceMap():
if device.startswith(linux_disk):
part = device.replace(linux_disk, "", 1)
if part:
# If device address ends with a number,
# "p" is used before partition number
if part.startswith("p"):
grub_part = int(part[1:]) - 1
else:
grub_part = int(part) - 1
return linux_disk, part, grub_disk, grub_part
return None
def parseGrubDevice(device):
"""
Parses GRUB device address and returns disk, partition and their Linux representations.
Arguments:
device: GRUB device address (e.g. "(hd0,0)")
Returns:
None on error, (GrubDev, GrubPartNo, LinuxDisk, PartNo) on success
"""
try:
disk, part = device.split(",")
except ValueError:
return None
disk = disk[1:]
part = part[:-1]
if not part.isdigit():
return None
for grub_disk, linux_disk in getDeviceMap():
if disk == grub_disk:
linux_part = int(part) + 1
# If device address ends with a number,
# "p" is used before partition number
if linux_disk[-1].isdigit():
linux_part = "p%s" % linux_part
return grub_disk, part, linux_disk, linux_part
return None
def grubAddress(device):
"""
Translates Linux device address to GRUB address.
Arguments:
device: Linux device address (e.g. "/dev/sda1")
Returns:
None on error, GRUB device on success
"""
try:
linux_disk, linux_part, grub_disk, grub_part = parseLinuxDevice(device)
except (ValueError, TypeError):
return None
return "(%s,%s)" % (grub_disk, grub_part)
def linuxAddress(device):
"""
Translates GRUB device address to Linux address.
Arguments:
device: GRUB device address (e.g. "(hd0,0)")
Returns:
None on error, Linux device on success
"""
try:
grub_disk, grub_part, linux_disk, linux_part = parseGrubDevice(device)
except (ValueError, TypeError):
return None
return "%s%s" % (linux_disk, linux_part)
def getDeviceByLabel(label):
"""
Find Linux device address from it's label.
Arguments:
label: Device label
Returns:
None on error, Linux device on success
"""
fn = os.path.join("/dev/disk/by-label/%s" % label)
if os.path.islink(fn):
return "/dev/%s" % os.readlink(fn)[6:]
else:
return None
def getDeviceByUUID(uuid):
"""
Find Linux device address from it's UUID.
Arguments:
uuid: Device UUID
Returns:
None on error, Linux device on success
"""
fn = os.path.join("/dev/disk/by-uuid/%s" % uuid)
if os.path.islink(fn):
return "/dev/%s" % os.readlink(fn)[6:]
else:
return None
def getDevice(path):
"""
Gives device address of a path.
Arguments:
path: Directory path
Returns:
Device address (e.g. "/dev/sda1")
"""
for mount in os.popen("/bin/mount").readlines():
mount_items = mount.split()
if mount_items[2] == path:
if mount_items[0].startswith("/dev"):
return mount_items[0]
elif mount_items[0].startswith("LABEL="):
return getDeviceByLabel(mount_items[0].split('=', 1)[1])
elif mount_items[0].startswith("UUID="):
return getDeviceByUUID(mount_items[0].split('=', 1)[1])
def getPartitions():
"""
Returns list of all partitions.
Returns:
List of partitions which includes metadata of partition
or None (if blkid not found) e.g.:
{'/dev/sda1': {label :'PARDUS_ROOT', # (if exists)
uuid :'b3cf94b9-ed79-43e2-8b22-b9054a529f01',
fstype :'ext4'}, ... }
"""
if not os.path.exists('/sbin/blkid'):
return None
cmd = os.popen('/sbin/blkid')
result = {}
try:
for line in cmd.readlines():
partition = line.split(':')[0]
if partition not in result:
result[partition] = {}
for info in line.split():
if info.startswith('LABEL='):
result[partition]['label'] = info[6:].strip('"')
if info.startswith('UUID='):
result[partition]['uuid'] = info[5:].strip('"')
if info.startswith('TYPE='):
result[partition]['fstype'] = info[5:].strip('"')
except:
return None
else:
return result
def getRoot():
"""
Gives current root device address.
Returns:
Device address (e.g. "/dev/sda1")
"""
return getDevice("/")
def getBoot():
"""
Gives current boot device address.
Returns:
Device address (e.g. "/dev/sda1")
"""
if os.path.ismount("/boot"):
return getDevice("/boot")
else:
return getRoot()
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#
"""sysutils module provides basic file I/0 utility functions."""
import os
import time
import fcntl
class FileLock:
def __init__(self, filename):
self.filename = filename
self.fd = None
def lock(self, shared=False, timeout=-1):
_type = fcntl.LOCK_EX
if shared:
_type = fcntl.LOCK_SH
if timeout != -1:
_type |= fcntl.LOCK_NB
self.fd = os.open(self.filename, os.O_WRONLY | os.O_CREAT, 0o600)
if self.fd == -1:
raise IOError("Cannot create lock file")
while True:
try:
fcntl.flock(self.fd, _type)
return
except IOError:
if timeout > 0:
time.sleep(0.2)
timeout -= 0.2
else:
raise
def unlock(self):
fcntl.flock(self.fd, fcntl.LOCK_UN)
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018, Suleyman POYRAZ (Zaryob)
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#
"""/etc/fstab parser facility."""
import os
import subprocess
REMOTE_FS_LIST = [
"nfs",
"nfs4",
"cifs",
"ncpfs",
]
def get_device_by_label(label):
"""Returns the devpath associated with the given label."""
devpath = os.path.join("/dev/disk/by-label", label)
device = None
try:
device = os.path.basename(os.readlink(devpath))
except OSError:
pass
else:
return os.path.join("/dev", device)
def get_device_by_uuid(uuid):
"""Returns the devpath associated with the given UUID."""
devpath = os.path.join("/dev/disk/by-uuid", uuid)
device = None
try:
device = os.path.basename(os.readlink(devpath))
except OSError:
pass
else:
return os.path.join("/dev", device)
class FstabEntry(object):
"""Class representing an fstab entry."""
def __init__(self, entry):
"""
fs: First field in fstab file which determines either the device or
special filesystems like proc, sysfs, debugfs, etc.
mountpoint: The mountpoint to which the fs will be mounted.
type: Filesystem type. Can be none, ignore or VFSTYPE.
opts: Extra options to pass to the mount helper.
dump: Defines whether the filesystem will be dumped, optional field.
fsck: Defines whether the filesystem will be fsck'ed regularly.
"""
fields = entry.strip().split()
# If number of fields is < 6, either fs_freq or fs_passno is
# not given. So we omit them first
self.__fs_freq = None
self.__fs_passno = None
self.__fs_spec = fields[0]
self.__fs_file = fields[1]
self.__fs_vfstype = fields[2]
self.__fs_mntopts = fields[3]
if len(fields) == 6:
self.__fs_freq = fields[4]
self.__fs_passno = fields[5]
self.__volume_label = None
self.__volume_uuid = None
self.__device = None
# Entry properties
self.__is_swap = self.__fs_vfstype == "swap"
self.__entry_ignored = self.__fs_vfstype == "ignore"
self.__bind_move_mount = self.__fs_vfstype == "none"
if self.__fs_spec.startswith("UUID="):
self.__volume_uuid = self.__fs_spec.split("=")[-1]
self.__device = get_device_by_uuid(self.__volume_uuid)
if self.__fs_spec.startswith("LABEL="):
self.__volume_label = self.__fs_spec.split("=")[-1]
self.__device = get_device_by_label(self.__volume_label)
def __str__(self):
return """\
fs_spec: %s
fs_file: %s
fs_vfstype: %s
f