You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hawq.apache.org by rl...@apache.org on 2016/06/21 02:41:34 UTC
[18/28] incubator-hawq git commit: HAWQ-837. Add python modules into
HAWQ code
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80e25b46/tools/bin/pythonSrc/PSI-0.3b2_gp/src/arch/sunos_process.c
----------------------------------------------------------------------
diff --git a/tools/bin/pythonSrc/PSI-0.3b2_gp/src/arch/sunos_process.c b/tools/bin/pythonSrc/PSI-0.3b2_gp/src/arch/sunos_process.c
new file mode 100644
index 0000000..596341c
--- /dev/null
+++ b/tools/bin/pythonSrc/PSI-0.3b2_gp/src/arch/sunos_process.c
@@ -0,0 +1,1021 @@
+/* The MIT License
+ *
+ * Copyright (C) 2008-2009 Floris Bruynooghe
+ *
+ * Copyright (C) 2008-2009 Abilisoft Ltd.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* SunOS implementation of the Process classes */
+
+
+#include <Python.h>
+
+
+/* We do not want to use the large file compilation environment as <procfs.h>
+ * doesn't play nice with that on ILP32 (32-bit machines), but <Python.h>, via
+ * pyconfig.h, sets the environment up for this so we need to reverse that.
+ * The transitional large file compilation environment (where the function
+ * sources are xxx64() instead and no mapping of the xxx symbols to xxx64
+ * symbols happens) is fine, so we leave _LARGEFILE64_SOURCE set. See the
+ * lfcompile(5) and lfcompile64(5) manpages for notes on mixing objects from
+ * different compilation environments: basically just don't share global
+ * variables across them. */
+#undef _FILE_OFFSET_BITS
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <procfs.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/proc.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <unistd.h>
+
+#if SUNOS5_MINOR >= 10
+#include <zone.h>
+#endif
+
+#include "psi.h"
+#include "process.h"
+#include "procfs_utils.h"
+#include "posix_utils.h"
+
+
+/***** Local declarations *****/
+static int parse_psinfo(struct psi_process *proci,
+ const pid_t pid,
+ psinfo_t **psinfop);
+static int parse_as(struct psi_process *proci,
+ const pid_t pid,
+ psinfo_t *psinfo);
+static int parse_usage(struct psi_process *proci, const pid_t pid);
+static double calc_pcpu(ushort_t pr_pctcpu);
+#if SUNOS5_MINOR >= 10
+static int set_cwd(struct psi_process *proci, const pid_t pid);
+static char *get_terminal(dev_t ttydev);
+static char *get_zonename(zoneid_t zoneid);
+#endif
+
+static int set_args_from_as(struct psi_process *proci,
+ const struct psinfo *psinfo,
+ const int asfd);
+static int set_args_from_argv(struct psi_process *proci,
+ const off_t *argv,
+ const psinfo_t *psinfo,
+ const int asfd);
+static int set_env_from_as(struct psi_process *proci,
+ const struct psinfo *psinfo,
+ const int asfd);
+static int set_envv_from_envp(struct psi_process *proci,
+ const int envc,
+ const off_t *envp,
+ const psinfo_t *psinfo,
+ const int asfd);
+static int set_exe(struct psi_process *proci,
+ const pid_t pid,
+ const psinfo_t *psinfo);
+static int set_args_env_from_fork(struct psi_process *proci,
+ const psinfo_t *psinfo);
+static char *find_sargs64(void);
+static int read_sargs64_pipe(struct psi_process *proci,
+ const psinfo_t *psinfo,
+ const int pipe);
+
+
+/***** Public interfaces from process.h. *****/
+
+
+/* The process status flags. */
+#define addflag(CONST) {"PROC_STATUS_"#CONST, CONST}
+struct psi_flag psi_arch_proc_status_flags[] = {
+ addflag(SIDL),
+ addflag(SRUN),
+ addflag(SSLEEP),
+ addflag(SSTOP),
+ addflag(SZOMB),
+#ifdef SONPROC
+ addflag(SONPROC),
+#endif
+#ifdef SWAIT
+ addflag(SWAIT),
+#endif
+ {NULL, 0}
+};
+
+
+/** Collect all information about a process
+ *
+ * The psinfo variable is so that /proc/<pid>/psinfo only needs to be read
+ * once.
+ */
+struct psi_process *
+psi_arch_process(const pid_t pid)
+{
+ struct psi_process *proci;
+ psinfo_t *psinfo;
+
+ if (procfs_check_pid(pid) < 0)
+ return NULL;
+ proci = psi_calloc(sizeof(struct psi_process));
+ if (proci == NULL)
+ return NULL;
+ if (parse_psinfo(proci, pid, &psinfo) < 0) {
+ psi_FREE(psinfo);
+ return psi_free_process(proci);
+ }
+ if (set_exe(proci, pid, psinfo) < 0) {
+ psi_free(psinfo);
+ return psi_free_process(proci);
+ }
+ if (parse_as(proci, pid, psinfo) < 0) {
+ psi_free(psinfo);
+ return psi_free_process(proci);
+ }
+ psi_free(psinfo);
+ if (parse_usage(proci, pid) < 0)
+ return psi_free_process(proci);
+#if SUNOS5_MINOR >= 10
+ if (set_cwd(proci, pid) < 0)
+ return psi_free_process(proci);
+#endif
+ return proci;
+}
+
+
+/***** Local functions *****/
+
+
+/** Parse information from /proc/<pid>/psinfo
+ *
+ * The `psinfop' argument will point to the `psinfo_t' structure or NULL. The
+ * caller *has* to call psi_free on it if it is non NULL. This means when an
+ * error arises in this function this function itself *should not* free the
+ * `psinfo' structure.
+ */
+static int
+parse_psinfo(struct psi_process *proci, const pid_t pid, psinfo_t **psinfop)
+{
+ psinfo_t *psinfo;
+ int bufsize;
+
+ bufsize = procfs_read_procfile((char**)&psinfo, pid, "psinfo");
+ *psinfop = psinfo;
+ if (bufsize == -1)
+ return -1;
+ if (bufsize == -2) {
+ proci->name_status = PSI_STATUS_PRIVS;
+ proci->argc_status = PSI_STATUS_PRIVS;
+ proci->command_status = PSI_STATUS_PRIVS;
+ proci->nthreads_status = PSI_STATUS_PRIVS;
+ proci->ppid_status = PSI_STATUS_PRIVS;
+ proci->pgrp_status = PSI_STATUS_PRIVS;
+ proci->sid_status = PSI_STATUS_PRIVS;
+ proci->ruid_status = PSI_STATUS_PRIVS;
+ proci->euid_status = PSI_STATUS_PRIVS;
+ proci->rgid_status = PSI_STATUS_PRIVS;
+ proci->egid_status = PSI_STATUS_PRIVS;
+ proci->euser_status = PSI_STATUS_PRIVS;
+ proci->ruser_status = PSI_STATUS_PRIVS;
+ proci->egroup_status = PSI_STATUS_PRIVS;
+ proci->rgroup_status = PSI_STATUS_PRIVS;
+ proci->vsz_status = PSI_STATUS_PRIVS;
+ proci->rss_status = PSI_STATUS_PRIVS;
+ proci->terminal_status = PSI_STATUS_PRIVS;
+ proci->pcpu_status = PSI_STATUS_PRIVS;
+ proci->start_time_status = PSI_STATUS_PRIVS;
+ proci->cputime_status = PSI_STATUS_PRIVS;
+ proci->exe_status = PSI_STATUS_PRIVS;
+ proci->status_status = PSI_STATUS_PRIVS;
+ proci->nice_status = PSI_STATUS_PRIVS;
+ proci->priority_status = PSI_STATUS_PRIVS;
+ proci->zoneid_status = PSI_STATUS_PRIVS;
+ proci->zonename_status = PSI_STATUS_PRIVS;
+ return 0;
+ }
+ if (bufsize != sizeof(psinfo_t)) {
+ PyErr_Format(PyExc_OSError,
+ "Unexpected psinfo file size: %d instead of %d",
+ bufsize, sizeof(psinfo_t));
+ return -1;
+ }
+ proci->name = (char *)psi_malloc(PRFNSZ); /* XXX or strlen()? */
+ if (proci->name == NULL)
+ return -1;
+ strcpy(proci->name, psinfo->pr_fname);
+ proci->name_status = PSI_STATUS_OK;
+ proci->argc = psinfo->pr_argc;
+ proci->argc_status = PSI_STATUS_OK;
+ proci->command = psi_strdup(psinfo->pr_psargs);
+ if (proci->command == NULL)
+ return -1;
+ proci->command_status = PSI_STATUS_OK;
+#if SUNOS5_MINOR >= 10
+ proci->nthreads = psinfo->pr_nlwp + psinfo->pr_nzomb;
+#else
+ proci->nthreads = psinfo->pr_nlwp;
+#endif
+ proci->nthreads_status = PSI_STATUS_OK;
+ proci->ppid = psinfo->pr_ppid;
+ proci->ppid_status = PSI_STATUS_OK;
+ proci->pgrp = psinfo->pr_pgid;
+ proci->pgrp_status = PSI_STATUS_OK;
+ proci->sid = psinfo->pr_sid;
+ proci->sid_status = PSI_STATUS_OK;
+ proci->ruid = psinfo->pr_uid;
+ proci->ruid_status = PSI_STATUS_OK;
+ proci->euid = psinfo->pr_euid;
+ proci->euid_status = PSI_STATUS_OK;
+ proci->rgid = psinfo->pr_gid;
+ proci->rgid_status = PSI_STATUS_OK;
+ proci->egid = psinfo->pr_egid;
+ proci->egid_status = PSI_STATUS_OK;
+ /* XXX rss & vsz are size_t on SunOS! */
+ proci->vsz = psinfo->pr_size * 1024;
+ proci->vsz_status = PSI_STATUS_OK;
+ proci->rss = (psinfo->pr_rssize) * 1024;
+ proci->rss_status = PSI_STATUS_OK;
+#if SUNOS5_MINOR >= 10
+ proci->terminal = get_terminal(psinfo->pr_ttydev);
+ if (proci->terminal == NULL && PyErr_Occurred() != NULL)
+ return -1;
+ proci->terminal_status = PSI_STATUS_OK;
+#endif
+ proci->pcpu = calc_pcpu(psinfo->pr_pctcpu);
+ proci->pcpu_status = PSI_STATUS_OK;
+ proci->start_time.tv_sec = psinfo->pr_start.tv_sec;
+ proci->start_time.tv_nsec = psinfo->pr_start.tv_nsec;
+ proci->start_time_status = PSI_STATUS_OK;
+ proci->cputime.tv_sec = psinfo->pr_time.tv_sec;
+ proci->cputime.tv_nsec = psinfo->pr_time.tv_nsec;
+ proci->cputime_status = PSI_STATUS_OK;
+ proci->status = psinfo->pr_lwp.pr_state;
+ proci->status_status = PSI_STATUS_OK;
+ proci->nice = psinfo->pr_lwp.pr_nice;
+ proci->nice_status = PSI_STATUS_OK;
+ proci->priority = psinfo->pr_lwp.pr_pri;
+ proci->priority_status = PSI_STATUS_OK;
+#if SUNOS5_MINOR >= 10
+ proci->zoneid = psinfo->pr_zoneid;
+ proci->zoneid_status = PSI_STATUS_OK;
+ proci->zonename = get_zonename(proci->zoneid);
+ if (proci->zonename == NULL)
+ return -1;
+ proci->zonename_status = PSI_STATUS_OK;
+#endif
+ *psinfop = psinfo;
+ return 0;
+}
+
+
+/** Parse the process address space: /proc/<pid>/as
+ *
+ * The argv, envc and envv slots are filled in from this.
+ *
+ * Care should be taken here as this is the address space image of the process
+ * it is not coverted to the data model of us (normally ILP32) like the rest
+ * of /proc, so it could be either ILP32 or LP64.
+ */
+static int
+parse_as(struct psi_process *proci, const pid_t pid, psinfo_t *psinfo)
+{
+ char *path;
+ int r;
+ int asfd;
+
+ if (psinfo->pr_dmodel != PR_MODEL_ILP32 &&
+ psinfo->pr_dmodel != PR_MODEL_LP64) {
+ /* Kernel threads/processes/LWPs. */
+ proci->argv_status = PSI_STATUS_NA;
+ proci->envc_status = PSI_STATUS_NA;
+ proci->envv_status = PSI_STATUS_NA;
+ return 0;
+ }
+#ifdef _ILP32
+ if (psinfo->pr_dmodel == PR_MODEL_LP64)
+ return set_args_env_from_fork(proci, psinfo);
+#endif
+ r = psi_asprintf(&path, "/proc/%d/as", pid);
+ if (r < 0)
+ return -1;
+ asfd = open(path, O_RDONLY);
+ if (asfd < 0) {
+ if (errno == EACCES || errno == EPERM) {
+ psi_free(path);
+ proci->argv_status = PSI_STATUS_PRIVS;
+ proci->envc_status = PSI_STATUS_PRIVS;
+ proci->envv_status = PSI_STATUS_PRIVS;
+ return 0;
+ } else if (errno == ENOENT) {
+ PyErr_SetFromErrnoWithFilename(PsiExc_NoSuchProcessError, path);
+ psi_free(path);
+ return -1;
+ } else {
+ PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
+ psi_free(path);
+ return -1;
+ }
+ }
+ psi_free(path);
+ if (set_args_from_as(proci, psinfo, asfd) < 0) {
+ close(asfd);
+ return -1;
+ }
+ if (set_env_from_as(proci, psinfo, asfd) < 0) {
+ close(asfd);
+ return -1;
+ }
+ close(asfd);
+ return 0;
+}
+
+
+static int
+parse_usage(struct psi_process *proci, const pid_t pid)
+{
+ prusage_t *prusage;
+ int bufsize;
+
+ bufsize = procfs_read_procfile((char**)&prusage, pid, "usage");
+ if (bufsize == -1)
+ return -1;
+ if (bufsize == -2) {
+ proci->utime_status = PSI_STATUS_PRIVS;
+ proci->stime_status = PSI_STATUS_PRIVS;
+ PyErr_Clear();
+ return 0;
+ }
+ if (bufsize != sizeof(prusage_t)) {
+ PyErr_Format(PyExc_OSError,
+ "Unexpected status file size: %d instead of %d",
+ bufsize, sizeof(prusage_t));
+ psi_free(prusage);
+ return -1;
+ }
+ proci->utime.tv_sec = prusage->pr_utime.tv_sec;
+ proci->utime.tv_nsec = prusage->pr_utime.tv_nsec;
+ proci->utime_status = PSI_STATUS_OK;
+ proci->stime.tv_sec = prusage->pr_stime.tv_sec;
+ proci->stime.tv_nsec = prusage->pr_stime.tv_nsec;
+ proci->stime_status = PSI_STATUS_OK;
+ psi_free(prusage);
+ return 0;
+}
+
+
+#if SUNOS5_MINOR >= 10
+static int
+set_cwd(struct psi_process *proci, const pid_t pid)
+{
+ char *path;
+ char *link;
+ int r;
+
+ r = psi_asprintf(&path, "/proc/%d/path/cwd", pid);
+ if (r == -1)
+ return -1;
+ r = psi_readlink(&link, path);
+ psi_free(path);
+ if (r == -2) {
+ PyErr_Clear();
+ proci->cwd_status = PSI_STATUS_PRIVS;
+ } else if (r < 0) {
+ procfs_check_pid(pid); /* OSError -> NoSuchProcessError if required */
+ return -1;
+ } else {
+ proci->cwd = psi_strdup(link);
+ psi_free(link);
+ proci->cwd_status = PSI_STATUS_OK;
+ }
+ return 0;
+}
+#endif
+
+
+#if SUNOS5_MINOR >= 10
+/* XXX For other solaris versions consider searching though /dev until the
+ * device is found like is done on AIX. */
+/** Find the terminal associated with ttydev
+ *
+ * This is derrived from solaris ps:
+ * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/ps/ps.c
+ * Unfortunately this only seems to work for SUNOS 5.10 and higher. Also
+ * _ttyname_dev() is probably an internal function, it appears in the symbol
+ * table of libc.so.1 however.
+ *
+ * The name of the terminal is returned or NULL. NULL is not always an error,
+ * it can just be there is no terminal (in which case python will see `None'
+ * so check with PyErr_Occurred().
+ */
+extern char *_ttyname_dev(dev_t, char *, size_t);
+
+static char *
+get_terminal(dev_t ttydev)
+{
+ char devname[TTYNAME_MAX];
+ char *rv;
+ int l;
+
+ if (ttydev == PRNODEV)
+ return NULL;
+ rv = _ttyname_dev(ttydev, devname, sizeof(devname));
+ if (rv == NULL)
+ return NULL;
+ l = strlen(devname);
+ rv = (char *)psi_malloc(l+1);
+ if (rv == NULL)
+ return NULL;
+ return strncpy(rv, devname, l+1);
+}
+#endif
+
+static double
+calc_pcpu(ushort_t pr_pctcpu)
+{
+ uint_t value = pr_pctcpu;
+
+ value = ((value*1000) + 0x7000) >> 15;
+ if (value >= 1000)
+ value = 999;
+ return (double)value/10.0;
+}
+
+
+#if SUNOS5_MINOR >= 10
+static char *
+get_zonename(zoneid_t zoneid)
+{
+ char zonename[ZONENAME_MAX];
+ char *name;
+ size_t reqsize;
+
+ reqsize = getzonenamebyid(zoneid, zonename, ZONENAME_MAX);
+ if (reqsize < 0)
+ return (char*)PyErr_SetFromErrno(PyExc_OSError);
+ name = psi_malloc(reqsize);
+ if (name == NULL)
+ return NULL;
+ strncpy(name, zonename, reqsize);
+ return name;
+}
+#endif
+
+
+/** Read bits in the process address space to extract `argv'
+ *
+ * This depends on the internal representation of the argv array: the base
+ * address of the entire array is pointed too by psinfo.pr_argv and this can't
+ * change, meaning that psinfo.pr_argc denotes the number of elements in the
+ * array. From this it is possible to create our own version of argv in the
+ * psi_process structure.
+ *
+ * Note that this function will never be called if we're a 32-bit Python
+ * looking at a 64-bit process so no need to detect this. This means off_t is
+ * always a valid way of pointing to an address in the address space.
+ */
+static int
+set_args_from_as(struct psi_process *proci,
+ const struct psinfo *psinfo,
+ const int asfd)
+{
+ off_t argvoff = (off_t)psinfo->pr_argv;
+ off_t *argv; /* not caddr_t due to casting issues */
+ caddr32_t *argv32;
+ ssize_t r;
+ int i;
+
+ /* First read in the array of pointers, this depends on the data model. */
+ if (psinfo->pr_dmodel == PR_MODEL_ILP32) {
+ argv32 = (caddr32_t*)psi_malloc(psinfo->pr_argc*sizeof(caddr32_t));
+ if (argv32 == NULL)
+ return -1;
+ r = pread(asfd, argv32, psinfo->pr_argc*sizeof(caddr32_t), argvoff);
+ if (r < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ psi_free(argv32);
+ return -1;
+ }
+ argv = (off_t*)psi_malloc(psinfo->pr_argc*sizeof(off_t));
+ if (argv == NULL) {
+ psi_free(argv32);
+ return -1;
+ }
+ for (i = 0; i < psinfo->pr_argc; i++)
+ argv[i] = (off_t)argv32[i];
+ psi_free(argv32);
+ } else { /* LP64 */
+ argv = (off_t*)psi_malloc(psinfo->pr_argc*sizeof(off_t));
+ if (argv == NULL)
+ return -1;
+ r = pread(asfd, argv, psinfo->pr_argc*sizeof(off_t), argvoff);
+ if (r < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ psi_free(argv);
+ return -1;
+ }
+ }
+
+ /* Now read each arg from the address space and place it into proci. */
+ i = set_args_from_argv(proci, argv, psinfo, asfd);
+ psi_free(argv);
+ if (i < 0)
+ return -1;
+ return 0;
+}
+
+
+/** Read the arguments from the address space pointed to by argv
+ *
+ * The pointers of where to read from in the address space (pointed to by the
+ * `asfd' file descriptor) are read from `argv' (which is of lenght
+ * `psinfo->pr_argc'). The result is stored in `proci->argv'.
+ *
+ * Note that proci->argv will get freed by psi_arch_process() in case of
+ * failure, so as soon as we assign an arch to it we don't have to worry about
+ * freeing it anymore in case of an error.
+ */
+static int
+set_args_from_argv(struct psi_process *proci,
+ const off_t *argv,
+ const psinfo_t *psinfo,
+ const int asfd)
+{
+ off_t argoff;
+ char *arg;
+ char *ptr;
+ int argsize;
+ ssize_t r;
+ int i;
+
+ proci->argv = (char**)psi_calloc(psinfo->pr_argc*sizeof(char*));
+ if (proci->argv == NULL)
+ return -1;
+ for (i = 0; i < psinfo->pr_argc; i++) {
+ argoff = argv[i];
+ argsize = 50;
+ arg = (char*)psi_malloc(argsize);
+ if (arg == NULL)
+ return -1;
+ ptr = arg;
+ *ptr = 'a';
+ while (*ptr != '\0') { /* read and grow buffer if required */
+ proci->argv[i] = arg;
+ r = pread(asfd, arg, argsize, argoff);
+ if (r < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ for (ptr = arg; ptr-arg < argsize-1; ptr++)
+ if (*ptr == '\0')
+ break;
+ if (*ptr != '\0') {
+ argsize += 50;
+ ptr = (char*)psi_realloc(arg, argsize);
+ if (ptr == NULL)
+ return -1;
+ arg = ptr;
+ }
+ }
+ }
+ proci->argv_status = PSI_STATUS_OK;
+ return 0;
+}
+
+
+
+/** Read bits in the process address space to extract `envp'
+ *
+ * This depends on the internal representation of the envp array: the base
+ * address of the entire array is pointed too by psinfo.pr_envp and POSIX
+ * defines that it is NULL terminated.
+ *
+ * Note that this function will never be called if we're a 32-bit Python
+ * looking at a 64-bit process so no need to detect this. This means off_t is
+ * always a valid way of pointing to an address in the address space.
+ *
+ * XXX This is too much code for one function.
+ */
+static int
+set_env_from_as(struct psi_process *proci,
+ const struct psinfo *psinfo,
+ const int asfd)
+{
+ off_t envpoff = (off_t)psinfo->pr_envp;
+ off_t *envp;
+ off_t *ptr;
+ caddr32_t *envp32;
+ caddr32_t *ptr32;
+ ssize_t r;
+ int array_size = 50;
+ int envc = 0;
+ int i;
+
+
+ /* First read in the array of pointers, this depends on the data model. */
+ if (psinfo->pr_dmodel == PR_MODEL_ILP32) {
+ envp32 = (caddr32_t*)psi_malloc(array_size*sizeof(caddr32_t));
+ if (envp32 == NULL)
+ return -1;
+ do {
+ r = pread(asfd, envp32, array_size*sizeof(caddr32_t), envpoff);
+ if (r < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ psi_free(envp32);
+ return -1;
+ }
+ ptr32 = envp32;
+ for (i = 0; i < array_size; i++) {
+ ptr32++;
+ if (*ptr32 == (caddr32_t)NULL) {
+ envc = i + 1;
+ break;
+ }
+ }
+ if (*ptr32 != (caddr32_t)NULL) { /* array was too small */
+ array_size += 50;
+ ptr32 = (caddr32_t*)psi_realloc(envp32,
+ array_size*sizeof(caddr32_t));
+ if (ptr32 == NULL) {
+ psi_free(envp32);
+ return -1;
+ }
+ envp32 = ptr32;
+ }
+ } while (*ptr32 != (caddr32_t)NULL);
+ envp = (off_t*)psi_malloc(envc*sizeof(off_t));
+ if (envp == NULL) {
+ psi_free(envp32);
+ return -1;
+ }
+ for (i = 0; i < envc; i++)
+ envp[i] = (off_t)envp32[i];
+ psi_free(envp32);
+ } else { /* LP64 */
+ envp = (off_t*)psi_malloc(array_size*sizeof(off_t));
+ if (envp == NULL)
+ return -1;
+ do {
+ r = pread(asfd, envp, array_size*sizeof(off_t), envpoff);
+ if (r < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ psi_free(envp);
+ return -1;
+ }
+ ptr = envp;
+ for (i = 0; i < array_size; i++) {
+ ptr++;
+ if (*ptr == (off_t)NULL) {
+ envc = i + 1;
+ break;
+ }
+ }
+ if (*ptr != (off_t)NULL) { /* array was too small */
+ array_size += 50;
+ ptr = (off_t*)psi_realloc(envp, array_size*sizeof(off_t));
+ if (ptr == NULL) {
+ psi_free(envp);
+ return -1;
+ }
+ envp = ptr;
+ }
+ } while (*ptr != (off_t)NULL);
+ }
+
+ /* Now we copy the environment vector into the psi_process structure. */
+ i = set_envv_from_envp(proci, envc, envp, psinfo, asfd);
+ psi_free(envp);
+ if (i < 0)
+ return -1;
+ proci->envc = envc;
+ proci->envc_status = PSI_STATUS_OK;
+ return 0;
+}
+
+
+static int
+set_envv_from_envp(struct psi_process *proci,
+ const int envc,
+ const off_t *envp,
+ const psinfo_t *psinfo,
+ const int asfd)
+{
+ off_t envoff;
+ char *env;
+ char *ptr;
+ ssize_t r;
+ int envsize;
+ int i;
+
+ proci->envv = (char**)psi_calloc(envc*sizeof(char*));
+ if (proci->envv == NULL)
+ return -1;
+ for (i = 0; i < envc; i++) {
+ envoff = envp[i];
+ envsize = 50;
+ env = (char*)psi_malloc(envsize);
+ if (env == NULL)
+ return -1;
+ ptr = env;
+ *ptr = 'a';
+ while (*ptr != '\0') { /* read and grow buffer if required */
+ proci->envv[i] = env;
+ r = pread(asfd, env, envsize, envoff);
+ if (r < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ for (ptr = env; ptr-env < envsize; ptr++)
+ if (*ptr == '\0')
+ break;
+ if (*ptr != '\0') {
+ envsize += 50;
+ ptr = (char*)psi_realloc(env, envsize);
+ if (ptr == NULL)
+ return -1;
+ env = ptr;
+ }
+ }
+ }
+ proci->envv_status = PSI_STATUS_OK;
+ return 0;
+}
+
+
+/** Set the exe and exe_status fields of the psi_process structure
+ *
+ * Returns -1 on failure, 0 on success.
+ */
+static int
+set_exe(struct psi_process *proci, const pid_t pid, const psinfo_t *psinfo)
+{
+#if SUNOS5_MINOR >= 10
+ char *fname;
+ char *link;
+ int r;
+
+ r = psi_asprintf(&fname, "/proc/%d/path/a.out", pid);
+ if (r == -1)
+ return -1;
+ r = psi_readlink(&link, fname);
+ psi_free(fname);
+ if (r < 0) {
+ PyErr_Clear();
+#endif
+ proci->exe = (char *)psi_malloc(PRFNSZ); /* XXX or strlen()? */
+ if (proci->exe == NULL)
+ return -1;
+ strcpy(proci->exe, psinfo->pr_fname);
+ proci->exe_status = PSI_STATUS_OK;
+#if SUNOS5_MINOR >= 10
+ } else {
+ proci->exe = link;
+ proci->exe_status = PSI_STATUS_OK;
+ }
+#endif
+ return 0;
+}
+
+
+/** Set argv, envc and envv by forking to 64-bit application
+ *
+ * This function gets called when we're a 32-bit Python trying to read the
+ * arguments and environment arrays from a 64-bit application. We can't do
+ * that ourself so we have to call sargs64.so which is a 64-bit helper
+ * program.
+ *
+ * sargs64.so must get the PID of the process as an argument and will write
+ * the results on it's standard output. The data format of result is:
+ * "arg0\0arg1\0...\0\0env0\0env1\0...\0\0". So you get a NULL-terminated
+ * array for the argument list, followed by a NULL terminated array of the
+ * environment. Once all information is sent sargs64.so will close the
+ * filedescriptor. Unless sargs64.so return 0 the output should not be
+ * trusted. If sargs64.so returns 2 then there was a permissions problem.
+ *
+ * Implementation notes
+ *
+ * The pipes[0] is read from in this process, pipes[1] gets written to in
+ * sargs64.so.
+ *
+ * We use fork1() (Solaris specific, not POSIX) since Solaris < 10 is not
+ * POSIX compliant and fork() there is an alias for forkall() which copies all
+ * the threads. And we don't want any threads in the child.
+ *
+ * XXX This function is too large.
+ */
+static int
+set_args_env_from_fork(struct psi_process *proci, const psinfo_t *psinfo)
+{
+ char *pid_str;
+ char *sargs64;
+ int pipes[2];
+ int child_stat;
+ pid_t child_pid;
+ int rv;
+
+ sargs64 = find_sargs64();
+ if (sargs64 == NULL)
+ return -1;
+ if (psi_asprintf(&pid_str, "%ld", (long)psinfo->pr_pid) < 0) {
+ psi_free(sargs64);
+ return -1;
+ }
+ if (pipe(pipes) == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ psi_free(sargs64);
+ psi_free(pid_str);
+ return -1;
+ }
+ child_pid = fork1();
+ if (child_pid == -1) { /* error */
+ PyErr_SetFromErrno(PyExc_OSError);
+ psi_free(sargs64);
+ psi_free(pid_str);
+ return -1;
+ } else if (child_pid == 0) { /* child */
+ if (close(pipes[0]) == -1)
+ exit(1);
+ if (dup2(pipes[1], 1) == -1)
+ exit(1);
+ if (close(pipes[1]) == -1)
+ exit(1);
+ execl(sargs64, "sargs64.so", pid_str, NULL);
+ exit(1);
+ } else { /* parent */
+ psi_free(sargs64);
+ psi_free(pid_str);
+ if (close(pipes[1]) == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ close(pipes[0]);
+ return -1;
+ }
+ rv = read_sargs64_pipe(proci, psinfo, pipes[0]);
+ if (close(pipes[0]) == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ if (waitpid(child_pid, &child_stat, 0) == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ if (!WIFEXITED(child_stat)) {
+ /* Someone changed the status of our child, clean it up. */
+ while (!WIFSIGNALED(child_stat) || !WIFEXITED(child_stat)) {
+ if (kill(child_pid, SIGTERM) == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ if (WIFSTOPPED(child_stat)) {
+ if (kill(child_pid, SIGCONT) == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ }
+ if (waitpid(child_pid, &child_stat, 0) == -1) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ }
+ PyErr_SetString(PyExc_OSError, "sargs64.so did not exit normally");
+ return -1;
+ }
+ if (WEXITSTATUS(child_stat) == 2) {
+ proci->argv_status = PSI_STATUS_PRIVS;
+ proci->envc_status = PSI_STATUS_PRIVS;
+ proci->envv_status = PSI_STATUS_PRIVS;
+ return 0;
+ } else if (WEXITSTATUS(child_stat) != 0) {
+ PyErr_SetString(PyExc_OSError, "sargs64.so failed");
+ procfs_check_pid(psinfo->pr_pid == 0);
+ return -1;
+ } else
+ return rv;
+ }
+}
+
+
+/** Return the path of sargs64.so
+ *
+ * On success the path of the sargs64.so executable is returned. Returns NULL
+ * on failure. The returned value must be freed using psi_free().
+ */
+static char *
+find_sargs64(void)
+{
+ PyObject *mod;
+ char *sargs64;
+ char *file;
+ char *p;
+ int l;
+
+ mod = PyImport_ImportModuleNoBlock("psi.process");
+ if (mod == NULL)
+ return NULL;
+ file = PyModule_GetFilename(mod);
+ Py_DECREF(mod);
+ if (file == NULL)
+ return NULL;
+ l = strlen(file);
+ sargs64 = (char *)psi_malloc(l + 11);
+ strncpy(sargs64, file, l+1);
+ p = strrchr(sargs64, '/') + 1;
+ strcpy(p, "sargs64.so");
+ p += 10;
+ *p = '\0';
+ return sargs64;
+}
+
+
+/** Read the data from sargs64.so via the pipe
+ *
+ * The format is described above in the set_args_env_from_fork() function.
+ * This sets the argv, argv_status, envv and envv_status slots in the procinfo
+ * structure if successful. If incomplete data is read an exception is set
+ * and -1 is returned.
+ */
+static int
+read_sargs64_pipe(struct psi_process *proci,
+ const psinfo_t *psinfo,
+ const int pipe)
+{
+ char *buf, *ptr, *envbuf;
+ ssize_t bytes;
+ int bufsize = 100;
+
+ /* Read buffer from pipe. */
+ buf = (char*)psi_malloc(bufsize + 2);
+ if (buf == NULL)
+ return -1;
+ ptr = buf;
+ while ((bytes = read(pipe, ptr, 100)))
+ if (bytes == 100) {
+ bufsize += 100;
+ ptr = psi_realloc(buf, bufsize + 2);
+ if (ptr == NULL) {
+ psi_free(buf);
+ return -1;
+ }
+ buf = ptr;
+ ptr = buf + bufsize - 100;
+ }
+ buf[bufsize-1] = '\0'; /* Ensure buffer ends in '\0\0' */
+ buf[bufsize] = '\0';
+
+ /* Parse argv. */
+ ptr = strchr(buf, '\0');
+ while (*(ptr+1) != '\0') {
+ ptr = strchr(ptr+1, '\0');
+ if (ptr == NULL) {
+ psi_free(buf);
+ PyErr_SetString(PyExc_OSError, "Invalid data from sargs64.so");
+ return -1;
+ }
+ }
+ proci->argc = psi_strings_count(buf, ptr-buf+1);
+ proci->argv = psi_strings_to_array(buf, proci->argc);
+ proci->argc_status = PSI_STATUS_OK;
+ proci->argv_status = PSI_STATUS_OK;
+
+ /* Parse envv. */
+ envbuf = ptr + 2;
+ if (envbuf-buf > bufsize-2) {
+ psi_free(buf);
+ PyErr_SetString(PyExc_OSError, "Invalid data from sargs64.so");
+ return -1;
+ }
+ ptr = strchr(envbuf, '\0');
+ while (*(ptr+1) != '\0') {
+ ptr = strchr(ptr+1, '\0');
+ if (ptr == NULL) {
+ psi_free(buf);
+ PyErr_SetString(PyExc_OSError, "Invalid data from sargs64.so");
+ return -1;
+ }
+ }
+ proci->envc = psi_strings_count(envbuf, ptr-envbuf+1);
+ proci->envv = psi_strings_to_array(envbuf, proci->envc);
+ proci->envc_status = PSI_STATUS_OK;
+ proci->envv_status = PSI_STATUS_OK;
+ psi_free(buf);
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80e25b46/tools/bin/pythonSrc/PSI-0.3b2_gp/src/arch/sunos_psi.c
----------------------------------------------------------------------
diff --git a/tools/bin/pythonSrc/PSI-0.3b2_gp/src/arch/sunos_psi.c b/tools/bin/pythonSrc/PSI-0.3b2_gp/src/arch/sunos_psi.c
new file mode 100644
index 0000000..e59dafb
--- /dev/null
+++ b/tools/bin/pythonSrc/PSI-0.3b2_gp/src/arch/sunos_psi.c
@@ -0,0 +1,66 @@
+/* The MIT License
+ *
+ * Copyright (C) 2009 Floris Bruynooghe
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* SunOS implementations of the _psi non-POSIX functions */
+
+
+#include <Python.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <time.h>
+#include <utmpx.h>
+
+#include "psifuncs.h"
+#include "posix_utils.h"
+
+
+/***** Public functions *****/
+
+
+int
+arch_boottime(struct timespec *boottime)
+{
+ return posix_utmpx_boottime(boottime);
+}
+
+
+int
+arch_uptime(struct timespec *uptime)
+{
+ struct timespec utbt;
+ struct timespec now;
+ struct timeval tvnow;
+
+ if (posix_utmpx_boottime(&utbt) < 0)
+ return -1;
+ if (gettimeofday(&tvnow, NULL) < 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ now.tv_sec = tvnow.tv_sec;
+ now.tv_nsec = tvnow.tv_usec * 1000;
+ *uptime = posix_timespec_subtract(&now, &utbt);
+ return 0;
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80e25b46/tools/bin/pythonSrc/PSI-0.3b2_gp/src/archmodule.c
----------------------------------------------------------------------
diff --git a/tools/bin/pythonSrc/PSI-0.3b2_gp/src/archmodule.c b/tools/bin/pythonSrc/PSI-0.3b2_gp/src/archmodule.c
new file mode 100644
index 0000000..38b6934
--- /dev/null
+++ b/tools/bin/pythonSrc/PSI-0.3b2_gp/src/archmodule.c
@@ -0,0 +1,210 @@
+/* The MIT License
+ *
+ * Copyright (C) 2008-2009 Floris Bruynooghe
+ *
+ * Copyright (C) 2008-2009 Abilisoft Ltd.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* The psi.arch module */
+
+
+#include <Python.h>
+
+#include "psi.h"
+#include "arch.h"
+
+
+/* Declarations (we need these since we use -Wmissing-declarations) */
+#ifdef PY3K
+PyMODINIT_FUNC PyInit_arch(void);
+#else
+PyMODINIT_FUNC initarch(void);
+#endif
+
+
+/* Re-declare these as non-extern since we're providing the symbols */
+PyObject *PsiExc_AttrNotAvailableError = NULL;
+PyObject *PsiExc_AttrInsufficientPrivsError = NULL;
+PyObject *PsiExc_AttrNotImplementedError = NULL;
+
+
+/* More constants */
+static char MODULE_NAME[] = "psi.arch";
+PyDoc_STRVAR(MODULE_DOC, "Module for system architecture information");
+
+
+/* The psi.arch.arch_type() function */
+static PyObject *
+psi_arch_type(PyObject *self, PyObject *args)
+{
+ return PsiArch_New();
+}
+
+
+/** Finalise the types
+ *
+ * Calls PyType_Ready() and does anything else required.
+ */
+static int
+prepare_types(void)
+{
+ if (PyType_Ready(&PsiArchBase_Type) < 0)
+ return -1;
+ if (PyType_Ready(&PsiArchLinux_Type) < 0)
+ return -1;
+ if (PyType_Ready(&PsiArchSunOS_Type) < 0)
+ return -1;
+ if (PyType_Ready(&PsiArchDarwin_Type) < 0)
+ return -1;
+ if (PyType_Ready(&PsiArchAIX_Type) < 0)
+ return -1;
+ Py_INCREF(&PsiArchBase_Type);
+ Py_INCREF(&PsiArchLinux_Type);
+ Py_INCREF(&PsiArchSunOS_Type);
+ Py_INCREF(&PsiArchDarwin_Type);
+ Py_INCREF(&PsiArchAIX_Type);
+ return 0;
+}
+
+
+/** Initialise the global exceptions
+ *
+ * If this function fails the modinit function will Py_XDECREF the exceptions,
+ * so no need to do that here.
+ */
+static int
+init_exceptions(void)
+{
+ PyObject *_psimod;
+
+ _psimod = PyImport_ImportModule("psi._psi");
+ if (_psimod == NULL)
+ return -1;
+ PsiExc_AttrNotAvailableError = PyObject_GetAttrString(
+ _psimod, "AttrNotAvailableError");
+ if (PsiExc_AttrNotAvailableError == NULL)
+ goto error;
+ PsiExc_AttrInsufficientPrivsError = PyObject_GetAttrString(
+ _psimod, "AttrInsufficientPrivsError");
+ if (PsiExc_AttrInsufficientPrivsError == NULL)
+ goto error;
+ PsiExc_AttrNotImplementedError = PyObject_GetAttrString(
+ _psimod, "AttrNotImplementedError");
+ if (PsiExc_AttrNotImplementedError == NULL)
+ goto error;
+ Py_DECREF(_psimod);
+ return 0;
+
+ error:
+ Py_DECREF(_psimod);
+ return -1;
+}
+
+
+/* Add all the objects to the module */
+static int
+add_module_objects(PyObject *mod)
+{
+ if (PyModule_AddObject(mod, "ArchBase",
+ (PyObject *)&PsiArchBase_Type) < 0)
+ return -1;
+ if (PyModule_AddObject(mod, "ArchLinux",
+ (PyObject *)&PsiArchLinux_Type) < 0)
+ return -1;
+ if (PyModule_AddObject(mod, "ArchSunOS",
+ (PyObject *)&PsiArchSunOS_Type) < 0)
+ return -1;
+ if (PyModule_AddObject(mod, "ArchDarwin",
+ (PyObject *)&PsiArchDarwin_Type) < 0)
+ return -1;
+ if (PyModule_AddObject(mod, "ArchAIX",
+ (PyObject *)&PsiArchAIX_Type) < 0)
+ return -1;
+ return 0;
+}
+
+
+static PyMethodDef arch_methods[] = {
+ {"arch_type", psi_arch_type, METH_NOARGS,
+ PyDoc_STR("Return an object representing the current architecture type")},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+
+#ifdef PY3K
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT, /* m_base */
+ MODULE_NAME, /* m_name */
+ MODULE_DOC, /* m_doc */
+ -1, /* m_size */
+ arch_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL /* m_free */
+};
+#endif
+
+
+/* Some defines to make the module init function readable */
+#ifdef PY3K
+#define MODFUNC PyInit_arch
+#define RETURN(VAR) return VAR
+#else
+#define MODFUNC initarch
+#define RETURN(VAR) return
+#endif
+
+
+/* Returns the psi.arch module */
+PyMODINIT_FUNC
+MODFUNC(void)
+{
+ PyObject *mod = NULL;
+
+ if (prepare_types() < 0)
+ RETURN(NULL);
+ if (init_exceptions() < 0)
+ goto error;
+#ifdef PY3K
+ mod = PyModule_Create(&moduledef);
+#else
+ mod = Py_InitModule3(MODULE_NAME, arch_methods, MODULE_DOC);
+#endif
+ if (mod == NULL)
+ goto error;
+ if (add_module_objects(mod) < 0)
+ goto error;
+ RETURN(mod);
+
+ error:
+ Py_XDECREF(mod);
+ Py_XDECREF(PsiExc_AttrNotAvailableError);
+ Py_XDECREF(PsiExc_AttrInsufficientPrivsError);
+ Py_XDECREF(PsiExc_AttrNotImplementedError);
+ Py_DECREF(&PsiArchBase_Type);
+ Py_DECREF(&PsiArchLinux_Type);
+ Py_DECREF(&PsiArchSunOS_Type);
+ Py_DECREF(&PsiArchDarwin_Type);
+ Py_DECREF(&PsiArchAIX_Type);
+ RETURN(NULL);
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80e25b46/tools/bin/pythonSrc/PSI-0.3b2_gp/src/mount.c
----------------------------------------------------------------------
diff --git a/tools/bin/pythonSrc/PSI-0.3b2_gp/src/mount.c b/tools/bin/pythonSrc/PSI-0.3b2_gp/src/mount.c
new file mode 100644
index 0000000..422c313
--- /dev/null
+++ b/tools/bin/pythonSrc/PSI-0.3b2_gp/src/mount.c
@@ -0,0 +1,502 @@
+/* The MIT License
+ *
+ * Copyright (C) 2009 Erick Tryzelaar
+ *
+ * Copyright (C) 2009 Floris Bruynooghe
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/** psi.mount.Mount* classes
+ *
+ * This file contains the common support for the psi.mount.Mount classes and
+ * factory functions.
+ */
+
+
+#include <Python.h>
+
+#include "psi.h"
+#include "mount.h"
+#include "posix_utils.h"
+
+
+/* The Python MountBase object */
+typedef struct {
+ PyObject_HEAD
+ psi_mountinfo_t *mounti;
+} PsiMountBaseObject;
+
+
+/* Helper functions */
+
+
+/* Always returns NULL */
+void *
+psi_free_mountinfo(psi_mountinfo_t *mounti)
+{
+ psi_FREE(mounti->mount_type);
+ psi_FREE(mounti->mount_options);
+ psi_FREE(mounti->mount_path);
+ psi_FREE(mounti->filesystem_host);
+ psi_FREE(mounti->filesystem_path);
+ psi_free(mounti);
+ return NULL;
+}
+
+
+/* Always returns NULL */
+void *
+psi_free_mountlist(psi_mountlist_t *mountlist)
+{
+ int i;
+
+ for (i = 0; i < mountlist->count; ++i) {
+ if (mountlist->mounts[i] != NULL) {
+ psi_free_mountinfo(mountlist->mounts[i]);
+ }
+ }
+ psi_free(mountlist->mounts);
+ psi_free(mountlist);
+ return NULL;
+}
+
+
+/* MountBase methods */
+
+
+static void
+MountBase_dealloc(PsiMountBaseObject *self)
+{
+ if (self->mounti != NULL) {
+ psi_free_mountinfo(self->mounti);
+ }
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject *
+MountBase_repr(PsiMountBaseObject *self)
+{
+ return PyStr_FromFormat("%s()", Py_TYPE(self)->tp_name);
+}
+
+
+/** Check if object is initialised */
+static int
+check_init(PsiMountBaseObject *obj)
+{
+ if (obj->mounti == NULL) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Instance has not been initialised properly");
+ return -1;
+ }
+ return 0;
+}
+
+
+static PyObject *
+MountBase_get_fstype(PsiMountBaseObject *self)
+{
+ if (check_init(self) == -1)
+ return NULL;
+ if (psi_checkattr("Mount.fstype", self->mounti->mount_type_status) < 0)
+ return NULL;
+ return PyStr_FromString(self->mounti->mount_type);
+}
+
+
+static PyObject *
+MountBase_get_options(PsiMountBaseObject *self)
+{
+ if (check_init(self) == -1)
+ return NULL;
+ if (psi_checkattr("Mount.options",
+ self->mounti->mount_options_status) < 0)
+ return NULL;
+ return PyStr_FromString(self->mounti->mount_options);
+}
+
+
+static PyObject *
+MountBase_get_mountpoint(PsiMountBaseObject *self)
+{
+ if (check_init(self) == -1)
+ return NULL;
+ if (psi_checkattr("Mount.mountpoint", self->mounti->mount_path_status) < 0)
+ return NULL;
+ return PyStr_FromString(self->mounti->mount_path);
+}
+
+
+static PyObject *
+MountBase_get_device(PsiMountBaseObject *self)
+{
+ if (check_init(self) == -1)
+ return NULL;
+ if (psi_checkattr("Mount.device", self->mounti->filesystem_path_status) < 0)
+ return NULL;
+ return PyStr_FromString(self->mounti->filesystem_path);
+}
+
+
+static PyObject *
+MountBase_get_total(PsiMountBaseObject *self, void *closure)
+{
+ PyObject *fr = NULL;
+ PyObject *tot = NULL;
+ PyObject *r = NULL;
+
+ if (check_init(self) < 0)
+ return NULL;
+ if (psi_checkattr("Mount.total", self->mounti->frsize_status) < 0 ||
+ psi_checkattr("Mount.total", self->mounti->total_status) < 0)
+ return NULL;
+ fr = PyLong_FromUnsignedLong(self->mounti->frsize);
+ if (fr == NULL)
+ goto end;
+ tot = PyLong_FromUnsignedLong(self->mounti->total);
+ if (tot == NULL)
+ goto end;
+ r = PyNumber_Multiply(fr, tot);
+
+ end:
+ Py_XDECREF(fr);
+ Py_XDECREF(tot);
+ return r;
+}
+
+
+static PyObject *
+MountBase_get_free(PsiMountBaseObject *self, void *closure)
+{
+ PyObject *fr = NULL;
+ PyObject *free = NULL;
+ PyObject *r = NULL;
+
+ if (check_init(self) < 0)
+ return NULL;
+ if (psi_checkattr("Mount.free", self->mounti->frsize_status) < 0 ||
+ psi_checkattr("Mount.free", self->mounti->ffree_status) < 0)
+ return NULL;
+ fr = PyLong_FromUnsignedLong(self->mounti->frsize);
+ if (fr == NULL)
+ goto end;
+ free = PyLong_FromUnsignedLong(self->mounti->ffree);
+ if (free == NULL)
+ goto end;
+ r = PyNumber_Multiply(fr, free);
+
+ end:
+ Py_XDECREF(fr);
+ Py_XDECREF(free);
+ return r;
+}
+
+
+static PyObject *
+MountBase_get_avail(PsiMountBaseObject *self, void *closure)
+{
+ PyObject *fr = NULL;
+ PyObject *avail = NULL;
+ PyObject *r = NULL;
+
+ if (check_init(self) < 0)
+ return NULL;
+ if (psi_checkattr("Mount.available", self->mounti->frsize_status) < 0 ||
+ psi_checkattr("Mount.available", self->mounti->favail_status) < 0)
+ return NULL;
+ fr = PyLong_FromUnsignedLong(self->mounti->frsize);
+ if (fr == NULL)
+ goto end;
+ avail = PyLong_FromUnsignedLong(self->mounti->favail);
+ if (avail == NULL)
+ goto end;
+ r = PyNumber_Multiply(fr, avail);
+
+ end:
+ Py_XDECREF(fr);
+ Py_XDECREF(avail);
+ return r;
+}
+
+
+static PyObject *
+MountBase_get_inodes(PsiMountBaseObject *self, void *closure)
+{
+ if (check_init(self) < 0)
+ return NULL;
+ if (psi_checkattr("Mount.inodes", self->mounti->files_status) < 0)
+ return NULL;
+ return PyLong_FromUnsignedLong(self->mounti->files);
+}
+
+
+static PyObject *
+MountBase_get_free_inodes(PsiMountBaseObject *self, void *closure)
+{
+ if (check_init(self) < 0)
+ return NULL;
+ if (psi_checkattr("Mount.free_inodes", self->mounti->ffree_status) < 0)
+ return NULL;
+ return PyLong_FromUnsignedLong(self->mounti->ffree);
+}
+
+
+static PyObject *
+MountBase_get_available_inodes(PsiMountBaseObject *self, void *closure)
+{
+ if (check_init(self) < 0)
+ return NULL;
+ if (psi_checkattr("Mount.available_inodes", self->mounti->favail_status)<0)
+ return NULL;
+ return PyLong_FromUnsignedLong(self->mounti->favail);
+}
+
+
+static PyObject *
+MountBase_refresh(PsiMountBaseObject *self)
+{
+ psi_mountlist_t *mountlist;
+ psi_mountinfo_t *mounti;
+ int remote = 0;
+ int i;
+
+ if (PyObject_IsInstance((PyObject *)self, (PyObject *)&RemoteMount_Type))
+ remote = 1;
+ mountlist = psi_arch_mountlist(remote);
+ if (mountlist == NULL)
+ return NULL;
+ for (i = 0; i < mountlist->count; i++) {
+ mounti = mountlist->mounts[i];
+ if (strcmp(self->mounti->mount_path, mounti->mount_path) == 0 &&
+ strcmp(self->mounti->filesystem_path, mounti->filesystem_path) == 0)
+ break;
+ }
+ psi_free_mountinfo(self->mounti);
+ self->mounti = mounti;
+ mountlist->mounts[i] = NULL;
+ psi_free_mountlist(mountlist);
+ Py_RETURN_NONE;
+}
+
+
+static PyGetSetDef MountBase_getseters[] = {
+ {"fstype", (getter)MountBase_get_fstype, (setter)NULL,
+ "Type of the filesystem", NULL},
+ {"options", (getter)MountBase_get_options, (setter)NULL,
+ "Mount options", NULL},
+ {"mountpoint", (getter)MountBase_get_mountpoint, (setter)NULL,
+ "Where this filesystem is mounted on the filesystem hierarchy", NULL},
+ {"device", (getter)MountBase_get_device, (setter)NULL,
+ "Filesystem path", NULL},
+ {"total", (getter)MountBase_get_total, (setter)NULL,
+ "Total filesystem size in bytes", NULL},
+ {"free", (getter)MountBase_get_free, (setter)NULL,
+ "Free filesystem size in bytes", NULL},
+ {"available", (getter)MountBase_get_avail, (setter)NULL,
+ "Available filesystem size in bytes, i.e. free space for non-root", NULL},
+ {"inodes", (getter)MountBase_get_inodes, (setter)NULL,
+ "Number of inodes", NULL},
+ {"free_inodes", (getter)MountBase_get_free_inodes, (setter)NULL,
+ "Number of free inodes", NULL},
+ {"available_inodes", (getter)MountBase_get_available_inodes, (setter)NULL,
+ "Number of available nodes, i.e. free inodes for non-root", NULL},
+ {NULL} /* Sentinel */
+};
+
+
+static PyMethodDef MountBase_methods[] = {
+ {"refresh", (PyCFunction)MountBase_refresh, METH_NOARGS,
+ PyDoc_STR("Refresh the attributes with recent data")},
+ {NULL} /* Sentinel */
+};
+
+
+PyTypeObject MountBase_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "psi.mount.Mount", /* tp_name */
+ sizeof(PsiMountBaseObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)MountBase_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ (reprfunc)MountBase_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ "Base object for all mount classes", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ MountBase_methods, /* tp_methods */
+ 0, /* tp_members */
+ MountBase_getseters, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+
+PyTypeObject LocalMount_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "psi.mount.LocalMount", /* tp_name */
+ sizeof(PsiMountBaseObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ "This object represents a local mountpoint", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &MountBase_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+
+static PyObject *
+RemoteMount_get_host(PsiMountBaseObject *self)
+{
+ if (check_init(self) == -1)
+ return NULL;
+ if (psi_checkattr("Mount.filesystem_host", self->mounti->filesystem_host_status) == -1)
+ return NULL;
+ return PyStr_FromString(self->mounti->filesystem_host);
+}
+
+
+static PyGetSetDef RemoteMount_getseters[] = {
+ {"host", (getter)RemoteMount_get_host, (setter)NULL,
+ "The host of the filesystem", NULL},
+ {NULL} /* Sentinel */
+};
+
+
+PyTypeObject RemoteMount_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "psi.mount.RemoteMount", /* tp_name */
+ sizeof(PsiMountBaseObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ "This object represents a remote mountpoint", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ RemoteMount_getseters, /* tp_getset */
+ &MountBase_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+
+/* Object Creation Functions */
+
+
+PyObject *
+PsiMount_New(psi_mountinfo_t *mounti)
+{
+ PsiMountBaseObject *self;
+
+ if (mounti == NULL) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Instance has not been initialised properly");
+ return NULL;
+ }
+ if (mounti->filesystem_host == NULL)
+ self = (PsiMountBaseObject *)PyType_GenericNew(&LocalMount_Type,
+ NULL, NULL);
+ else
+ self = (PsiMountBaseObject *)PyType_GenericNew(&RemoteMount_Type,
+ NULL, NULL);
+ if (self != NULL)
+ self->mounti = mounti;
+ return (PyObject *)self;
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/80e25b46/tools/bin/pythonSrc/PSI-0.3b2_gp/src/mountmodule.c
----------------------------------------------------------------------
diff --git a/tools/bin/pythonSrc/PSI-0.3b2_gp/src/mountmodule.c b/tools/bin/pythonSrc/PSI-0.3b2_gp/src/mountmodule.c
new file mode 100644
index 0000000..c743bd2
--- /dev/null
+++ b/tools/bin/pythonSrc/PSI-0.3b2_gp/src/mountmodule.c
@@ -0,0 +1,229 @@
+/* The MIT License
+ *
+ * Copyright (C) 2009 Erick Tryzelaar
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* The psi.mount module */
+
+
+#include <Python.h>
+
+#include "psi.h"
+#include "mount.h"
+
+
+/* Declarations (we need these since we use -Wmissing-declarations) */
+#ifdef PY3K
+PyMODINIT_FUNC PyInit_mount(void);
+#else
+PyMODINIT_FUNC initmount(void);
+#endif
+
+
+/* Re-declare these as non-extern since we're providing the symbols */
+PyObject *PsiExc_AttrNotAvailableError = NULL;
+PyObject *PsiExc_AttrInsufficientPrivsError = NULL;
+PyObject *PsiExc_AttrNotImplementedError = NULL;
+
+
+/* More contstants */
+static char MODULE_NAME[] = "psi.mount";
+PyDoc_STRVAR(MODULE_DOC, "Module for system mount information");
+
+
+PyDoc_STRVAR(psi_mount_mounts__doc, "\
+mounts(remote=False) -> iterator\n\
+\n\
+Return an iterator containing ojects representing mounted filesystems. The\n\
+remote argument is a boolean value that can be used to control if remote\n\
+filesystems should be included or not. Remote filesystems might take longer\n\
+to be created or suffer from timeouts collecting information from them.\n\
+");
+static PyObject *
+psi_mount_mounts(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ static char *kwlist[] = {"remote", NULL};
+ psi_mountlist_t *mountlist;
+ PyObject *mount;
+ PyObject *list;
+ PyObject *iter;
+ ssize_t i;
+ int remote = 0;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &remote))
+ return NULL;
+ mountlist = psi_arch_mountlist(remote);
+ if (mountlist == NULL)
+ return NULL;
+ list = PyList_New(mountlist->count);
+ if (list == NULL)
+ return psi_free_mountlist(mountlist);
+ for (i = 0; i < mountlist->count; ++i) {
+ mount = PsiMount_New(mountlist->mounts[i]);
+ if (mount == NULL) {
+ Py_DECREF(list);
+ return psi_free_mountlist(mountlist);
+ }
+ PyList_SET_ITEM(list, i, mount);
+
+ /* Python now owns the mountinfo, so clear it from the list. */
+ mountlist->mounts[i] = NULL;
+ }
+ psi_free_mountlist(mountlist);
+ iter = PySeqIter_New(list);
+ Py_DECREF(list);
+ return iter;
+}
+
+
+/** Finalise the types
+ *
+ * Calls PyType_Ready() and does anything else required.
+ */
+static int
+prepare_types(void)
+{
+ if (PyType_Ready(&MountBase_Type) < 0)
+ return -1;
+ if (PyType_Ready(&LocalMount_Type) < 0)
+ return -1;
+ if (PyType_Ready(&RemoteMount_Type) < 0)
+ return -1;
+ Py_INCREF(&MountBase_Type);
+ Py_INCREF(&LocalMount_Type);
+ Py_INCREF(&RemoteMount_Type);
+ return 0;
+}
+
+
+/** Initialise the global exceptions
+ *
+ * If this function fails the modinit function will Py_XDECREF the exceptions,
+ * so no need to do that here.
+ */
+static int
+init_exceptions(void)
+{
+ PyObject *_psimod;
+
+ _psimod = PyImport_ImportModule("psi._psi");
+ if (_psimod == NULL)
+ return -1;
+ PsiExc_AttrNotAvailableError = PyObject_GetAttrString(
+ _psimod, "AttrNotAvailableError");
+ if (PsiExc_AttrNotAvailableError == NULL)
+ goto error;
+ PsiExc_AttrInsufficientPrivsError = PyObject_GetAttrString(
+ _psimod, "AttrInsufficientPrivsError");
+ if (PsiExc_AttrInsufficientPrivsError == NULL)
+ goto error;
+ PsiExc_AttrNotImplementedError = PyObject_GetAttrString(
+ _psimod, "AttrNotImplementedError");
+ if (PsiExc_AttrNotImplementedError == NULL)
+ goto error;
+ Py_DECREF(_psimod);
+ return 0;
+
+ error:
+ Py_DECREF(_psimod);
+ return -1;
+}
+
+
+/* Add all the objects to the module */
+static int
+add_module_objects(PyObject *mod)
+{
+ if (PyModule_AddObject(mod, "MountBase", (PyObject *)&MountBase_Type) < 0)
+ return -1;
+ if (PyModule_AddObject(mod, "LocalMount", (PyObject *)&LocalMount_Type) < 0)
+ return -1;
+ if (PyModule_AddObject(mod, "RemoteMount", (PyObject *)&RemoteMount_Type) < 0)
+ return -1;
+ return 0;
+}
+
+
+static PyMethodDef mount_methods[] = {
+ {"mounts", (PyCFunction)psi_mount_mounts, METH_VARARGS | METH_KEYWORDS,
+ psi_mount_mounts__doc},
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+
+#ifdef PY3K
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT, /* m_base */
+ MODULE_NAME, /* m_name */
+ MODULE_DOC, /* m_doc */
+ -1, /* m_size */
+ mount_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL /* m_free */
+};
+#endif
+
+
+/* Some defines to make the module init function readable */
+#ifdef PY3K
+#define MODFUNC PyInit_mount
+#define RETURN(VAR) return VAR
+#else
+#define MODFUNC initmount
+#define RETURN(VAR) return
+#endif
+
+
+/* Returns the psi.mount module */
+PyMODINIT_FUNC
+MODFUNC(void)
+{
+ PyObject *mod = NULL;
+
+ if (prepare_types() < 0)
+ RETURN(NULL);
+ if (init_exceptions() < 0)
+ goto error;
+#ifdef PY3K
+ mod = PyModule_Create(&moduledef);
+#else
+ mod = Py_InitModule3(MODULE_NAME, mount_methods, MODULE_DOC);
+#endif
+ if (mod == NULL)
+ goto error;
+ if (add_module_objects(mod) < 0)
+ goto error;
+ PyErr_WarnEx(PyExc_FutureWarning, "Experimental API", 1);
+ RETURN(mod);
+
+error:
+ Py_XDECREF(mod);
+ Py_XDECREF(PsiExc_AttrNotAvailableError);
+ Py_XDECREF(PsiExc_AttrInsufficientPrivsError);
+ Py_XDECREF(PsiExc_AttrNotImplementedError);
+ Py_XDECREF(&MountBase_Type);
+ Py_XDECREF(&LocalMount_Type);
+ Py_XDECREF(&RemoteMount_Type);
+ RETURN(NULL);
+}