1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte * CDDL HEADER START
3fcf3ce44SJohn Forte *
4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte *
8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte * and limitations under the License.
12fcf3ce44SJohn Forte *
13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte *
19fcf3ce44SJohn Forte * CDDL HEADER END
20fcf3ce44SJohn Forte */
21fcf3ce44SJohn Forte /*
22fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23fcf3ce44SJohn Forte * Use is subject to license terms.
24fcf3ce44SJohn Forte */
25fcf3ce44SJohn Forte
26fcf3ce44SJohn Forte #include "cfga_fp.h"
27fcf3ce44SJohn Forte
28fcf3ce44SJohn Forte /*
29fcf3ce44SJohn Forte * This file contains the entry points to the plug-in as defined in the
30*bbf21555SRichard Lowe * config_admin(3CFGADM) man page.
31fcf3ce44SJohn Forte */
32fcf3ce44SJohn Forte
33fcf3ce44SJohn Forte /*
34fcf3ce44SJohn Forte * Set the version number
35fcf3ce44SJohn Forte */
36fcf3ce44SJohn Forte int cfga_version = CFGA_HSL_V2;
37fcf3ce44SJohn Forte
38fcf3ce44SJohn Forte /*ARGSUSED*/
39fcf3ce44SJohn Forte cfga_err_t
cfga_change_state(cfga_cmd_t state_change_cmd,const char * ap_id,const char * options,struct cfga_confirm * confp,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)40fcf3ce44SJohn Forte cfga_change_state(
41fcf3ce44SJohn Forte cfga_cmd_t state_change_cmd,
42fcf3ce44SJohn Forte const char *ap_id,
43fcf3ce44SJohn Forte const char *options,
44fcf3ce44SJohn Forte struct cfga_confirm *confp,
45fcf3ce44SJohn Forte struct cfga_msg *msgp,
46fcf3ce44SJohn Forte char **errstring,
47fcf3ce44SJohn Forte cfga_flags_t flags)
48fcf3ce44SJohn Forte {
49fcf3ce44SJohn Forte apid_t apidt = {NULL};
50fcf3ce44SJohn Forte fpcfga_ret_t ret;
51fcf3ce44SJohn Forte la_wwn_t pwwn;
52fcf3ce44SJohn Forte char *value, *hw_option, *hw_option_p;
53fcf3ce44SJohn Forte char *fp_cs_hw_opts[] = {"disable_rcm", "force_update",
54fcf3ce44SJohn Forte "no_update", "unusable_SCSI_LUN", "unusable_FCP_dev", NULL};
55fcf3ce44SJohn Forte HBA_HANDLE handle;
56fcf3ce44SJohn Forte HBA_PORTATTRIBUTES portAttrs;
57fcf3ce44SJohn Forte int portIndex;
58fcf3ce44SJohn Forte
59fcf3ce44SJohn Forte if (errstring != NULL) {
60fcf3ce44SJohn Forte *errstring = NULL;
61fcf3ce44SJohn Forte }
62fcf3ce44SJohn Forte
63fcf3ce44SJohn Forte /* Check for super user priveleges */
64fcf3ce44SJohn Forte if (geteuid() != 0) {
65fcf3ce44SJohn Forte return (CFGA_PRIV);
66fcf3ce44SJohn Forte }
67fcf3ce44SJohn Forte
68fcf3ce44SJohn Forte /* Only configure and unconfigure operations are supported */
69fcf3ce44SJohn Forte if (state_change_cmd != CFGA_CMD_CONFIGURE &&
70fcf3ce44SJohn Forte state_change_cmd != CFGA_CMD_UNCONFIGURE) {
71fcf3ce44SJohn Forte return (CFGA_OPNOTSUPP);
72fcf3ce44SJohn Forte }
73fcf3ce44SJohn Forte
742c2d21e9SRichard Lowe if ((ret = apidt_create(ap_id, &apidt, errstring)) != FPCFGA_OK) {
75fcf3ce44SJohn Forte return (err_cvt(ret));
76fcf3ce44SJohn Forte }
77fcf3ce44SJohn Forte
78fcf3ce44SJohn Forte if (options != NULL) {
79fcf3ce44SJohn Forte hw_option = calloc(1, strlen(options) + 1);
80fcf3ce44SJohn Forte (void) snprintf(hw_option, strlen(options) + 1, "%s", options);
81fcf3ce44SJohn Forte hw_option_p = hw_option;
82fcf3ce44SJohn Forte /* Use getsubopt() if more options get added */
83fcf3ce44SJohn Forte while (*hw_option_p != '\0') {
842c2d21e9SRichard Lowe switch (getsubopt(&hw_option_p, fp_cs_hw_opts,
852c2d21e9SRichard Lowe &value)) {
86fcf3ce44SJohn Forte case OPT_DISABLE_RCM :
87fcf3ce44SJohn Forte apidt.flags |= FLAG_DISABLE_RCM;
88fcf3ce44SJohn Forte break;
89fcf3ce44SJohn Forte case OPT_FORCE_UPDATE_REP :
90fcf3ce44SJohn Forte apidt.flags |= FLAG_FORCE_UPDATE_REP;
91fcf3ce44SJohn Forte break;
92fcf3ce44SJohn Forte case OPT_NO_UPDATE_REP :
93fcf3ce44SJohn Forte apidt.flags |= FLAG_NO_UPDATE_REP;
94fcf3ce44SJohn Forte break;
95fcf3ce44SJohn Forte case OPT_REMOVE_UNUSABLE_FCP_DEV :
96fcf3ce44SJohn Forte case OPT_REMOVE_UNUSABLE_SCSI_LUN:
97fcf3ce44SJohn Forte if (state_change_cmd != CFGA_CMD_UNCONFIGURE) {
98fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_OPT_INVAL,
99fcf3ce44SJohn Forte options, 0);
100fcf3ce44SJohn Forte S_FREE(hw_option);
101fcf3ce44SJohn Forte apidt_free(&apidt);
102fcf3ce44SJohn Forte return (CFGA_ERROR);
103fcf3ce44SJohn Forte }
104fcf3ce44SJohn Forte apidt.flags |= FLAG_REMOVE_UNUSABLE_FCP_DEV;
105fcf3ce44SJohn Forte break;
106fcf3ce44SJohn Forte default :
107fcf3ce44SJohn Forte /* process unknonw option. */
108fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_OPT_INVAL,
109fcf3ce44SJohn Forte options, 0);
110fcf3ce44SJohn Forte S_FREE(hw_option);
111fcf3ce44SJohn Forte apidt_free(&apidt);
112fcf3ce44SJohn Forte return (CFGA_ERROR);
113fcf3ce44SJohn Forte }
114fcf3ce44SJohn Forte }
115fcf3ce44SJohn Forte S_FREE(hw_option);
116fcf3ce44SJohn Forte }
117fcf3ce44SJohn Forte
118fcf3ce44SJohn Forte if (options != NULL && apidt.flags == 0) {
119fcf3ce44SJohn Forte /* invalid option specified. */
120fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_OPT_INVAL, options, 0);
121fcf3ce44SJohn Forte apidt_free(&apidt);
122fcf3ce44SJohn Forte return (CFGA_ERROR);
123fcf3ce44SJohn Forte }
124fcf3ce44SJohn Forte
125fcf3ce44SJohn Forte if (apidt.dyncomp != NULL) { /* Was there a port WWN passed ? */
126fcf3ce44SJohn Forte /*
127fcf3ce44SJohn Forte * Yes - so change state of the particular device
128fcf3ce44SJohn Forte *
129fcf3ce44SJohn Forte * First Get the WWN in la_wwn_t form
130fcf3ce44SJohn Forte */
131fcf3ce44SJohn Forte if (cvt_dyncomp_to_lawwn(apidt.dyncomp, &pwwn)) {
132fcf3ce44SJohn Forte cfga_err(errstring, 0, ERR_APID_INVAL, 0);
133fcf3ce44SJohn Forte return (err_cvt(FPCFGA_LIB_ERR));
134fcf3ce44SJohn Forte }
135fcf3ce44SJohn Forte
136fcf3ce44SJohn Forte if ((ret = findMatchingAdapterPort(apidt.xport_phys,
137fcf3ce44SJohn Forte &handle, &portIndex, &portAttrs, errstring)) ==
138fcf3ce44SJohn Forte FPCFGA_OK) {
139fcf3ce44SJohn Forte ret = dev_change_state(state_change_cmd, &apidt, &pwwn,
140fcf3ce44SJohn Forte flags, errstring, handle, portAttrs);
141fcf3ce44SJohn Forte HBA_CloseAdapter(handle);
142fcf3ce44SJohn Forte HBA_FreeLibrary();
143fcf3ce44SJohn Forte }
144fcf3ce44SJohn Forte } else {
145fcf3ce44SJohn Forte /* Change state of all devices on FCA and the FCA itself */
146fcf3ce44SJohn Forte ret = fca_change_state(state_change_cmd, &apidt,
147fcf3ce44SJohn Forte flags, errstring);
148fcf3ce44SJohn Forte }
149fcf3ce44SJohn Forte
150fcf3ce44SJohn Forte apidt_free(&apidt);
151fcf3ce44SJohn Forte return (err_cvt(ret));
152fcf3ce44SJohn Forte }
153fcf3ce44SJohn Forte
154fcf3ce44SJohn Forte
155fcf3ce44SJohn Forte /*ARGSUSED*/
156fcf3ce44SJohn Forte cfga_err_t
cfga_private_func(const char * func,const char * ap_id,const char * options,struct cfga_confirm * confp,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)157fcf3ce44SJohn Forte cfga_private_func(
158fcf3ce44SJohn Forte const char *func,
159fcf3ce44SJohn Forte const char *ap_id,
160fcf3ce44SJohn Forte const char *options,
161fcf3ce44SJohn Forte struct cfga_confirm *confp,
162fcf3ce44SJohn Forte struct cfga_msg *msgp,
163fcf3ce44SJohn Forte char **errstring,
164fcf3ce44SJohn Forte cfga_flags_t flags)
165fcf3ce44SJohn Forte {
166fcf3ce44SJohn Forte if (errstring != NULL) {
167fcf3ce44SJohn Forte *errstring = NULL;
168fcf3ce44SJohn Forte }
169fcf3ce44SJohn Forte
170fcf3ce44SJohn Forte if (geteuid() != 0) {
171fcf3ce44SJohn Forte return (CFGA_PRIV);
172fcf3ce44SJohn Forte }
173fcf3ce44SJohn Forte
174fcf3ce44SJohn Forte return (CFGA_OPNOTSUPP);
175fcf3ce44SJohn Forte }
176fcf3ce44SJohn Forte
177fcf3ce44SJohn Forte
178fcf3ce44SJohn Forte /*ARGSUSED*/
179fcf3ce44SJohn Forte cfga_err_t
cfga_test(const char * ap_id,const char * options,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)180fcf3ce44SJohn Forte cfga_test(
181fcf3ce44SJohn Forte const char *ap_id,
182fcf3ce44SJohn Forte const char *options,
183fcf3ce44SJohn Forte struct cfga_msg *msgp,
184fcf3ce44SJohn Forte char **errstring,
185fcf3ce44SJohn Forte cfga_flags_t flags)
186fcf3ce44SJohn Forte {
187fcf3ce44SJohn Forte if (errstring != NULL) {
188fcf3ce44SJohn Forte *errstring = NULL;
189fcf3ce44SJohn Forte }
190fcf3ce44SJohn Forte
191fcf3ce44SJohn Forte if (geteuid() != 0) {
192fcf3ce44SJohn Forte return (CFGA_PRIV);
193fcf3ce44SJohn Forte }
194fcf3ce44SJohn Forte
195fcf3ce44SJohn Forte return (CFGA_OPNOTSUPP);
196fcf3ce44SJohn Forte }
197fcf3ce44SJohn Forte
198fcf3ce44SJohn Forte
199fcf3ce44SJohn Forte /*ARGSUSED*/
200fcf3ce44SJohn Forte cfga_err_t
cfga_list_ext(const char * ap_id,cfga_list_data_t ** ap_id_list,int * nlistp,const char * options,const char * listopts,char ** errstring,cfga_flags_t flags)201fcf3ce44SJohn Forte cfga_list_ext(
202fcf3ce44SJohn Forte const char *ap_id,
203fcf3ce44SJohn Forte cfga_list_data_t **ap_id_list,
204fcf3ce44SJohn Forte int *nlistp,
205fcf3ce44SJohn Forte const char *options,
206fcf3ce44SJohn Forte const char *listopts,
207fcf3ce44SJohn Forte char **errstring,
208fcf3ce44SJohn Forte cfga_flags_t flags)
209fcf3ce44SJohn Forte {
210fcf3ce44SJohn Forte int fca, expand, nelem;
211fcf3ce44SJohn Forte ldata_list_t *ldatalistp = NULL;
212fcf3ce44SJohn Forte apid_t apidt = {NULL};
213fcf3ce44SJohn Forte fpcfga_cmd_t cmd;
214fcf3ce44SJohn Forte fpcfga_ret_t ret;
215fcf3ce44SJohn Forte char *value, *hw_option, *hw_option_p;
216fcf3ce44SJohn Forte uint_t fp_flags = 0;
217fcf3ce44SJohn Forte char *fp_list_hw_opts[] = {"devinfo_force", "show_SCSI_LUN",
218fcf3ce44SJohn Forte "show_FCP_dev", NULL};
219fcf3ce44SJohn Forte
220fcf3ce44SJohn Forte if (errstring != NULL) {
221fcf3ce44SJohn Forte *errstring = NULL;
222fcf3ce44SJohn Forte }
223fcf3ce44SJohn Forte
224fcf3ce44SJohn Forte /* Check for super user privileges */
225fcf3ce44SJohn Forte if (geteuid() != 0) {
226fcf3ce44SJohn Forte return (CFGA_PRIV);
227fcf3ce44SJohn Forte }
228fcf3ce44SJohn Forte
229fcf3ce44SJohn Forte if (ap_id_list == NULL || nlistp == NULL) {
230fcf3ce44SJohn Forte return (CFGA_ERROR);
231fcf3ce44SJohn Forte }
232fcf3ce44SJohn Forte
233fcf3ce44SJohn Forte *ap_id_list = NULL;
234fcf3ce44SJohn Forte *nlistp = 0;
235fcf3ce44SJohn Forte
236fcf3ce44SJohn Forte if (options != NULL) {
237fcf3ce44SJohn Forte hw_option = calloc(1, strlen(options) + 1);
238fcf3ce44SJohn Forte (void) snprintf(hw_option, strlen(options) + 1, "%s", options);
239fcf3ce44SJohn Forte hw_option_p = hw_option;
240fcf3ce44SJohn Forte /* Use getsubopt() if more options get added */
241fcf3ce44SJohn Forte while (*hw_option_p != '\0') {
2422c2d21e9SRichard Lowe switch (getsubopt(&hw_option_p, fp_list_hw_opts,
2432c2d21e9SRichard Lowe &value)) {
244fcf3ce44SJohn Forte case OPT_DEVINFO_FORCE :
245fcf3ce44SJohn Forte fp_flags |= FLAG_DEVINFO_FORCE;
246fcf3ce44SJohn Forte break;
247fcf3ce44SJohn Forte case OPT_FCP_DEV :
248fcf3ce44SJohn Forte case OPT_SHOW_SCSI_LUN:
249fcf3ce44SJohn Forte fp_flags |= FLAG_FCP_DEV;
250fcf3ce44SJohn Forte break;
251fcf3ce44SJohn Forte default :
252fcf3ce44SJohn Forte /* process unknonw option. */
253fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_OPT_INVAL,
254fcf3ce44SJohn Forte options, 0);
255fcf3ce44SJohn Forte S_FREE(hw_option);
256fcf3ce44SJohn Forte return (CFGA_ERROR);
257fcf3ce44SJohn Forte }
258fcf3ce44SJohn Forte }
259fcf3ce44SJohn Forte S_FREE(hw_option);
260fcf3ce44SJohn Forte }
261fcf3ce44SJohn Forte
262fcf3ce44SJohn Forte /* if force_devinfo is specified check uid = 0 or not. */
263fcf3ce44SJohn Forte if (((fp_flags & FLAG_DEVINFO_FORCE) == FLAG_DEVINFO_FORCE) &&
264fcf3ce44SJohn Forte (geteuid() != 0)) {
265fcf3ce44SJohn Forte return (CFGA_PRIV);
266fcf3ce44SJohn Forte }
267fcf3ce44SJohn Forte
268fcf3ce44SJohn Forte fca = 0;
269fcf3ce44SJohn Forte if (GET_DYN(ap_id) == NULL) {
270fcf3ce44SJohn Forte fca = 1;
271fcf3ce44SJohn Forte }
272fcf3ce44SJohn Forte
273fcf3ce44SJohn Forte expand = 0;
274fcf3ce44SJohn Forte if ((flags & CFGA_FLAG_LIST_ALL) == CFGA_FLAG_LIST_ALL) {
275fcf3ce44SJohn Forte expand = 1;
276fcf3ce44SJohn Forte }
277fcf3ce44SJohn Forte
278fcf3ce44SJohn Forte /*
279fcf3ce44SJohn Forte * We expand published attachment points but not
280fcf3ce44SJohn Forte * dynamic attachment points
281fcf3ce44SJohn Forte */
282fcf3ce44SJohn Forte
283fcf3ce44SJohn Forte if (!fca) { /* Stat a single device - no expansion for devices */
284fcf3ce44SJohn Forte cmd = FPCFGA_STAT_FC_DEV;
285fcf3ce44SJohn Forte } else if (!expand) { /* Stat only the HBA */
286fcf3ce44SJohn Forte cmd = FPCFGA_STAT_FCA_PORT;
287fcf3ce44SJohn Forte } else { /* Expand HBA attachment point */
288fcf3ce44SJohn Forte cmd = FPCFGA_STAT_ALL;
289fcf3ce44SJohn Forte }
290fcf3ce44SJohn Forte
291fcf3ce44SJohn Forte ldatalistp = NULL;
292fcf3ce44SJohn Forte nelem = 0;
293fcf3ce44SJohn Forte
294fcf3ce44SJohn Forte if ((fp_flags & FLAG_FCP_DEV) == FLAG_FCP_DEV) {
295fcf3ce44SJohn Forte ret = do_list_FCP_dev(ap_id, fp_flags, cmd, &ldatalistp, &nelem,
296fcf3ce44SJohn Forte errstring);
297fcf3ce44SJohn Forte if (ret != FPCFGA_OK) {
298fcf3ce44SJohn Forte list_free(&ldatalistp);
299fcf3ce44SJohn Forte return (err_cvt(ret));
300fcf3ce44SJohn Forte }
301fcf3ce44SJohn Forte } else {
302fcf3ce44SJohn Forte if ((ret = apidt_create(ap_id, &apidt, errstring))
303fcf3ce44SJohn Forte != FPCFGA_OK) {
304fcf3ce44SJohn Forte return (err_cvt(ret));
305fcf3ce44SJohn Forte }
306fcf3ce44SJohn Forte
307fcf3ce44SJohn Forte if (options != NULL) {
308fcf3ce44SJohn Forte apidt.flags |= fp_flags;
309fcf3ce44SJohn Forte }
310fcf3ce44SJohn Forte
311fcf3ce44SJohn Forte ret = do_list(&apidt, cmd, &ldatalistp, &nelem, errstring);
312fcf3ce44SJohn Forte if (ret != FPCFGA_OK) {
313fcf3ce44SJohn Forte list_free(&ldatalistp);
314fcf3ce44SJohn Forte apidt_free(&apidt);
315fcf3ce44SJohn Forte return (err_cvt(ret));
316fcf3ce44SJohn Forte }
317fcf3ce44SJohn Forte apidt_free(&apidt);
318fcf3ce44SJohn Forte }
319fcf3ce44SJohn Forte
320fcf3ce44SJohn Forte assert(ldatalistp != NULL);
321fcf3ce44SJohn Forte
322fcf3ce44SJohn Forte if (list_ext_postprocess(&ldatalistp, nelem, ap_id_list, nlistp,
323fcf3ce44SJohn Forte errstring) != FPCFGA_OK) {
324fcf3ce44SJohn Forte assert(*ap_id_list == NULL && *nlistp == 0);
325fcf3ce44SJohn Forte ret = FPCFGA_LIB_ERR;
326fcf3ce44SJohn Forte } else {
327fcf3ce44SJohn Forte assert(*ap_id_list != NULL && *nlistp == nelem);
328fcf3ce44SJohn Forte ret = FPCFGA_OK;
329fcf3ce44SJohn Forte }
330fcf3ce44SJohn Forte
331fcf3ce44SJohn Forte list_free(&ldatalistp);
332fcf3ce44SJohn Forte return (err_cvt(ret));
333fcf3ce44SJohn Forte }
334fcf3ce44SJohn Forte
335fcf3ce44SJohn Forte
336fcf3ce44SJohn Forte /*ARGSUSED*/
337fcf3ce44SJohn Forte cfga_err_t
cfga_help(struct cfga_msg * msgp,const char * options,cfga_flags_t flags)338fcf3ce44SJohn Forte cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
339fcf3ce44SJohn Forte {
340fcf3ce44SJohn Forte cfga_msg(msgp, MSG_HELP_HDR, MSG_HELP_USAGE, 0);
341fcf3ce44SJohn Forte
342fcf3ce44SJohn Forte return (CFGA_OK);
343fcf3ce44SJohn Forte
344fcf3ce44SJohn Forte }
345fcf3ce44SJohn Forte
346fcf3ce44SJohn Forte int
cfga_ap_id_cmp(const cfga_ap_log_id_t ap_id1,const cfga_ap_log_id_t ap_id2)347f02e918dSToomas Soome cfga_ap_id_cmp(const cfga_ap_log_id_t ap_id1, const cfga_ap_log_id_t ap_id2)
348fcf3ce44SJohn Forte {
349fcf3ce44SJohn Forte int i = 0;
350fcf3ce44SJohn Forte long long ret;
351fcf3ce44SJohn Forte
352fcf3ce44SJohn Forte if (ap_id1 == ap_id2) {
353fcf3ce44SJohn Forte return (0);
354fcf3ce44SJohn Forte }
355fcf3ce44SJohn Forte
356fcf3ce44SJohn Forte if (ap_id1 == NULL || ap_id2 == NULL) {
357fcf3ce44SJohn Forte if (ap_id1 == NULL) {
358fcf3ce44SJohn Forte /* Return a negative value */
359fcf3ce44SJohn Forte return (0 - (uchar_t)ap_id2[0]);
360fcf3ce44SJohn Forte } else {
361fcf3ce44SJohn Forte return ((uchar_t)ap_id1[0]);
362fcf3ce44SJohn Forte }
363fcf3ce44SJohn Forte }
364fcf3ce44SJohn Forte
365fcf3ce44SJohn Forte /*
366fcf3ce44SJohn Forte * Search for first different char
367fcf3ce44SJohn Forte */
368fcf3ce44SJohn Forte while (ap_id1[i] == ap_id2[i] && ap_id1[i] != '\0')
369fcf3ce44SJohn Forte i++;
370fcf3ce44SJohn Forte
371fcf3ce44SJohn Forte if ((ap_id1[i] == '\0') &&
372fcf3ce44SJohn Forte !(strncmp(&ap_id2[i], LUN_COMP_SEP, strlen(LUN_COMP_SEP)))) {
373fcf3ce44SJohn Forte return (0);
374fcf3ce44SJohn Forte } else if ((ap_id2[i] == '\0') &&
375fcf3ce44SJohn Forte !(strncmp(&ap_id1[i], LUN_COMP_SEP, strlen(LUN_COMP_SEP)))) {
376fcf3ce44SJohn Forte return (0);
377fcf3ce44SJohn Forte }
378fcf3ce44SJohn Forte
379fcf3ce44SJohn Forte /*
380fcf3ce44SJohn Forte * If one of the char is a digit, back up to where the
381fcf3ce44SJohn Forte * number started, compare the number.
382fcf3ce44SJohn Forte */
383fcf3ce44SJohn Forte if (isxdigit(ap_id1[i]) || isxdigit(ap_id2[i])) {
384fcf3ce44SJohn Forte while ((i > 0) && isxdigit(ap_id1[i - 1]))
385fcf3ce44SJohn Forte i--;
386fcf3ce44SJohn Forte
387fcf3ce44SJohn Forte if (isxdigit(ap_id1[i]) && isxdigit(ap_id2[i])) {
388fcf3ce44SJohn Forte ret = (strtoll((ap_id1 + i), NULL, 16)) -
389fcf3ce44SJohn Forte (strtoll((ap_id2 + i), NULL, 16));
390fcf3ce44SJohn Forte if (ret > 0) {
391fcf3ce44SJohn Forte return (1);
392fcf3ce44SJohn Forte } else if (ret < 0) {
393fcf3ce44SJohn Forte return (-1);
394fcf3ce44SJohn Forte } else {
395fcf3ce44SJohn Forte return (0);
396fcf3ce44SJohn Forte }
397fcf3ce44SJohn Forte }
398fcf3ce44SJohn Forte }
399fcf3ce44SJohn Forte
400fcf3ce44SJohn Forte /* One of them isn't a number, compare the char */
401fcf3ce44SJohn Forte return (ap_id1[i] - ap_id2[i]);
402fcf3ce44SJohn Forte }
403