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>
15 #include <sys/types.h>
27 * Convert and save a struct project on the perl XS return stack.
28 * In a void context it returns nothing, in a scalar context it returns just
29 * the name of the project and in a list context it returns a 6-element list
30 * consisting of (name, projid, comment, users, groups, attr), where users and
31 * groups are references to arrays containing the appropriate lists.
34 pushret_project(const struct project *proj)
40 if (GIMME_V == G_SCALAR) {
42 PUSHs(sv_2mortal(newSVpv(proj->pj_name, 0)));
45 } else if (GIMME_V == G_ARRAY) {
47 PUSHs(sv_2mortal(newSVpv(proj->pj_name, 0)));
48 PUSHs(sv_2mortal(newSViv(proj->pj_projid)));
49 PUSHs(sv_2mortal(newSVpv(proj->pj_comment, 0)));
51 for (cp = proj->pj_users; *cp != NULL; cp++) {
52 av_push(ary, newSVpv(*cp, 0));
54 PUSHs(sv_2mortal(newRV_noinc((SV *)ary)));
56 for (cp = proj->pj_groups; *cp != NULL; cp++) {
57 av_push(ary, newSVpv(*cp, 0));
59 PUSHs(sv_2mortal(newRV_noinc((SV *)ary)));
60 PUSHs(sv_2mortal(newSVpv(proj->pj_attr, 0)));
69 pwalk_cb(const projid_t project, void *walk_data)
74 nitemsp = (int *) walk_data;
76 PUSHs(sv_2mortal(newSViv(project)));
83 * The XS code exported to perl is below here. Note that the XS preprocessor
84 * has its own commenting syntax, so all comments from this point on are in
85 * that form. Note also that the PUTBACK; lines are necessary to synchronise
86 * the local and global views of the perl stack before calling pushret_project,
87 * as the code generated by the perl XS compiler twiddles with the stack on
91 MODULE = Sun::Solaris::Project PACKAGE = Sun::Solaris::Project
95 # Define any constants that need to be exported. By doing it this way we can
96 # avoid the overhead of using the DynaLoader package, and in addition constants
97 # defined using this mechanism are eligible for inlining by the perl
98 # interpreter at compile time.
104 stash = gv_stashpv("Sun::Solaris::Project", TRUE);
105 newCONSTSUB(stash, "MAXPROJID", newSViv(MAXPROJID));
106 newCONSTSUB(stash, "PROJNAME_MAX", newSViv(PROJNAME_MAX));
107 newCONSTSUB(stash, "PROJF_PATH",
108 newSVpv(PROJF_PATH, sizeof (PROJF_PATH) - 1));
109 newCONSTSUB(stash, "PROJECT_BUFSZ", newSViv(PROJECT_BUFSZ));
110 newCONSTSUB(stash, "SETPROJ_ERR_TASK", newSViv(SETPROJ_ERR_TASK));
111 newCONSTSUB(stash, "SETPROJ_ERR_POOL", newSViv(SETPROJ_ERR_POOL));
112 newCONSTSUB(stash, "RCTL_GLOBAL_NOBASIC",
113 newSViv(RCTL_GLOBAL_NOBASIC));
114 newCONSTSUB(stash, "RCTL_GLOBAL_LOWERABLE",
115 newSViv(RCTL_GLOBAL_LOWERABLE));
116 newCONSTSUB(stash, "RCTL_GLOBAL_DENY_ALWAYS",
117 newSViv(RCTL_GLOBAL_DENY_ALWAYS));
118 newCONSTSUB(stash, "RCTL_GLOBAL_DENY_NEVER",
119 newSViv(RCTL_GLOBAL_DENY_NEVER));
120 newCONSTSUB(stash, "RCTL_GLOBAL_FILE_SIZE",
121 newSViv(RCTL_GLOBAL_FILE_SIZE));
122 newCONSTSUB(stash, "RCTL_GLOBAL_CPU_TIME",
123 newSViv(RCTL_GLOBAL_CPU_TIME));
124 newCONSTSUB(stash, "RCTL_GLOBAL_SIGNAL_NEVER",
125 newSViv(RCTL_GLOBAL_SIGNAL_NEVER));
126 newCONSTSUB(stash, "RCTL_GLOBAL_INFINITE",
127 newSViv(RCTL_GLOBAL_INFINITE));
128 newCONSTSUB(stash, "RCTL_GLOBAL_UNOBSERVABLE",
129 newSViv(RCTL_GLOBAL_UNOBSERVABLE));
130 newCONSTSUB(stash, "RCTL_GLOBAL_BYTES",
131 newSViv(RCTL_GLOBAL_BYTES));
132 newCONSTSUB(stash, "RCTL_GLOBAL_SECONDS",
133 newSViv(RCTL_GLOBAL_SECONDS));
134 newCONSTSUB(stash, "RCTL_GLOBAL_COUNT",
135 newSViv(RCTL_GLOBAL_COUNT));
136 sprintf(buf, "%llu", UINT64_MAX);
137 newCONSTSUB(stash, "RCTL_MAX_VALUE",
138 newSVpv(buf, strlen(buf)));
145 setproject(name, user_name, flags)
147 const char *user_name
157 project_walk(&pwalk_cb, (void*)&nitems);
163 struct project proj, *projp;
164 char buf[PROJECT_BUFSZ];
167 if ((projp = getprojent(&proj, buf, sizeof (buf)))) {
168 XSRETURN(pushret_project(projp));
183 struct project proj, *projp;
184 char buf[PROJECT_BUFSZ];
187 if ((projp = getprojbyname(name, &proj, buf, sizeof (buf)))) {
188 XSRETURN(pushret_project(projp));
197 struct project proj, *projp;
198 char buf[PROJECT_BUFSZ];
201 if ((projp = getprojbyid(id, &proj, buf, sizeof (buf)))) {
202 XSRETURN(pushret_project(projp));
211 struct project proj, *projp;
212 char buf[PROJECT_BUFSZ];
215 if ((projp = getdefaultproj(user, &proj, buf, sizeof (buf)))) {
216 XSRETURN(pushret_project(projp));
225 struct project proj, *projp;
226 char buf[PROJECT_BUFSZ];
229 if ((projp = fgetprojent(fh, &proj, buf, sizeof (buf)))) {
230 XSRETURN(pushret_project(projp));
240 char buf[PROJECT_BUFSZ];
242 RETVAL = inproj(user, proj, buf, sizeof (buf));
248 getprojidbyname(proj)
253 if ((id = getprojidbyname(proj)) == -1) {
260 # rctl_get_info(name)
262 # For the given rctl name, returns the list
263 # ($max, $flags), where $max is the integer value
264 # of the system rctl, and $flags are the rctl's
265 # global flags, as returned by rctlblk_get_global_flags
267 # This function is private to Project.pm
272 rctlblk_t *blk1 = NULL;
273 rctlblk_t *blk2 = NULL;
274 rctlblk_t *tmp = NULL;
280 char string[24]; /* 24 will always hold a uint64_t */
282 Newc(0, blk1, rctlblk_size(), char, rctlblk_t);
287 Newc(1, blk2, rctlblk_size(), char, rctlblk_t);
292 ret = getrctl(name, NULL, blk1, RCTL_FIRST);
297 priv = rctlblk_get_privilege(blk1);
298 while (priv != RCPRIV_SYSTEM) {
302 ret = getrctl(name, blk2, blk1, RCTL_NEXT);
307 priv = rctlblk_get_privilege(blk1);
309 value = rctlblk_get_value(blk1);
310 flags = rctlblk_get_global_flags(blk1);
311 ret = sprintf(string, "%llu", value);
323 XPUSHs(sv_2mortal(newSVpv(string, 0)));
324 XPUSHs(sv_2mortal(newSViv(flags)));
330 # Returns 0 a pool with the given name exists on the current system.
331 # Returns 1 if pools are disabled or the pool does not exist
333 # Used internally by project.pm to validate the project.pool attribute
335 # This function is private to Project.pm
342 pool_status_t status;
347 * Determine if pools are enabled using /dev/pool directly, as
348 * libpool may not be present.
350 if (getzoneid() != GLOBAL_ZONEID) {
353 if ((fd = open("/dev/pool", O_RDONLY)) < 0) {
356 if (ioctl(fd, POOL_STATUSQ, &status) < 0) {
361 if (status.ps_io_state != 1) {
366 * If pools are enabled, assume libpool is present.
368 conf = pool_conf_alloc();
372 if (pool_conf_open(conf, pool_dynamic_location(), PO_RDONLY)) {
373 pool_conf_free(conf);
376 pool = pool_get_pool(conf, name);
378 pool_conf_close(conf);
379 pool_conf_free(conf);
382 pool_conf_close(conf);
383 pool_conf_free(conf);