Imported Upstream version 3.2.0
[debian/amanda] / ndmp-src / ndma_cops_query.c
1 /*
2  * Copyright (c) 1998,1999,2000
3  *      Traakan, Inc., Los Altos, CA
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 /*
30  * Project:  NDMJOB
31  * Ident:    $Id: $
32  *
33  * Description:
34  *
35  */
36
37
38 #include "ndmagents.h"
39
40
41 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
42
43
44 int
45 ndmca_op_query (struct ndm_session *sess)
46 {
47         ndmca_opq_data(sess);
48         ndmca_opq_tape(sess);
49         ndmca_opq_robot(sess);
50         return 0;
51 }
52
53 int
54 ndmca_opq_data (struct ndm_session *sess)
55 {
56         struct ndm_job_param *  job = &sess->control_acb.job;
57         int                     rc;
58
59         if (job->data_agent.conn_type == NDMCONN_TYPE_NONE)
60                 return 0;
61
62         rc = ndmca_connect_data_agent (sess);
63         if (rc) {
64                 ndmconn_destruct (sess->plumb.data);
65                 return rc;      /* already tattled */
66         }
67
68         ndmalogqr (sess, "");
69         ndmalogqr (sess, "Data Agent %s NDMPv%d",
70                 job->data_agent.host,
71                 sess->plumb.data->protocol_version);
72         ndmca_opq_host_info (sess, sess->plumb.data);
73         ndmca_opq_get_mover_type (sess, sess->plumb.data);
74         ndmca_opq_get_butype_attr (sess, sess->plumb.data);
75 #ifndef NDMOS_OPTION_NO_NDMP3
76         if (sess->plumb.data->protocol_version == NDMP3VER) {
77                 ndmca_opq_get_fs_info (sess, sess->plumb.data);
78         }
79 #endif /* !NDMOS_OPTION_NO_NDMP3 */
80 #ifndef NDMOS_OPTION_NO_NDMP4
81         if (sess->plumb.data->protocol_version == NDMP4VER) {
82                 ndmca_opq_get_fs_info (sess, sess->plumb.data);
83         }
84 #endif /* !NDMOS_OPTION_NO_NDMP4 */
85
86         return 0;
87 }
88
89 int
90 ndmca_opq_tape (struct ndm_session *sess)
91 {
92         struct ndm_job_param *  job = &sess->control_acb.job;
93         int                     rc;
94
95         if (job->tape_agent.conn_type == NDMCONN_TYPE_NONE)
96                 return 0;
97
98         rc = ndmca_connect_tape_agent (sess);
99         if (rc) {
100                 ndmconn_destruct (sess->plumb.tape);
101                 return rc;      /* already tattled */
102         }
103
104         ndmalogqr (sess, "");
105         ndmalogqr (sess, "Tape Agent %s NDMPv%d",
106                 job->tape_agent.host,
107                 sess->plumb.tape->protocol_version);
108         if (sess->plumb.tape != sess->plumb.data) {     /* don't be boring */
109                 ndmca_opq_host_info (sess, sess->plumb.tape);
110                 ndmca_opq_get_mover_type (sess, sess->plumb.tape);
111         }
112
113 #ifndef NDMOS_OPTION_NO_NDMP3
114         if (sess->plumb.tape->protocol_version == NDMP3VER) {
115                 ndmca_opq_get_tape_info (sess, sess->plumb.tape);
116         }
117 #endif /* !NDMOS_OPTION_NO_NDMP3 */
118 #ifndef NDMOS_OPTION_NO_NDMP4
119         if (sess->plumb.tape->protocol_version == NDMP4VER) {
120                 ndmca_opq_get_tape_info (sess, sess->plumb.tape);
121         }
122 #endif /* !NDMOS_OPTION_NO_NDMP4 */
123
124         return 0;
125 }
126
127 int
128 ndmca_opq_robot (struct ndm_session *sess)
129 {
130         struct ndm_job_param *  job = &sess->control_acb.job;
131         int                     rc;
132
133         if (job->robot_agent.conn_type == NDMCONN_TYPE_NONE
134          && !job->have_robot)
135                 return 0;
136
137         rc = ndmca_connect_robot_agent (sess);
138         if (rc)
139                 return rc;      /* already tattled */
140
141         ndmalogqr (sess, "");
142         ndmalogqr (sess, "Robot Agent %s NDMPv%d",
143                 job->robot_agent.host,
144                 sess->plumb.robot->protocol_version);
145
146         if (sess->plumb.robot != sess->plumb.data
147          && sess->plumb.robot != sess->plumb.tape) {
148                 /* don't be boring */
149                 ndmca_opq_host_info (sess, sess->plumb.robot);
150         }
151
152 #ifndef NDMOS_OPTION_NO_NDMP3
153         if (sess->plumb.robot->protocol_version == NDMP3VER) {
154                 ndmca_opq_get_scsi_info (sess, sess->plumb.robot);
155         }
156 #endif /* !NDMOS_OPTION_NO_NDMP3 */
157 #ifndef NDMOS_OPTION_NO_NDMP4
158         if (sess->plumb.robot->protocol_version == NDMP4VER) {
159                 ndmca_opq_get_scsi_info (sess, sess->plumb.robot);
160         }
161 #endif /* !NDMOS_OPTION_NO_NDMP4 */
162
163         if (job->have_robot) {
164                 if (ndmca_robot_prep_target(sess)) {
165                         ndmalogqr (sess, "  robot init failed");
166                         return -1;
167                 }
168
169                 ndmca_robot_query (sess);
170         }
171
172         return 0;
173 }
174
175 int
176 ndmca_opq_host_info (struct ndm_session *sess, struct ndmconn *conn)
177 {
178         int             rc;
179         unsigned int    i;
180         char            buf[100];
181
182         switch (conn->protocol_version) {
183         default:
184                 ndmalogqr (sess, "  Host info NDMPv???? %d",
185                                 conn->protocol_version);
186                 ndmalogqr (sess, "    INTERNAL ERROR, CHECK BUILD");
187                 break;
188
189 #ifndef NDMOS_OPTION_NO_NDMP2
190         case NDMP2VER:
191             NDMC_WITH_VOID_REQUEST(ndmp2_config_get_host_info, NDMP2VER)
192                 rc = NDMC_CALL(conn);
193                 if (rc) {
194                         ndmalogqr (sess, "get_host_info failed");
195                         return rc;
196                 }
197
198                 ndmalogqr (sess, "  Host info");
199                 ndmalogqr (sess, "    hostname   %s", reply->hostname);
200                 ndmalogqr (sess, "    os_type    %s", reply->os_type);
201                 ndmalogqr (sess, "    os_vers    %s", reply->os_vers);
202                 ndmalogqr (sess, "    hostid     %s", reply->hostid);
203
204                 *buf = 0;
205                 for (i = 0; i < reply->auth_type.auth_type_len; i++) {
206                         ndmp2_auth_type atyp;
207
208                         atyp = reply->auth_type.auth_type_val[i];
209                         strcat (buf, " ");
210                         strcat (buf, ndmp2_auth_type_to_str (atyp));
211                 }
212
213                 ndmalogqr (sess, "    auths      (%d) %s",
214                                         reply->auth_type.auth_type_len, buf);
215                 ndmalogqr (sess, "");
216
217                 NDMC_FREE_REPLY();
218             NDMC_ENDWITH
219             break;
220 #endif /* !NDMOS_OPTION_NO_NDMP2 */
221
222 #ifndef NDMOS_OPTION_NO_NDMP3
223         case NDMP3VER:
224             NDMC_WITH_VOID_REQUEST(ndmp3_config_get_host_info, NDMP3VER)
225                 rc = NDMC_CALL(conn);
226                 if (rc) {
227                         ndmalogqr (sess, "get_host_info failed");
228                         return rc;
229                 }
230
231                 ndmalogqr (sess, "  Host info");
232                 ndmalogqr (sess, "    hostname   %s", reply->hostname);
233                 ndmalogqr (sess, "    os_type    %s", reply->os_type);
234                 ndmalogqr (sess, "    os_vers    %s", reply->os_vers);
235                 ndmalogqr (sess, "    hostid     %s", reply->hostid);
236                 ndmalogqr (sess, "");
237
238                 NDMC_FREE_REPLY();
239             NDMC_ENDWITH
240
241             NDMC_WITH_VOID_REQUEST(ndmp3_config_get_server_info, NDMP3VER)
242                 rc = NDMC_CALL(conn);
243                 if (rc) {
244                         ndmalogqr (sess, "get_server_info failed");
245                         return rc;
246                 }
247
248                 ndmalogqr (sess, "  Server info");
249
250                 ndmalogqr (sess, "    vendor     %s", reply->vendor_name);
251                 ndmalogqr (sess, "    product    %s", reply->product_name);
252                 ndmalogqr (sess, "    revision   %s", reply->revision_number);
253                 *buf = 0;
254                 for (i = 0; i < reply->auth_type.auth_type_len; i++) {
255                         ndmp3_auth_type atyp;
256
257                         atyp = reply->auth_type.auth_type_val[i];
258                         strcat (buf, " ");
259                         strcat (buf, ndmp3_auth_type_to_str (atyp));
260                 }
261                 ndmalogqr (sess, "    auths      (%d) %s",
262                                         reply->auth_type.auth_type_len, buf);
263                 ndmalogqr (sess, "");
264
265                 NDMC_FREE_REPLY();
266             NDMC_ENDWITH
267             break;
268 #endif /* !NDMOS_OPTION_NO_NDMP3 */
269
270 #ifndef NDMOS_OPTION_NO_NDMP4
271         case NDMP4VER:
272             NDMC_WITH_VOID_REQUEST(ndmp4_config_get_host_info, NDMP4VER)
273                 rc = NDMC_CALL(conn);
274                 if (rc) {
275                         ndmalogqr (sess, "get_host_info failed");
276                         return rc;
277                 }
278
279                 ndmalogqr (sess, "  Host info");
280                 ndmalogqr (sess, "    hostname   %s", reply->hostname);
281                 ndmalogqr (sess, "    os_type    %s", reply->os_type);
282                 ndmalogqr (sess, "    os_vers    %s", reply->os_vers);
283                 ndmalogqr (sess, "    hostid     %s", reply->hostid);
284                 ndmalogqr (sess, "");
285
286                 NDMC_FREE_REPLY();
287             NDMC_ENDWITH
288
289             NDMC_WITH_VOID_REQUEST(ndmp4_config_get_server_info, NDMP4VER)
290                 rc = NDMC_CALL(conn);
291                 if (rc) {
292                         ndmalogqr (sess, "get_server_info failed");
293                         return rc;
294                 }
295
296                 ndmalogqr (sess, "  Server info");
297
298                 ndmalogqr (sess, "    vendor     %s", reply->vendor_name);
299                 ndmalogqr (sess, "    product    %s", reply->product_name);
300                 ndmalogqr (sess, "    revision   %s", reply->revision_number);
301                 *buf = 0;
302                 for (i = 0; i < reply->auth_type.auth_type_len; i++) {
303                         ndmp4_auth_type atyp;
304
305                         atyp = reply->auth_type.auth_type_val[i];
306                         strcat (buf, " ");
307                         strcat (buf, ndmp4_auth_type_to_str (atyp));
308                 }
309                 ndmalogqr (sess, "    auths      (%d) %s",
310                                         reply->auth_type.auth_type_len, buf);
311                 ndmalogqr (sess, "");
312
313                 NDMC_FREE_REPLY();
314             NDMC_ENDWITH
315             break;
316 #endif /* !NDMOS_OPTION_NO_NDMP4 */
317         }
318
319         return 0;
320 }
321
322 int
323 ndmca_opq_get_mover_type (struct ndm_session *sess, struct ndmconn *conn)
324 {
325         int             rc;
326         unsigned int    i;
327         char            buf[100];
328
329         switch (conn->protocol_version) {
330         default:
331                 /* already tattled in ndmca_opq_host_info() */
332                 break;
333
334 #ifndef NDMOS_OPTION_NO_NDMP2
335         case NDMP2VER:
336             NDMC_WITH_VOID_REQUEST(ndmp2_config_get_mover_type, NDMP2VER)
337                 rc = NDMC_CALL(conn);
338                 if (rc) {
339                         ndmalogqr (sess, "get_mover_info failed");
340                         return rc;
341                 }
342
343                 ndmalogqr (sess, "  Mover types");
344
345                 *buf = 0;
346                 for (i = 0; i < reply->methods.methods_len; i++) {
347                         ndmp2_mover_addr_type   val;
348
349                         val = reply->methods.methods_val[i];
350                         strcat (buf, " ");
351                         strcat (buf, ndmp2_mover_addr_type_to_str (val));
352                 }
353                 ndmalogqr (sess, "    methods    (%d) %s",
354                                         reply->methods.methods_len,
355                                         buf);
356                 ndmalogqr (sess, "");
357
358                 NDMC_FREE_REPLY();
359             NDMC_ENDWITH
360             break;
361 #endif /* !NDMOS_OPTION_NO_NDMP2 */
362
363 #ifndef NDMOS_OPTION_NO_NDMP3
364         case NDMP3VER:
365             NDMC_WITH_VOID_REQUEST(ndmp3_config_get_connection_type, NDMP3VER)
366                 rc = NDMC_CALL(conn);
367                 if (rc) {
368                         ndmalogqr (sess, "get_connection_type failed");
369                         return rc;
370                 }
371
372                 ndmalogqr (sess, "  Connection types");
373                 *buf = 0;
374                 for (i = 0; i < reply->addr_types.addr_types_len; i++) {
375                         ndmp3_addr_type         val;
376
377                         val = reply->addr_types.addr_types_val[i];
378                         strcat (buf, " ");
379                         strcat (buf, ndmp3_addr_type_to_str (val));
380                 }
381                 ndmalogqr (sess, "    addr_types (%d) %s",
382                                         reply->addr_types.addr_types_len, buf);
383                 ndmalogqr (sess, "");
384
385                 NDMC_FREE_REPLY();
386             NDMC_ENDWITH
387             break;
388 #endif /* !NDMOS_OPTION_NO_NDMP3 */
389
390 #ifndef NDMOS_OPTION_NO_NDMP4
391         case NDMP4VER:
392             NDMC_WITH_VOID_REQUEST(ndmp4_config_get_connection_type, NDMP4VER)
393                 rc = NDMC_CALL(conn);
394                 if (rc) {
395                         ndmalogqr (sess, "get_connection_type failed");
396                         return rc;
397                 }
398
399                 ndmalogqr (sess, "  Connection types");
400                 *buf = 0;
401                 for (i = 0; i < reply->addr_types.addr_types_len; i++) {
402                         ndmp4_addr_type         val;
403
404                         val = reply->addr_types.addr_types_val[i];
405                         strcat (buf, " ");
406                         strcat (buf, ndmp4_addr_type_to_str (val));
407                 }
408                 ndmalogqr (sess, "    addr_types (%d) %s",
409                                         reply->addr_types.addr_types_len, buf);
410                 ndmalogqr (sess, "");
411
412                 NDMC_FREE_REPLY();
413             NDMC_ENDWITH
414             break;
415 #endif /* !NDMOS_OPTION_NO_NDMP4 */
416         }
417
418         return 0;
419 }
420
421 int
422 ndmca_opq_get_butype_attr (struct ndm_session *sess, struct ndmconn *conn)
423 {
424         int             rc;
425
426         switch (conn->protocol_version) {
427         default:
428                 /* already tattled in ndmca_opq_host_info() */
429                 break;
430
431 #ifndef NDMOS_OPTION_NO_NDMP2
432         case NDMP2VER:
433             NDMC_WITH(ndmp2_config_get_butype_attr, NDMP2VER)
434                 request->name = sess->control_acb.job.bu_type;
435                 rc = NDMC_CALL(conn);
436                 if (rc) {
437                         ndmalogqr (sess, "  get_butype_attr '%s' failed",
438                                         sess->control_acb.job.bu_type);
439                         return rc;
440                 }
441
442                 ndmalogqr (sess, "  Backup type attributes of %s format",
443                         sess->control_acb.job.bu_type);
444                 ndmalogqr (sess, "    backup-filelist   %s",
445                         (reply->attrs&NDMP2_NO_BACKUP_FILELIST) ? "no":"yes");
446                 ndmalogqr (sess, "    backup-fhinfo     %s",
447                         (reply->attrs&NDMP2_NO_BACKUP_FHINFO) ? "no":"yes");
448                 ndmalogqr (sess, "    recover-filelist  %s",
449                         (reply->attrs&NDMP2_NO_RECOVER_FILELIST) ? "no":"yes");
450                 ndmalogqr (sess, "    recover-fhinfo    %s",
451                         (reply->attrs&NDMP2_NO_RECOVER_FHINFO) ? "no":"yes");
452                 ndmalogqr (sess, "    recover-inc-only  %s",
453                         (reply->attrs&NDMP2_NO_RECOVER_INC_ONLY) ? "no":"yes");
454
455                 NDMC_FREE_REPLY();
456             NDMC_ENDWITH
457             break;
458 #endif /* !NDMOS_OPTION_NO_NDMP2 */
459
460 #ifndef NDMOS_OPTION_NO_NDMP3
461         case NDMP3VER:
462             NDMC_WITH_VOID_REQUEST(ndmp3_config_get_butype_info, NDMP3VER)
463                 unsigned int    i, j;
464
465                 rc = NDMC_CALL(conn);
466                 if (rc) {
467                         ndmalogqr (sess, "  get_butype_info failed");
468                         return rc;
469                 }
470
471                 for (i = 0; i < reply->butype_info.butype_info_len; i++) {
472                     ndmp3_butype_info * buti;
473
474                     buti = &reply->butype_info.butype_info_val[i];
475                     ndmalogqr (sess, "  Backup type info of %s format",
476                                 buti->butype_name);
477                     ndmalogqr (sess, "    attrs      0x%lx",
478                                 buti->attrs);
479
480                     ndmalogqr (sess, "      backup-file-history   %s",
481                                (buti->attrs&NDMP3_BUTYPE_BACKUP_FILE_HISTORY) ? "yes":"no");
482                     ndmalogqr (sess, "      backup-filelist   %s",
483                                (buti->attrs&NDMP3_BUTYPE_BACKUP_FILELIST) ? "yes":"no");
484                     ndmalogqr (sess, "      recover-filelist   %s",
485                                (buti->attrs&NDMP3_BUTYPE_RECOVER_FILELIST) ? "yes":"no");
486                     ndmalogqr (sess, "      backup-direct   %s",
487                                (buti->attrs&NDMP3_BUTYPE_BACKUP_DIRECT) ? "yes":"no");
488                     ndmalogqr (sess, "      recover-direct   %s",
489                                (buti->attrs&NDMP3_BUTYPE_RECOVER_DIRECT) ? "yes":"no");
490                     ndmalogqr (sess, "      backup-incremental   %s",
491                                (buti->attrs&NDMP3_BUTYPE_BACKUP_INCREMENTAL) ? "yes":"no");
492                     ndmalogqr (sess, "      recover-incremental   %s",
493                                (buti->attrs&NDMP3_BUTYPE_RECOVER_INCREMENTAL) ? "yes":"no");
494                     ndmalogqr (sess, "      backup-utf8   %s",
495                                (buti->attrs&NDMP3_BUTYPE_BACKUP_UTF8) ? "yes":"no");
496                     ndmalogqr (sess, "      recover-utf8   %s",
497                                (buti->attrs&NDMP3_BUTYPE_RECOVER_UTF8) ? "yes":"no");
498                     ndmalogqr (sess, "      recover-file-history   %s",
499                                (buti->attrs&NDMP3_BUTYPE_RECOVER_FILE_HISTORY) ? "yes":"no");
500
501
502
503
504                     for (j = 0; j < buti->default_env.default_env_len; j++) {
505                         ndmalogqr (sess, "    set        %s=%s",
506                                 buti->default_env.default_env_val[j].name,
507                                 buti->default_env.default_env_val[j].value);
508                     }
509                     if (j == 0)
510                         ndmalogqr (sess, "    empty default env");
511                     ndmalogqr (sess, "");
512                 }
513                 if (i == 0)
514                         ndmalogqr (sess, "  Empty backup type info");
515
516                 NDMC_FREE_REPLY();
517             NDMC_ENDWITH
518             break;
519 #endif /* !NDMOS_OPTION_NO_NDMP3 */
520
521 #ifndef NDMOS_OPTION_NO_NDMP4
522         case NDMP4VER:
523             NDMC_WITH_VOID_REQUEST(ndmp4_config_get_butype_info, NDMP4VER)
524                 unsigned int    i, j;
525
526                 rc = NDMC_CALL(conn);
527                 if (rc) {
528                         ndmalogqr (sess, "  get_butype_info failed");
529                         return rc;
530                 }
531
532                 for (i = 0; i < reply->butype_info.butype_info_len; i++) {
533                     ndmp4_butype_info * buti;
534
535                     buti = &reply->butype_info.butype_info_val[i];
536                     ndmalogqr (sess, "  Backup type info of %s format",
537                                 buti->butype_name);
538                     ndmalogqr (sess, "    attrs      0x%lx",
539                                 buti->attrs);
540                     for (j = 0; j < buti->default_env.default_env_len; j++) {
541                         ndmalogqr (sess, "    set        %s=%s",
542                                 buti->default_env.default_env_val[j].name,
543                                 buti->default_env.default_env_val[j].value);
544                     }
545                     if (j == 0)
546                         ndmalogqr (sess, "    empty default env");
547                     ndmalogqr (sess, "");
548                 }
549                 if (i == 0)
550                         ndmalogqr (sess, "  Empty backup type info");
551
552                 NDMC_FREE_REPLY();
553             NDMC_ENDWITH
554             break;
555 #endif /* !NDMOS_OPTION_NO_NDMP4 */
556         }
557
558         return 0;
559 }
560
561 #ifndef NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4
562 int
563 ndmca_opq_get_fs_info (struct ndm_session *sess, struct ndmconn *conn)
564 {
565         int             rc;
566
567         switch (conn->protocol_version) {
568         default:
569                 /* already tattled in ndmca_opq_host_info() */
570                 break;
571
572 #ifndef NDMOS_OPTION_NO_NDMP2
573         case NDMP2VER:
574                 break;  /* why are we here? */
575 #endif /* !NDMOS_OPTION_NO_NDMP2 */
576 #ifndef NDMOS_OPTION_NO_NDMP3
577         case NDMP3VER:
578             NDMC_WITH_VOID_REQUEST(ndmp3_config_get_fs_info, NDMP3VER)
579                 unsigned int    i, j;
580
581                 rc = NDMC_CALL(conn);
582                 if (rc) {
583                         ndmalogqr (sess, "  get_fs_info failed");
584                         return rc;
585                 }
586
587                 for (i = 0; i < reply->fs_info.fs_info_len; i++) {
588                         ndmp3_fs_info *         fsi;
589
590                         fsi = &reply->fs_info.fs_info_val[i];
591
592                         ndmalogqr (sess, "  File system %s",
593                                         fsi->fs_logical_device);
594
595                         ndmalogqr (sess, "    physdev    %s",
596                                         fsi->fs_physical_device);
597                         ndmalogqr (sess, "    invalid    0x%lx", fsi->invalid);
598                         if (fsi->invalid & NDMP3_FS_INFO_TOTAL_SIZE_INVALID)
599                             ndmalogqr (sess, "        TOTAL_SIZE_INVALID");
600                         if (fsi->invalid & NDMP3_FS_INFO_USED_SIZE_INVALID)
601                             ndmalogqr (sess, "        USED_SIZE_INVALID");
602                         if (fsi->invalid & NDMP3_FS_INFO_AVAIL_SIZE_INVALID)
603                             ndmalogqr (sess, "        AVAIL_SIZE_INVALID");
604
605                         if (fsi->invalid & NDMP3_FS_INFO_TOTAL_INODES_INVALID)
606                             ndmalogqr (sess, "        TOTAL_INODES_INVALID");
607                         if (fsi->invalid & NDMP3_FS_INFO_USED_INODES_INVALID)
608                             ndmalogqr (sess, "        USED_INODES_INVALID");
609                         ndmalogqr (sess, "    type       %s", fsi->fs_type);
610                         ndmalogqr (sess, "    status     %s", fsi->fs_status);
611                         ndmalogqr (sess,
612                             "    space      %lld total, %lld used, %lld avail",
613                                         fsi->total_size,
614                                         fsi->used_size,
615                                         fsi->avail_size);
616
617                         ndmalogqr (sess, "    inodes     %lld total, %lld used",
618                                         fsi->total_inodes,
619                                         fsi->used_inodes);
620
621                         for (j = 0; j < fsi->fs_env.fs_env_len; j++) {
622                                 ndmalogqr (sess, "    set        %s=%s",
623                                         fsi->fs_env.fs_env_val[j].name,
624                                         fsi->fs_env.fs_env_val[j].value);
625                         }
626                         if (j == 0)
627                                 ndmalogqr (sess, "    empty default env");
628                         ndmalogqr (sess, "");
629                 }
630                 if (i == 0)
631                         ndmalogqr (sess, "  Empty fs info");
632
633                 NDMC_FREE_REPLY();
634             NDMC_ENDWITH
635             break;
636 #endif /* !NDMOS_OPTION_NO_NDMP3 */
637 #ifndef NDMOS_OPTION_NO_NDMP4
638         case NDMP4VER:
639             NDMC_WITH_VOID_REQUEST(ndmp4_config_get_fs_info, NDMP4VER)
640                 unsigned int    i, j;
641
642                 rc = NDMC_CALL(conn);
643                 if (rc) {
644                         ndmalogqr (sess, "  get_fs_info failed");
645                         return rc;
646                 }
647
648                 for (i = 0; i < reply->fs_info.fs_info_len; i++) {
649                         ndmp4_fs_info *         fsi;
650
651                         fsi = &reply->fs_info.fs_info_val[i];
652
653                         ndmalogqr (sess, "  File system %s",
654                                         fsi->fs_logical_device);
655
656                         ndmalogqr (sess, "    physdev    %s",
657                                         fsi->fs_physical_device);
658                         ndmalogqr (sess, "    unsupported 0x%lx",
659                                                 fsi->unsupported);
660                         if (fsi->unsupported & NDMP4_FS_INFO_TOTAL_SIZE_UNS)
661                             ndmalogqr (sess, "        TOTAL_SIZE_UNS");
662                         if (fsi->unsupported & NDMP4_FS_INFO_USED_SIZE_UNS)
663                             ndmalogqr (sess, "        USED_SIZE_UNS");
664                         if (fsi->unsupported & NDMP4_FS_INFO_AVAIL_SIZE_UNS)
665                             ndmalogqr (sess, "        AVAIL_SIZE_UNS");
666
667                         if (fsi->unsupported & NDMP4_FS_INFO_TOTAL_INODES_UNS)
668                             ndmalogqr (sess, "        TOTAL_INODES_UNS");
669                         if (fsi->unsupported & NDMP4_FS_INFO_USED_INODES_UNS)
670                             ndmalogqr (sess, "        USED_INODES_UNS");
671
672
673                         ndmalogqr (sess, "    type       %s", fsi->fs_type);
674                         ndmalogqr (sess, "    status     %s", fsi->fs_status);
675                         ndmalogqr (sess,
676                             "    space      %lld total, %lld used, %lld avail",
677                                         fsi->total_size,
678                                         fsi->used_size,
679                                         fsi->avail_size);
680
681                         ndmalogqr (sess, "    inodes     %lld total, %lld used",
682                                         fsi->total_inodes,
683                                         fsi->used_inodes);
684
685                         for (j = 0; j < fsi->fs_env.fs_env_len; j++) {
686                                 ndmalogqr (sess, "    set        %s=%s",
687                                         fsi->fs_env.fs_env_val[j].name,
688                                         fsi->fs_env.fs_env_val[j].value);
689                         }
690                         if (j == 0)
691                                 ndmalogqr (sess, "    empty default env");
692                         ndmalogqr (sess, "");
693                 }
694                 if (i == 0)
695                         ndmalogqr (sess, "  Empty fs info");
696
697                 NDMC_FREE_REPLY();
698             NDMC_ENDWITH
699             break;
700 #endif /* !NDMOS_OPTION_NO_NDMP4 */
701         }
702
703         return 0;
704 }
705
706 int
707 ndmca_opq_show_device_info (struct ndm_session *sess,
708   ndmp9_device_info *info,
709   unsigned n_info, char *what)
710 {
711         unsigned int    i, j, k;
712
713         for (i = 0; i < n_info; i++) {
714                 ndmalogqr (sess, "  %s %s", what, info[i].model);
715                 for (j = 0; j < info[i].caplist.caplist_len; j++) {
716                         ndmp9_device_capability *dc;
717                         u_long attr;
718
719                         dc = &info[i].caplist.caplist_val[j];
720
721                         ndmalogqr (sess, "    device     %s", dc->device);
722                         if (!strcmp(what, "tape")) {
723 #ifndef NDMOS_OPTION_NO_NDMP3
724                             if (sess->plumb.tape->protocol_version == 3) {
725                                 attr = dc->v3attr.value;
726                                 ndmalogqr (sess, "      attr       0x%lx",
727                                            attr);
728                                 if (attr & NDMP3_TAPE_ATTR_REWIND)
729                                     ndmalogqr (sess, "        REWIND");
730                                 if (attr & NDMP3_TAPE_ATTR_UNLOAD)
731                                     ndmalogqr (sess, "        UNLOAD");
732                             }
733 #endif /* !NDMOS_OPTION_NO_NDMP3 */
734 #ifndef NDMOS_OPTION_NO_NDMP4
735                             if (sess->plumb.tape->protocol_version == 4) {
736                                 attr = dc->v4attr.value;
737                                 ndmalogqr (sess, "      attr       0x%lx",
738                                            attr);
739                                 if (attr & NDMP4_TAPE_ATTR_REWIND)
740                                     ndmalogqr (sess, "        REWIND");
741                                 if (attr & NDMP4_TAPE_ATTR_UNLOAD)
742                                     ndmalogqr (sess, "        UNLOAD");
743                             }
744 #endif /* !NDMOS_OPTION_NO_NDMP4 */
745                         }
746                         for (k = 0; k < dc->capability.capability_len; k++) {
747                                 ndmalogqr (sess, "      set        %s=%s",
748                                     dc->capability.capability_val[k].name,
749                                     dc->capability.capability_val[k].value);
750                         }
751                         if (k == 0)
752                                 ndmalogqr (sess, "      empty capabilities");
753                 }
754                 if (j == 0)
755                         ndmalogqr (sess, "    empty caplist");
756                 ndmalogqr (sess, "");
757         }
758         if (i == 0)
759                 ndmalogqr (sess, "  Empty %s info", what);
760
761         return 0;
762 }
763
764 int
765 ndmca_opq_get_tape_info (struct ndm_session *sess, struct ndmconn *conn)
766 {
767         int             rc;
768
769     NDMC_WITH_VOID_REQUEST(ndmp9_config_get_tape_info, NDMP9VER)
770         rc = NDMC_CALL(conn);
771         if (rc) {
772                 ndmalogqr (sess, "  get_tape_info failed");
773                 return rc;
774         }
775         ndmca_opq_show_device_info (sess,
776                 reply->config_info.tape_info.tape_info_val,
777                 reply->config_info.tape_info.tape_info_len,
778                 "tape");
779
780         NDMC_FREE_REPLY();
781
782         return 0;
783     NDMC_ENDWITH
784 }
785
786 int
787 ndmca_opq_get_scsi_info (struct ndm_session *sess, struct ndmconn *conn)
788 {
789         int             rc;
790
791     NDMC_WITH_VOID_REQUEST(ndmp9_config_get_scsi_info, NDMP9VER)
792         rc = NDMC_CALL(conn);
793         if (rc) {
794                 ndmalogqr (sess, "  get_scsi_info failed");
795                 return rc;
796         }
797         ndmca_opq_show_device_info (sess,
798                 reply->config_info.scsi_info.scsi_info_val,
799                 reply->config_info.scsi_info.scsi_info_len,
800                 "scsi");
801
802         NDMC_FREE_REPLY();
803
804         return 0;
805     NDMC_ENDWITH
806 }
807
808 #endif /* !NDMOS_EFFECT_NO_NDMP3_NOR_NDMP4 */
809
810 void
811 ndmalogqr (struct ndm_session *sess, char *fmt, ...)
812 {
813         va_list         ap;
814
815         va_start (ap, fmt);
816         ndmalogfv (sess, "QR", 0, fmt, ap);
817         va_end (ap);
818 }
819 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */