7759 Perl modules update
[unleashed-userland.git] / components / perl / sun_solaris / src / Sun / Solaris / Exacct / File / File.xs
blob2a4f0e2edef41447414e955291ace15065e85f7f
1 /*
2  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
3  *
4  * File.xs contains XS code for exacct file manipulation.
5  */
7 #include <pwd.h>
8 #include "../exacct_common.xh"
10 /* Pull in the file generated by extract_defines. */
11 #include "FileDefs.xi"
14  * The XS code exported to perl is below here.  Note that the XS preprocessor
15  * has its own commenting syntax, so all comments from this point on are in
16  * that form.
17  */
19 MODULE = Sun::Solaris::Exacct::File PACKAGE = Sun::Solaris::Exacct::File
20 PROTOTYPES: ENABLE
22  #
23  # Define the stash pointers if required and create and populate @_Constants.
24  #
25 BOOT:
26         {
27         init_stashes();
28         define_constants(PKGBASE "::File", constants);
29         }
31  #
32  # Open an exacct file and return an object with which to manipulate it.
33  # The parameters are the filename, the open mode and a list of optional
34  # (key => value) parameters where the key may be  one of creator, aflags or
35  # mode.  For a full explanation of the various combinations, see the manpage
36  # for ea_open_file(3EXACCT).
37  #
38 ea_file_t *
39 new(class, name, oflags, ...)
40         char    *class;
41         char    *name;
42         int     oflags;
43 PREINIT:
44         int     i;
45         /* Assume usernames are <= 32 chars (pwck(1M) assumes <= 8) */
46         char    user[33];
47         char    *creator = NULL;
48         int     aflags   = -1;
49         mode_t  mode     = 0666;
50 CODE:
51         /*
52          * Account for the mandatory parameters,
53          * and the rest must be an even number.
54          */
55         i = items - 3;
56         if ((i % 2) != 0) {
57                 croak("Usage: Sun::Solaris::Exacct::File::new"
58                     "(class, name, oflags, ...)");
59         }
61         /* Process any optional parameters. */
62         for (i = 3; i < items; i += 2) {
63                 if (strEQ(SvPV_nolen(ST(i)), "creator")) {
64                         creator = SvPV_nolen(ST(i + 1));
65                 } else if (strEQ(SvPV_nolen(ST(i)), "aflags")) {
66                         aflags = SvIV(ST(i + 1));
67                 } else if (strEQ(SvPV_nolen(ST(i)), "mode")) {
68                         mode = SvIV(ST(i + 1));
69                 } else {
70                         croak("invalid named argument %s", SvPV_nolen(ST(i)));
71                 }
72         }
74         /* Check and default the creator parameter. */
75         if (oflags & O_CREAT && creator == NULL) {
76                 uid_t           uid;
77                 struct passwd   *pwent;
79                 uid = getuid();
80                 if ((pwent = getpwuid(uid)) == NULL) {
81                         snprintf(user, sizeof (user), "%d", uid);
82                 } else {
83                         strlcpy(user, pwent->pw_name, sizeof (user));
84                 }
85                 creator = user;
86         }
88         /* Check and default the aflags parameter. */
89         if (aflags == -1) {
90                 if (oflags == O_RDONLY) {
91                         aflags = EO_HEAD;
92                 } else {
93                         aflags = EO_TAIL;
94                 }
95         }
96         RETVAL = ea_alloc(sizeof (ea_file_t));
97         PERL_ASSERT(RETVAL != NULL);
98         if (ea_open(RETVAL, name, creator, aflags, oflags, mode) == -1) {
99                 ea_free(RETVAL, sizeof (ea_file_t));
100                 RETVAL = NULL;
101         }
102 OUTPUT:
103         RETVAL
105 void
106 DESTROY(self)
107         ea_file_t       *self;
108 CODE:
109         ea_close(self);
110         ea_free(self, sizeof(ea_file_t));
113  # Return the creator of the file.
116 creator(self)
117         ea_file_t       *self;
118 PREINIT:
119         const char      *creator;
120 CODE:
121         if ((creator = ea_get_creator(self)) == NULL) {
122                 RETVAL = &PL_sv_undef;
123         } else {
124                 RETVAL = newSVpv(creator, 0);
125         }
126 OUTPUT:
127         RETVAL
130  # Return the hostname the file was created on.
133 hostname(self)
134         ea_file_t       *self;
135 PREINIT:
136         const char      *hostname;
137 CODE:
138         if ((hostname = ea_get_hostname(self)) == NULL) {
139                 RETVAL = &PL_sv_undef;
140         } else {
141                 RETVAL = newSVpv(hostname, 0);
142         }
143 OUTPUT:
144         RETVAL
147  # Get the next/previous record from the file and return its type.
148  # These two operations are so similar that the XSUB ALIAS functionality is
149  # used to merge them into one function.
151 void
152 next(self)
153         ea_file_t       *self;
154 ALIAS:
155         previous = 1
156 PREINIT:
157         ea_object_type_t                type;
158         const char                      *type_str;
159         ea_object_t                     object;
160         SV                              *sv;
161         static const char *const        type_map[] =
162             { "EO_NONE", "EO_GROUP", "EO_ITEM" };
163 PPCODE:
164         /* Call the appropriate next/last function. */
165         if (ix == 0) {
166                 type = ea_next_object(self, &object);
167         } else {
168                 type = ea_previous_object(self, &object);
169         }
171         /* Work out the call context. */
172         switch (GIMME_V) {
173         case G_SCALAR:
174                 /* In a scalar context, just return the type. */
175                 EXTEND(SP, 1);
176                 if (type == EO_ERROR) {
177                         PUSHs(&PL_sv_undef);
178                 } else {
179                         sv = newSVuv(type);
180                         sv_setpv(sv, type_map[type]);
181                         SvIOK_on(sv);
182                         PUSHs(sv_2mortal(sv));
183                 }
184                 break;
185         case G_ARRAY:
186                 /* In a list contect, return the type and catalog. */
187                 EXTEND(SP, 2);
188                 if (type == EO_ERROR) {
189                         PUSHs(&PL_sv_undef);
190                         PUSHs(&PL_sv_undef);
191                 } else {
192                         sv = newSVuv(type);
193                         sv_setpv(sv, type_map[type]);
194                         SvIOK_on(sv);
195                         PUSHs(sv_2mortal(sv));
196                         PUSHs(sv_2mortal(new_catalog(object.eo_catalog)));
197                 }
198                 break;
199         case G_VOID:
200         default:
201                 /* In a void context, return nothing. */
202                 break;
203         }
206  # Get the next object from the file and return as an ::Object.
209 get(self)
210         ea_file_t       *self;
211 PREINIT:
212         ea_object_t     *obj;
213 CODE:
214         if ((obj = ea_get_object_tree(self, 1)) != NULL) {
215                 RETVAL = new_xs_ea_object(obj);
216         } else {
217                 RETVAL = &PL_sv_undef;
218         }
219 OUTPUT:
220         RETVAL
223  # Write the passed list of ::Objects to the file.
224  # Returns true on success and false on failure.
227 write(self, ...)
228         ea_file_t       *self;
229 PREINIT:
230         int             i;
231         SV              *sv;
232         HV              *stash;
233         ea_object_t     *obj;
234 CODE:
235         for (i = 1; i < items; i++) {
236                 /* Check the value is either an ::Item or a ::Group. */
237                 sv = SvRV(ST(i));
238                 stash = sv ? SvSTASH(sv) : NULL;
239                 if (stash != Sun_Solaris_Exacct_Object_Item_stash &&
240                     stash != Sun_Solaris_Exacct_Object_Group_stash) {
241                         XSRETURN_NO;
242                 }
244                 /* Deflate and write the object. */
245                 obj = deflate_xs_ea_object(ST(i));
246                 PERL_ASSERT(obj != NULL);
247                 if (ea_write_object(self, obj) == -1) {
248                         XSRETURN_NO;
249                 }
250         }
251         RETVAL = &PL_sv_yes;
252 OUTPUT:
253         RETVAL