SMREmulator 1.0
ShingledMagneticRecordingEmulator

emudiskimg.c

Go to the documentation of this file.
00001 
00014 #include <fcntl.h>
00015 #include <errno.h>
00016 #include <unistd.h>
00017 #include <string.h>
00018 #include <stdarg.h>
00019 
00020 #include <emulator.h>
00021 #include <emudebug.h>
00022 #include <emudiskimg.h>
00023 #include <ediversion.h>
00024 #include <emulog.h>
00025 
00026 
00027 
00028 /* -- Macro Definitions -- */
00029 
00030 #define EDIOPS(fd)      edi_versions[edis[fd].version]
00031 #define LOG             edi_log
00032 #define EDI_LOG
00033 
00037 #define EDI_MAGIC_NUMBER 0xE5D10000U     // Hex for Emulated 5hingled Disk 1mage
00038 
00039 
00040 
00041 /* -- Type Definitions -- */
00042 
00049 typedef struct {
00050         int fd;
00051         uint32_t version;
00052 } edi_fd_t;
00053 
00054 
00055 
00056 /* -- Static Variables -- */
00057 static edi_fd_t edis[MAX_EDIS];
00058 static int edi_count;
00059 static edi_lops_t *edi_log;
00060 
00061 
00062 
00063 /* -- Function Implementations -- */
00064 
00082 int edi_create(const char* filename, uint32_t version, ...) {
00083         int fd, retval = -1;
00084         int oflags = O_RDWR | O_CREAT | O_EXCL;
00085         mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
00086         edi_ident_t edi_ident;
00087         va_list args;
00088 
00089 
00090         /* Validate the version */
00091         if (!ediv_is_valid(version)) {
00092                 errno = EVERSION;
00093                 return -1;
00094         }
00095         dbg("Version %d is valid.\n", version);
00096 
00097 
00098         /* Check if the version specific create() function exists */
00099         if (edi_versions[version]->create == NULL) {
00100                 errno = EUNSUPPORTED;
00101                 return -1;
00102         }
00103         dbg("Version %d is supported.\n", version);
00104 
00105 
00106         /* Process the variable arguments list */
00107         va_start(args, version);
00108         dbg("Variable arguments processed!\n");
00109 
00110 
00111         /* Create the EDI file */
00112         if ((fd = open(filename, oflags, mode)) < 0)
00113                 goto cleanup_vargs;
00114         dbg("File %s created. Open at descriptor %d...\n", filename, fd);
00115 
00116 
00117         /* Write the EDI identifier record */
00118         edi_ident.magic_no = EDI_MAGIC_NUMBER;
00119         edi_ident.version = version;
00120         if (pwrite(fd, &edi_ident, sizeof(edi_ident_t), 0) != sizeof(edi_ident_t))
00121                 goto cleanup_file;
00122         dbg("EDI Identifier written to file!");
00123 
00124 
00125         /* Call the version specific create() function to handle further tasks */
00126         if (edi_versions[version]->create(fd, args) < 0)
00127                 goto cleanup_file;
00128         dbg("Header and Metadata written out to file!\n");
00129 
00130         /* Return the file descriptor to the caller */
00131         retval = fd;
00132         goto cleanup_vargs;
00133 
00134 
00135 cleanup_file:
00136         /* Close and delete the open file */
00137         close(fd);
00138         unlink(filename);
00139 
00140 cleanup_vargs:
00141         /* Cleanup the variable arguments */
00142         va_end(args);
00143 
00144         return retval;
00145 }
00146 
00147 
00148 
00164 int edi_dump(int fd) {
00165         /* Verify the file descriptor index */
00166         if (fd >= edi_count) {
00167                 errno = EBADFD;
00168                 return -1;
00169         }
00170 
00171     /* Select the appropriate call-back function */
00172     if (EDIOPS(fd)->dump == NULL) {
00173         dbg("version[%d]->dump() not supported!\n", edis[fd].version);
00174         errno = EUNSUPPORTED;
00175         return -1;
00176     }
00177 
00178     /* Call the registered call-back function */
00179         dbg("Calling version[%d]->dump()!\n", edis[fd].version);
00180     return EDIOPS(fd)->dump(edis[fd].fd);
00181 }
00182 
00183 
00184 
00205 int edi_open(const char* filename) {
00206     /* Declare the variables needed */
00207         int edi_fd;
00208     edi_ident_t edi_ident;
00209     int ident_size = sizeof(edi_ident_t);
00210 
00211 
00212     /* Attempt to open the file for reading and writing */
00213     if ((edi_fd = open(filename, O_RDWR)) < 0)
00214         return -1;
00215     dbg("Opened EDI file %s\n", filename);
00216 
00217 
00218     /* Read the header to check if the file is a valid Emulated Disk Image */
00219     if (pread(edi_fd, &edi_ident, ident_size, 0) < ident_size) {
00220         /* Report the error */
00221         dbg("Cannot read identifier data!\n");
00222         errno = EINVALIDFILE;
00223         return -1;
00224     }
00225 
00226     /* Verify the Magic Number */
00227     if (edi_ident.magic_no != EDI_MAGIC_NUMBER) {
00228         /* Report the error */
00229         dbg("Magic Number does not match!\n");
00230         errno = EINVALIDFILE;
00231         return -1;
00232     }
00233     dbg("Magic number is good.\n");
00234 
00235 
00236     /* Verify that the version is valid and supported */
00237     if (!ediv_is_valid(edi_ident.version)) {
00238         LOG->error("Version is not valid!\n");
00239         errno = EVERSION;
00240         return -1;
00241     }
00242 
00243     if (edi_versions[edi_ident.version] == NULL) {
00244         LOG->error("Version %d is not supported by the library!\n", edi_ident.version);
00245         errno = EUNSUPPORTED;
00246         return -1;
00247     }
00248     dbg("Version is valid and supported!\n");
00249 
00250 
00251     /* Add the new file descriptor to the list of open EDI files */
00252     edis[edi_count].fd = edi_fd;
00253     edis[edi_count].version = edi_ident.version;
00254 
00255 
00256     /* Call the registered callback function, if any */
00257     if (EDIOPS(edi_count)->open != NULL) {
00258         dbg("Calling version[%d]->open()\n", edi_ident.version);
00259         if ((EDIOPS(edi_count)->open(edis[edi_count].fd)) < 0)
00260             return -1;
00261     }
00262 
00263 
00264     /* Return the index of the newly opened EDI in the open_edis array */
00265     dbg("EDI File %s opened with descriptor %d!\n", filename, edi_count);
00266     edi_count++;
00267     return (edi_count - 1);
00268 }
00269 
00270 
00271 
00285 int edi_close(int fd) {
00286         /* Verify the file descriptor index */
00287         if (fd >= edi_count) {
00288                 dbg("%d is an invalid index into the FD lookup table!\n", fd);
00289                 errno = EBADFD;
00290                 return -1;
00291         }
00292 
00293 
00294     /* Call the registered callback function, if any */
00295     if (EDIOPS(fd)->close != NULL) {
00296         dbg("Calling version[%d]->close()!\n", edis[fd].version);
00297         EDIOPS(fd)->close(edis[fd].fd);
00298     }
00299 
00300 
00301     /* Attempt to close the file */
00302     if (close(edis[fd].fd) < 0) {
00303         dbg("Cannot close EDI file!\n");
00304         return -1;
00305     }
00306         dbg("EDI file closed successfully!\n");
00307 
00308     return 0;
00309 }
00310 
00311 
00312 
00334 int edi_modesense(int fd, inq_t inq, void *data) {
00335 #ifdef EDI_LOG
00336         /* Log the function call */
00337         switch(inq) {
00338         case INQ_BLKSIZE:
00339                 LOG->info("edi_modesense(fd=%d, inq=BLK_SIZE, data=%p)\n", fd, data);
00340                 break;
00341 
00342         case INQ_BNDCOUNT:
00343                 LOG->info("edi_modesense(fd=%d, inq=BAND_COUNT, data=%p)\n", fd, data);
00344                 break;
00345 
00346         }
00347 #endif
00348 
00349 
00350         /* Verify the file descriptor index */
00351         if (fd >= edi_count) {
00352                 errno = EBADFD;
00353                 return -1;
00354         }
00355 
00356     /* Select the appropriate call-back function */
00357     if (EDIOPS(fd)->modesense == NULL) {
00358         dbg("version[%d]->modesense() not supported!\n", edis[fd].version);
00359         errno = EUNSUPPORTED;
00360         return -1;
00361     }
00362 
00363     /* Call the registered call-back function */
00364         dbg("Calling version[%d]->modesense()!\n", edis[fd].version);
00365     return EDIOPS(fd)->modesense(edis[fd].fd, inq, data);
00366 }
00367 
00368 
00369 
00417 int edi_managebands(int fd, svc_act_t action, band_t* band, rba_t* rba,
00418                 int len) {
00419 #ifdef EDI_LOG
00420         /* Log the function call */
00421         switch(action) {
00422         case SVC_GETPTR:
00423                 LOG->info("edi_managebands(fd=%d, inq=SVC_GETPTR, band=%d, rba=%p)\n",
00424                                   fd, *band, rba, len);
00425                 break;
00426 
00427         case SVC_SETPTR:
00428                 LOG->info("edi_managebands(fd=%d, inq=SVC_SETPTR, band=%d, rba=%d)\n",
00429                                   fd, *band, *rba, len);
00430                 break;
00431 
00432         case SVC_GETMULTIPLE:
00433                 LOG->info("edi_managebands(fd=%d, inq=SVC_GETMULTIPLE, band=%p, rba=%p,"
00434                                   " len=%d)\n", fd, band, rba, len);
00435                 break;
00436 
00437         case SVC_RESETALL:
00438                 LOG->info("edi_managebands(fd=%d, inq=SVC_RESETALL, band=%p, rba=%p, "
00439                                   "len=%d)\n", fd, band, rba, len);
00440                 break;
00441 
00442         case SVC_GETBANDCONFIG:
00443                 LOG->info("edi_managebands(fd=%d, inq=SVC_GETBANDCONFIG, band=%d, "
00444                                   "rba=%d, len=%d)\n", fd, *band, *rba, len);
00445                 break;
00446 
00447         case SVC_SETBANDCONFIG:
00448                 LOG->info("edi_managebands(fd=%d, inq=SVC_SETBANDCONFIG, band=%d, "
00449                                   "rba=%d, len=%d)\n", fd, *band, *rba, len);
00450                 break;
00451 }
00452 #endif
00453 
00454 
00455         /* Verify the file descriptor index */
00456         if (fd >= edi_count) {
00457                 errno = EBADFD;
00458                 return -1;
00459         }
00460 
00461     /* Select the appropriate call-back function */
00462     if (EDIOPS(fd)->managebands == NULL) {
00463         dbg("version[%d]->modesense() not supported!\n", edis[fd].version);
00464         errno = EUNSUPPORTED;
00465         return -1;
00466     }
00467 
00468     /* Call the registered call-back function */
00469         dbg("Calling version[%d]->managebands()!\n", edis[fd].version);
00470     return EDIOPS(fd)->managebands(edis[fd].fd, action, band, rba, len);
00471 }
00472 
00473 
00474 
00493 int edi_read(int fd, band_t band, rba_t rba, char *buf, rba_t len) {
00494 #ifdef EDI_LOG
00495         /* Log the function call */
00496         LOG->info("edi_read(fd=%d, band=%d, rba=%d, buf=%p, len=%d)\n",
00497                         fd, band, rba, buf, len);
00498 #endif
00499 
00500 
00501         /* Verify the file descriptor index */
00502         if (fd >= edi_count) {
00503                 errno = EBADFD;
00504                 return -1;
00505         }
00506 
00507     /* Select the appropriate call-back function */
00508     if (EDIOPS(fd)->read == NULL) {
00509         dbg("version[%d]->read() not supported!\n", edis[fd].version);
00510         errno = EUNSUPPORTED;
00511         return -1;
00512     }
00513 
00514     /* Call the registered call-back function */
00515         dbg("Calling version[%d]->read()!\n", edis[fd].version);
00516     return EDIOPS(fd)->read(edis[fd].fd, band, rba, buf, len);
00517 }
00518 
00519 
00520 
00536 int edi_write(int fd, band_t band, rba_t rba, char *buf, rba_t len) {
00537 #ifdef EDI_LOG
00538         /* Log the function call */
00539         LOG->info("edi_write(fd=%d, band=%d, rba=%d, buf=%p, len=%d)\n",
00540                         fd, band, rba, buf, len);
00541 #endif
00542 
00543 
00544         /* Verify the file descriptor index */
00545         if (fd >= edi_count) {
00546                 errno = EBADFD;
00547                 return -1;
00548         }
00549 
00550     /* Select the appropriate call-back function */
00551     if (EDIOPS(fd)->write == NULL) {
00552         dbg("version[%d]->write() not supported!\n", edis[fd].version);
00553         errno = EUNSUPPORTED;
00554         return -1;
00555     }
00556 
00557     /* Call the registered callback function */
00558         dbg("Calling version[%d]->write()!\n", edis[fd].version);
00559     return EDIOPS(fd)->write(edis[fd].fd, band, rba, buf, len);
00560 }
00561 
00562 
00563 
00569 int edi_init() {
00570 #ifdef EDI_LOG
00571         char filename[25];
00572         int len;
00573         time_t curtime = time(NULL);
00574 
00575         /* Initialize the logging module */
00576         len = strftime(filename, 25, "edi%Y%m%d%H%M%S.log", localtime(&curtime));
00577         if (!len) {
00578                 fprintf(stderr, "Error generating log file name: %s\n", filename);
00579                 return -1;
00580         }
00581     dbg("Log filename generated as %s\n", filename);
00582 
00583         LOG = emulog_open(filename);
00584         if (LOG == NULL) {
00585                 fprintf(stderr, "Cannot open log file %s\n", filename);
00586                 return -1;
00587         }
00588 #endif
00589 
00590 
00591         /* Initialize the data structures */
00592         memset(&edis, 0, sizeof(edi_fd_t) * MAX_EDIS);
00593         edi_count = 0;
00594 
00595 
00596         /* Call the initialization operations for the Versioning Interface */
00597         return ediv_init();
00598 }