Imported Upstream version 2.5.0
[debian/amanda] / contrib / gsc / defgsc.c
1 /*
2  * $Id: defgsc.c,v 1.1 2001/04/15 11:12:37 ant Exp $
3  * Copyright (c) 1997 by Matthew Jacob
4  *
5  *      This software is free software; you can redistribute it and/or
6  *      modify it under the terms of the GNU Library General Public
7  *      License as published by the Free Software Foundation; version 2.
8  *
9  *      This software is distributed in the hope that it will be useful,
10  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *      Library General Public License for more details.
13  *
14  *      You should have received a copy of the GNU Library General Public
15  *      License along with this software; if not, write to the Free
16  *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  *      The author may be reached via electronic communications at
19  *
20  *              mjacob@feral.com
21  *
22  *      or, via United States Postal Address
23  *
24  *              Matthew Jacob
25  *              1831 Castro Street
26  *              San Francisco, CA, 94131
27  */
28
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <sys/cfgdb.h>
32 #include <sys/cfgodm.h>
33 #include <cf.h>
34
35 static const char *triple = "type = '%s' AND class = '%s' AND subclass = '%s'";
36 static const char *utype =
37         "uniquetype = '%s' and connkey = '%s' and connwhere = '%s'";
38
39 static void
40 err_exit(char exitcode)
41 {
42     odm_close_class(CuDv_CLASS);
43     odm_close_class(PdDv_CLASS);
44     odm_terminate();
45     exit(exitcode);
46 }
47
48 int
49 main(int a, char **v)
50 {
51     extern int optind;
52     extern char *optarg;
53     char *class, *subclass, *type, *parent, *connect;
54     char sstring[256], lname[256];
55     char parent_loc[LOCSIZE];
56     struct Class *cusdev;
57     struct PdDv PdDv;
58     struct PdCn PdCn;
59     struct CuDv CuDv;
60     int seqno, rc, errflg, c;
61
62     errflg = 0;
63
64     class = subclass = type = NULL;
65     parent = connect = NULL;
66
67     while ((c = getopt(a, v, "p:w:c:s:t:")) != EOF) {
68         switch (c) {
69         case 'c':
70             if (class != NULL)
71                 errflg++;
72             class = optarg;
73             break;
74         case 's':
75             if (subclass != NULL)
76                 errflg++;
77             subclass = optarg;
78             break;
79         case 't':
80             if (type != NULL)
81                 errflg++;
82             type = optarg;
83             break;
84         case 'w':
85             if (connect != NULL)
86                 errflg++;
87             connect = optarg;
88             break;
89         case 'p':
90             if (parent != NULL)
91                 errflg++;
92             parent = optarg;
93             break;
94         default:
95             errflg++;
96         }
97     }
98     if (errflg) {
99         exit(E_ARGS);
100     }
101
102     /*
103      * Verify that we have the right triple and all of it specified.
104      */
105     if (class == NULL || subclass == NULL || type == NULL) {
106         exit(E_TYPE);
107     }
108     if (strcmp(class, "generic") ||
109         strcmp(subclass, "scsi") ||
110         strcmp(type, "gsc")) {
111         exit(E_TYPE);
112     }
113     /*
114      * Verify that a parent and a connection address was specified
115      */
116     if (parent == NULL || connect == NULL) {
117         exit(E_PARENT);
118     }
119
120     /*
121      * Open up ODM.
122      */
123     if (odm_initialize() == -1) {
124         exit(E_ODMINIT);
125     }
126     if (odm_lock("/etc/objrepos/config_lock", 0) == -1) {
127         err_exit(E_ODMLOCK);
128     }
129     /*
130      * Get the PreDefined Device Object
131      */
132     (void) sprintf(sstring, triple, type, class, subclass);
133     rc = (int) odm_get_first(PdDv_CLASS, sstring, &PdDv);
134     if (rc == 0) {
135         err_exit(E_NOPdDv);
136     } else if (rc == -1) {
137         err_exit(E_ODMGET);
138     }
139
140     /*
141      * Open the Customized Device data base
142      */
143     if ((int) (cusdev = odm_open_class(CuDv_CLASS)) == -1) {
144         err_exit(E_ODMOPEN);
145     }
146     /*
147      * Check parent device
148      */
149     (void) sprintf(sstring, "name = '%s'", parent);
150     rc = (int) odm_get_first(cusdev, sstring, &CuDv);
151     if (rc == 0) {
152         err_exit(E_NOCuDvPARENT);
153     } else if (rc == -1) {
154         err_exit(E_ODMGET);
155     }
156     (void) memset(parent_loc, 0, sizeof parent_loc);
157     (void) strncpy(parent_loc, CuDv.location, sizeof CuDv.location);
158     (void) sprintf(sstring, utype, CuDv.PdDvLn_Lvalue, subclass , connect);
159     rc = (int) odm_get_first(PdCn_CLASS, sstring, &PdCn);
160     if (rc == 0) {
161         err_exit(E_INVCONNECT);
162     } else if (rc == -1) {
163         err_exit(E_ODMGET);
164     }
165
166     /*
167      * Generate a name.
168      */
169
170     /* generate logical name for device */
171     if ((seqno = genseq(PdDv.prefix)) < 0) {
172         err_exit(E_MAKENAME);
173     }
174     (void) sprintf(lname, "%s%d", PdDv.prefix, seqno);
175     (void) sprintf(sstring, "name = '%s'", lname);
176     rc = (int) odm_get_first(cusdev, sstring, &CuDv);
177     if (rc == -1) {
178         err_exit(E_ODMGET);
179     } else if (rc != 0) {
180         /*
181          * Name already exists
182          */
183         err_exit(E_LNAME);
184     }
185     /* Put device name into new CuDv object */
186     (void) strcpy(CuDv.name, lname);
187
188     /*
189      * Fill in remainder of new customized device object
190      */
191
192     /*
193      * Location codes for SCSI devices consists of 4 pairs of
194      * digits separated by hyphens. The first two pairs of digits 
195      * identify the adapter's slot number. The last two pairs of
196      * digits identify the adapter connector number and the scsi
197      * connection address. As far as I can tell, there never
198      * is a non-zero value on the connector number for SCSI
199      * adapters.
200      *
201      * This is further complicated by a slight difference in
202      * this naming convention where Model 320 and Model 220
203      * machines define the parent (adapter) location as 00-00-0S,
204      * so we'll detect that variant.
205      *
206      * This can also be further complicated by the fact that
207      * connection addresses changed between AIX Release 3.2.X
208      * and AIX Release 4.X, where the trailing digit pair went
209      * from a simple two digits (Target ID adjacent to Logical
210      * Unit Number) to two digits separated by a comma. However,
211      * since that is an argument passed in via the command line,
212      * we can say, "Not our problem," and drive onwards.
213      */
214     if (strlen(parent_loc) <= 5) {
215         (void) sprintf(CuDv.location, "%s-00-%s", parent_loc, connect);
216     } else {
217         (void) sprintf(CuDv.location, "%s-%s", parent_loc, connect);
218     }
219
220     CuDv.status = DEFINED;
221     CuDv.chgstatus = PdDv.chgstatus;
222     strcpy(CuDv.ddins, PdDv.DvDr);
223     strcpy(CuDv.PdDvLn_Lvalue, PdDv.uniquetype);
224     strcpy(CuDv.parent, parent);
225     strcpy(CuDv.connwhere, connect);
226
227     if (odm_add_obj(cusdev, &CuDv) == -1) {
228         err_exit(E_ODMADD);
229     }
230     if (odm_close_class(CuDv_CLASS) == -1) {
231         err_exit(E_ODMCLOSE);
232     }
233     odm_terminate();
234     /*
235      * Device defined successfully.
236      * Print device name to stdout with a space appended.
237      */
238     fprintf(stdout, "%s ", CuDv.name);
239     exit(E_OK);
240 }
241 /*
242  * Overrides for Emacs so that we follow Linus's tabbing style.
243  * Emacs will notice this stuff at the end of the file and automatically
244  * adjust the settings for this buffer only.  This must remain at the end
245  * of the file.
246  * ---------------------------------------------------------------------------
247 n * Local variables:
248  * c-indent-level: 4
249  * c-brace-imaginary-offset: 0
250  * c-brace-offset: -4
251  * c-argdecl-indent: 4
252  * c-label-offset: -4
253  * c-continued-statement-offset: 4
254  * c-continued-brace-offset: 0
255  * End:
256  */