2 * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2014 Racktop Systems.
6 * Project.xs contains XS wrappers for the project database maniplulation
7 * functions as provided by libproject and described in getprojent(3EXACCT).
10 /* Solaris includes. */
14 #include <sys/pool_impl.h>
24 * Convert and save a struct project on the perl XS return stack.
25 * In a void context it returns nothing, in a scalar context it returns just
26 * the name of the project and in a list context it returns a 6-element list
27 * consisting of (name, projid, comment, users, groups, attr), where users and
28 * groups are references to arrays containing the appropriate lists.
31 pushret_project(const struct project *proj)
37 if (GIMME_V == G_SCALAR) {
39 PUSHs(sv_2mortal(newSVpv(proj->pj_name, 0)));
42 } else if (GIMME_V == G_ARRAY) {
44 PUSHs(sv_2mortal(newSVpv(proj->pj_name, 0)));
45 PUSHs(sv_2mortal(newSViv(proj->pj_projid)));
46 PUSHs(sv_2mortal(newSVpv(proj->pj_comment, 0)));
48 for (cp = proj->pj_users; *cp != NULL; cp++) {
49 av_push(ary, newSVpv(*cp, 0));
51 PUSHs(sv_2mortal(newRV_noinc((SV *)ary)));
53 for (cp = proj->pj_groups; *cp != NULL; cp++) {
54 av_push(ary, newSVpv(*cp, 0));
56 PUSHs(sv_2mortal(newRV_noinc((SV *)ary)));
57 PUSHs(sv_2mortal(newSVpv(proj->pj_attr, 0)));
66 pwalk_cb(const projid_t project, void *walk_data)
71 nitemsp = (int *) walk_data;
73 PUSHs(sv_2mortal(newSViv(project)));
80 * The XS code exported to perl is below here. Note that the XS preprocessor
81 * has its own commenting syntax, so all comments from this point on are in
82 * that form. Note also that the PUTBACK; lines are necessary to synchronise
83 * the local and global views of the perl stack before calling pushret_project,
84 * as the code generated by the perl XS compiler twiddles with the stack on
88 MODULE = Sun::Solaris::Project PACKAGE = Sun::Solaris::Project
92 # Define any constants that need to be exported. By doing it this way we can
93 # avoid the overhead of using the DynaLoader package, and in addition constants
94 # defined using this mechanism are eligible for inlining by the perl
95 # interpreter at compile time.
101 stash = gv_stashpv("Sun::Solaris::Project", TRUE);
102 newCONSTSUB(stash, "MAXPROJID", newSViv(MAXPROJID));
103 newCONSTSUB(stash, "PROJNAME_MAX", newSViv(PROJNAME_MAX));
104 newCONSTSUB(stash, "PROJF_PATH",
105 newSVpv(PROJF_PATH, sizeof (PROJF_PATH) - 1));
106 newCONSTSUB(stash, "PROJECT_BUFSZ", newSViv(PROJECT_BUFSZ));
107 newCONSTSUB(stash, "SETPROJ_ERR_TASK", newSViv(SETPROJ_ERR_TASK));
108 newCONSTSUB(stash, "SETPROJ_ERR_POOL", newSViv(SETPROJ_ERR_POOL));
109 newCONSTSUB(stash, "RCTL_GLOBAL_NOBASIC",
110 newSViv(RCTL_GLOBAL_NOBASIC));
111 newCONSTSUB(stash, "RCTL_GLOBAL_LOWERABLE",
112 newSViv(RCTL_GLOBAL_LOWERABLE));
113 newCONSTSUB(stash, "RCTL_GLOBAL_DENY_ALWAYS",
114 newSViv(RCTL_GLOBAL_DENY_ALWAYS));
115 newCONSTSUB(stash, "RCTL_GLOBAL_DENY_NEVER",
116 newSViv(RCTL_GLOBAL_DENY_NEVER));
117 newCONSTSUB(stash, "RCTL_GLOBAL_FILE_SIZE",
118 newSViv(RCTL_GLOBAL_FILE_SIZE));
119 newCONSTSUB(stash, "RCTL_GLOBAL_CPU_TIME",
120 newSViv(RCTL_GLOBAL_CPU_TIME));
121 newCONSTSUB(stash, "RCTL_GLOBAL_SIGNAL_NEVER",
122 newSViv(RCTL_GLOBAL_SIGNAL_NEVER));
123 newCONSTSUB(stash, "RCTL_GLOBAL_INFINITE",
124 newSViv(RCTL_GLOBAL_INFINITE));
125 newCONSTSUB(stash, "RCTL_GLOBAL_UNOBSERVABLE",
126 newSViv(RCTL_GLOBAL_UNOBSERVABLE));
127 newCONSTSUB(stash, "RCTL_GLOBAL_BYTES",
128 newSViv(RCTL_GLOBAL_BYTES));
129 newCONSTSUB(stash, "RCTL_GLOBAL_SECONDS",
130 newSViv(RCTL_GLOBAL_SECONDS));
131 newCONSTSUB(stash, "RCTL_GLOBAL_COUNT",
132 newSViv(RCTL_GLOBAL_COUNT));
133 sprintf(buf, "%llu", UINT64_MAX);
134 newCONSTSUB(stash, "RCTL_MAX_VALUE",
135 newSVpv(buf, strlen(buf)));
142 setproject(name, user_name, flags)
144 const char *user_name
154 project_walk(&pwalk_cb, (void*)&nitems);
160 struct project proj, *projp;
161 char buf[PROJECT_BUFSZ];
164 if ((projp = getprojent(&proj, buf, sizeof (buf)))) {
165 XSRETURN(pushret_project(projp));
180 struct project proj, *projp;
181 char buf[PROJECT_BUFSZ];
184 if ((projp = getprojbyname(name, &proj, buf, sizeof (buf)))) {
185 XSRETURN(pushret_project(projp));
194 struct project proj, *projp;
195 char buf[PROJECT_BUFSZ];
198 if ((projp = getprojbyid(id, &proj, buf, sizeof (buf)))) {
199 XSRETURN(pushret_project(projp));
208 struct project proj, *projp;
209 char buf[PROJECT_BUFSZ];
212 if ((projp = getdefaultproj(user, &proj, buf, sizeof (buf)))) {
213 XSRETURN(pushret_project(projp));
222 struct project proj, *projp;
223 char buf[PROJECT_BUFSZ];
226 if ((projp = fgetprojent(fh, &proj, buf, sizeof (buf)))) {
227 XSRETURN(pushret_project(projp));
237 char buf[PROJECT_BUFSZ];
239 RETVAL = inproj(user, proj, buf, sizeof (buf));
245 getprojidbyname(proj)
250 if ((id = getprojidbyname(proj)) == -1) {
257 # rctl_get_info(name)
259 # For the given rctl name, returns the list
260 # ($max, $flags), where $max is the integer value
261 # of the system rctl, and $flags are the rctl's
262 # global flags, as returned by rctlblk_get_global_flags
264 # This function is private to Project.pm
269 rctlblk_t *blk1 = NULL;
270 rctlblk_t *blk2 = NULL;
271 rctlblk_t *tmp = NULL;
277 char string[24]; /* 24 will always hold a uint64_t */
279 Newc(0, blk1, rctlblk_size(), char, rctlblk_t);
284 Newc(1, blk2, rctlblk_size(), char, rctlblk_t);
289 ret = getrctl(name, NULL, blk1, RCTL_FIRST);
294 priv = rctlblk_get_privilege(blk1);
295 while (priv != RCPRIV_SYSTEM) {
299 ret = getrctl(name, blk2, blk1, RCTL_NEXT);
304 priv = rctlblk_get_privilege(blk1);
306 value = rctlblk_get_value(blk1);
307 flags = rctlblk_get_global_flags(blk1);
308 ret = sprintf(string, "%llu", value);
320 XPUSHs(sv_2mortal(newSVpv(string, 0)));
321 XPUSHs(sv_2mortal(newSViv(flags)));
327 # Returns 0 a pool with the given name exists on the current system.
328 # Returns 1 if pools are disabled or the pool does not exist
330 # Used internally by project.pm to validate the project.pool attribute
332 # This function is private to Project.pm
339 pool_status_t status;
344 * Determine if pools are enabled using /dev/pool directly, as
345 * libpool may not be present.
347 if (getzoneid() != GLOBAL_ZONEID) {
350 if ((fd = open("/dev/pool", O_RDONLY)) < 0) {
353 if (ioctl(fd, POOL_STATUSQ, &status) < 0) {
358 if (status.ps_io_state != 1) {
363 * If pools are enabled, assume libpool is present.
365 conf = pool_conf_alloc();
369 if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY)) {
370 pool_conf_free(conf);
373 pool = pool_get_pool(conf, name);
375 pool_conf_close(conf);
376 pool_conf_free(conf);
379 pool_conf_close(conf);
380 pool_conf_free(conf);