/* unieject - Universal eject command Copyright (C) 2005-2006, Diego Pettenò 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; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will 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 unieject; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #ifdef HAVE_LIBGEN_H # include #endif #include char *simplifylink(const char *orig) { #if defined(HAVE_READLINK) && defined(HAVE_DIRNAME) char *tmp = (char*)malloc(1024); int c = readlink(orig, tmp, 1023); if ( c != -1) { tmp[c] = '\0'; if ( tmp[0] != '/' ) // relative link { char *copylink = sstrdup(orig); char *origdir = strdup(dirname(copylink)); free(copylink); char *newname = NULL; asprintf(&newname, "%s/%s", origdir, tmp); free(tmp); free(origdir); tmp = newname; } return tmp; } free(tmp); #endif return strdup(orig); } /** * @brief Output an error for unieject library * @param opts Options to apply for the output * @param format Output format of the error * @param ... As in printf() like function * * @note Internal function */ void unieject_error(const struct unieject_opts opts, const char *format, ...) { if ( opts.verbose == -1 ) return; char *newformat = NULL; if ( asprintf(&newformat, "%s: %s", opts.progname, format) == -1 ) return; va_list argptr; va_start(argptr, format); vfprintf(stderr, newformat, argptr); va_end(argptr); free(newformat); } /** * @brief Output verbose message for unieject library * @param opts Options to apply for the output * @param format Output format of the message * @param ... As in printf() like function * * @note Internal function */ void unieject_verbose(const struct unieject_opts opts, const char *format, ...) { if ( opts.verbose < 1 ) return; char *newformat = NULL; if ( asprintf(&newformat, "%s: %s", opts.progname, format) == -1 ) return; va_list argptr; va_start(argptr, format); vfprintf(stdout, newformat, argptr); va_end(argptr); free(newformat); } /** * @brief Outputs a message about the given status return code * @param opts Options to apply for the output * @param sts Status return code from libcdio library */ int unieject_status(const struct unieject_opts opts, int sts) { switch(sts) { case DRIVER_OP_SUCCESS: return 0; default: unieject_error(opts, _("unable to execute command (unknown CDIO status: %d)\n"), sts); } return -3; } /** * @brief Returns the (workaround'ed) capabilities of a drive * * This function is a wrapper around cdio_get_drive_cap() function from libcdio * that tries to work around situations like FreeBSD's broken capabilities or * USB flash drives passed directly to libcdio. */ cdio_drive_misc_cap_t unieject_get_misccaps(const struct unieject_opts opts) { if ( opts.caps ) { cdio_drive_misc_cap_t read_cap, write_cap, misc_cap; cdio_get_drive_cap((CdIo_t*)opts.cdio, &read_cap, &write_cap, &misc_cap); /* In case there's an error reading capabilities or they are not loaded, then return the full caps (act as we were ignoring capabilities. Also return full capabilities if it can't read CD-R, as we assume that every CD-Rom drive reads them, and if it doesn't report it, it might be an USB/SCSI device. */ if ( misc_cap & (CDIO_DRIVE_CAP_UNKNOWN|CDIO_DRIVE_CAP_ERROR) || ! (read_cap & CDIO_DRIVE_CAP_READ_CD_R) ) return 0xFFFFFFFF; #ifdef FREEBSD_DRIVER if ( strncmp("/dev/cd", opts.device, 7) != 0 ) return 0xFFFFFFFF; #endif return misc_cap; } return 0xFFFFFFFF; }