| /* |
| * Copyright (c) 2000-2001 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it would be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <time.h> |
| #include <stdlib.h> |
| #include <sys/dirent.h> |
| #include <stdio.h> |
| #include <getopt.h> |
| #include <assert.h> |
| |
| #include "config.h" |
| |
| #include "types.h" |
| #include "util.h" |
| #include "mlog.h" |
| #include "getopt.h" |
| #include "stream.h" |
| #include "global.h" |
| #include "drive.h" |
| #include "media.h" |
| |
| /* media.c - selects and initializes a media strategy |
| */ |
| |
| |
| /* declarations of externally defined global symbols *************************/ |
| |
| extern void usage(void); |
| |
| /* declare all media strategies here |
| */ |
| extern media_strategy_t media_strategy_simple; |
| extern media_strategy_t media_strategy_rmvtape; |
| |
| |
| /* forward declarations of locally defined static functions ******************/ |
| |
| static media_t *media_alloc(drive_t *, char *); |
| |
| |
| /* definition of locally defined global variables ****************************/ |
| |
| |
| /* definition of locally defined static variables *****************************/ |
| |
| /* media strategy array - ordered by precedence |
| */ |
| static media_strategy_t *strategyp[] = { |
| &media_strategy_simple, |
| &media_strategy_rmvtape, |
| }; |
| |
| |
| /* definition of locally defined global functions ****************************/ |
| |
| /* media_create - select and initialize a media strategy. |
| * and create and initialize media managers for each stream. |
| */ |
| media_strategy_t * |
| media_create(int argc, char *argv[], drive_strategy_t *dsp) |
| { |
| int c; |
| size_t mediaix; |
| size_t mediacnt; |
| media_t **mediapp; |
| char *medialabel; |
| media_strategy_t **spp = strategyp; |
| media_strategy_t **epp = strategyp + sizeof(strategyp) |
| / |
| sizeof(strategyp[0]); |
| media_strategy_t *chosen_sp; |
| int id; |
| bool_t ok; |
| |
| /* sanity check asserts |
| */ |
| assert(sizeof(media_hdr_t) == MEDIA_HDR_SZ); |
| assert(MEDIA_MARKLOG_SZ == sizeof(media_marklog_t)); |
| |
| /* scan the command line for a media label |
| */ |
| medialabel = 0; |
| optind = 1; |
| opterr = 0; |
| while ((c = getopt(argc, argv, GETOPT_CMDSTRING)) != EOF) { |
| switch (c) { |
| #ifdef DUMP |
| case GETOPT_MEDIALABEL: |
| if (medialabel) { |
| mlog(MLOG_NORMAL, |
| _("too many -%c arguments: " |
| "\"-%c %s\" already given\n"), |
| c, |
| c, |
| medialabel); |
| usage(); |
| return 0; |
| } |
| if (!optarg || optarg[0] == '-') { |
| mlog(MLOG_NORMAL, |
| _("-%c argument missing\n"), |
| c); |
| usage(); |
| return 0; |
| } |
| medialabel = optarg; |
| break; |
| #endif /* DUMP */ |
| } |
| } |
| |
| /* if no media label specified, synthesize one |
| */ |
| if (!medialabel) { |
| /* not useful |
| mlog(MLOG_VERBOSE, |
| _("WARNING: no media label specified\n")); |
| */ |
| medialabel = ""; |
| } |
| |
| /* create a media_t array, and a media_ts for each drive. |
| * Initialize each media_t's generic portions. these will |
| * be lended to each media strategy during the strategy |
| * match phase, and given to the winning strategy. |
| */ |
| mediacnt = dsp->ds_drivecnt; |
| mediapp = (media_t **)calloc(mediacnt, sizeof(media_t *)); |
| assert(mediapp); |
| for (mediaix = 0; mediaix < mediacnt; mediaix++) { |
| mediapp[mediaix] = media_alloc(dsp->ds_drivep[mediaix], |
| medialabel); |
| } |
| |
| /* choose the first strategy which claims appropriateness. |
| * if none match, return null. Also, initialize the strategy ID |
| * and pointer to the drive strategy. the ID is simply the index |
| * of the strategy in the strategy array. it is placed in the |
| * media_strategy_t as well as the write headers. |
| */ |
| chosen_sp = 0; |
| for (id = 0; spp < epp; spp++, id++) { |
| (*spp)->ms_id = id; |
| if (!chosen_sp) { |
| /* lend the media_t array to the strategy |
| */ |
| (*spp)->ms_mediap = mediapp; |
| (*spp)->ms_dsp = dsp; |
| (*spp)->ms_mediacnt = mediacnt; |
| for (mediaix = 0; mediaix < mediacnt; mediaix++) { |
| media_t *mediap = mediapp[mediaix]; |
| mediap->m_strategyp = *spp; |
| mediap->m_writehdrp->mh_strategyid = id; |
| } |
| if ((*(*spp)->ms_match)(argc, argv, dsp)) { |
| chosen_sp = *spp; |
| } |
| } |
| } |
| if (!chosen_sp) { |
| mlog(MLOG_NORMAL, |
| #ifdef DUMP |
| _("no media strategy available for selected " |
| "dump destination(s)\n") |
| #endif /* DUMP */ |
| #ifdef RESTORE |
| _("no media strategy available for selected " |
| "restore source(s)\n") |
| #endif /* RESTORE */ |
| ); |
| usage(); |
| return 0; |
| } |
| |
| /* give the media_t array to the chosen strategy |
| */ |
| for (mediaix = 0; mediaix < mediacnt; mediaix++) { |
| media_t *mediap = mediapp[mediaix]; |
| mediap->m_strategyp = chosen_sp; |
| mediap->m_writehdrp->mh_strategyid = chosen_sp->ms_id; |
| } |
| |
| /* initialize the strategy. this will cause each of the managers |
| * to be initialized as well. if error, return 0. |
| */ |
| ok = (*chosen_sp->ms_create)(chosen_sp, argc, argv); |
| if (!ok) { |
| return 0; |
| } |
| |
| /* return the selected strategy |
| */ |
| return chosen_sp; |
| } |
| |
| bool_t |
| media_init(media_strategy_t *msp, int argc, char *argv[]) |
| { |
| bool_t ok; |
| |
| ok = (*msp->ms_init)(msp, argc, argv); |
| |
| return ok; |
| } |
| |
| void |
| media_complete(media_strategy_t *msp) |
| { |
| (*msp->ms_complete)(msp); |
| } |
| |
| /* media_get_upper_hdrs - supply pointers to portion of media file headers |
| * set aside for upper software layers, as well as to the global hdrs |
| */ |
| void |
| media_get_upper_hdrs(media_t *mediap, |
| global_hdr_t **grhdrpp, |
| char **rhdrpp, |
| size_t *rhdrszp, |
| global_hdr_t **gwhdrpp, |
| char **whdrpp, |
| size_t *whdrszp) |
| { |
| *grhdrpp = mediap->m_greadhdrp; |
| *rhdrpp = mediap->m_readhdrp->mh_upper; |
| *rhdrszp = sizeof(mediap->m_readhdrp->mh_upper); |
| |
| *gwhdrpp = mediap->m_gwritehdrp; |
| *whdrpp = mediap->m_writehdrp->mh_upper; |
| *whdrszp = sizeof(mediap->m_writehdrp->mh_upper); |
| } |
| |
| |
| /* definition of locally defined static functions ****************************/ |
| |
| /* media_alloc - allocate and initialize the generic portions of a media |
| * descriptor and read and write media headers |
| */ |
| static media_t * |
| media_alloc(drive_t *drivep, |
| char *medialabel) |
| { |
| media_t *mediap; |
| global_hdr_t *grhdrp; |
| global_hdr_t *gwhdrp; |
| media_hdr_t *mrhdrp; |
| media_hdr_t *mwhdrp; |
| size_t mrhdrsz; |
| size_t mwhdrsz; |
| |
| mediap = (media_t *)calloc(1, sizeof(media_t)); |
| assert(mediap); |
| |
| grhdrp = 0; |
| gwhdrp = 0; |
| mrhdrp = 0; |
| mwhdrp = 0; |
| drive_get_upper_hdrs(drivep, |
| &grhdrp, |
| (char **)&mrhdrp, |
| &mrhdrsz, |
| &gwhdrp, |
| (char **)&mwhdrp, |
| &mwhdrsz); |
| assert(grhdrp); |
| assert(gwhdrp); |
| assert(mrhdrp); |
| assert(mwhdrp); |
| assert(mrhdrsz == MEDIA_HDR_SZ); |
| assert(mwhdrsz == MEDIA_HDR_SZ); |
| |
| mediap->m_greadhdrp = grhdrp; |
| mediap->m_gwritehdrp = gwhdrp; |
| mediap->m_readhdrp = mrhdrp; |
| mediap->m_writehdrp = mwhdrp; |
| mediap->m_drivep = drivep; |
| |
| strncpyterm(mwhdrp->mh_medialabel, |
| medialabel, |
| sizeof(mwhdrp->mh_medialabel)); |
| |
| #ifdef DUMP |
| uuid_create(mwhdrp->mh_mediaid); |
| #else /* DUMP */ |
| uuid_clear(mwhdrp->mh_mediaid); |
| #endif /* DUMP */ |
| |
| return mediap; |
| } |