| 1 |
/** |
| 2 |
* @file mkisofs.c |
| 3 |
* @brief mkisofsによるISOイメージ作成 |
| 4 |
* @auther BananaJinn |
| 5 |
* @version $Id: mkisofs.c,v 1.2 2010/11/02 15:23:51 bananajinn Exp $ |
| 6 |
* 円盤複写屋 |
| 7 |
* Copyright (C) 2004-2010 BananaJinn<banana@mxh.mesh.ne.jp>. |
| 8 |
*/ |
| 9 |
#if defined(WIN32) |
| 10 |
# include <io.h> |
| 11 |
# define R_OK 0 |
| 12 |
#endif |
| 13 |
#include <stdio.h> |
| 14 |
#include <string.h> |
| 15 |
#include <stdlib.h> |
| 16 |
#include "mkisofs.h" |
| 17 |
#include "drive.h" |
| 18 |
#include "mem.h" |
| 19 |
#include "ebstring.h" |
| 20 |
#include "ui.h" |
| 21 |
#include "text.h" |
| 22 |
#include "log.h" |
| 23 |
|
| 24 |
#if defined(WIN32) |
| 25 |
# define MKISOFS_CMD "genisoimage.exe" |
| 26 |
#else |
| 27 |
# define MKISOFS_CMD "mkisofs" |
| 28 |
#endif |
| 29 |
|
| 30 |
#define VIDEO_OPTION "-dvd-video" |
| 31 |
|
| 32 |
/** |
| 33 |
* @brief エラーメッセージ設定 |
| 34 |
* @param[in] mif MKISOFS構造体 |
| 35 |
* @param[in] error_message エラーメッセージ |
| 36 |
*/ |
| 37 |
static void SetErrorMessage(MKISOFS *mif, const char *error_message) |
| 38 |
{ |
| 39 |
if(mif->error_message != NULL){ |
| 40 |
EbStringFree(mif->error_message); |
| 41 |
} |
| 42 |
mif->error_message = EbStringNew(error_message); |
| 43 |
} |
| 44 |
|
| 45 |
/** |
| 46 |
* @brief エラーメッセージ取得 |
| 47 |
* @param[in] mif MKISOFS構造体 |
| 48 |
* @return エラーメッセージを返す。設定されていない場合は NULL を返す。 |
| 49 |
*/ |
| 50 |
const char *MIFGetErrorMessage(MKISOFS *mif) |
| 51 |
{ |
| 52 |
return mif->error_message; |
| 53 |
} |
| 54 |
|
| 55 |
|
| 56 |
/** |
| 57 |
* @brief 構造体初期化 |
| 58 |
* @param[out] mif 初期化する構造体のポインタ |
| 59 |
* @retval RET_OK 正常終了 |
| 60 |
*/ |
| 61 |
int MIFInitialize(MKISOFS *mif) |
| 62 |
{ |
| 63 |
memset(mif, 0, sizeof(MKISOFS)); |
| 64 |
return RET_OK; |
| 65 |
} |
| 66 |
|
| 67 |
/** |
| 68 |
* @brief 構造体解放 |
| 69 |
* @param[in] mif 解放する構造体のポインタ |
| 70 |
* @retval RET_OK 正常終了 |
| 71 |
* @retval RET_NG エラー |
| 72 |
*/ |
| 73 |
int MIFFree(MKISOFS *mif) |
| 74 |
{ |
| 75 |
int ret = RET_OK; |
| 76 |
BOOL success; |
| 77 |
int exitcode = 0; |
| 78 |
|
| 79 |
if(mif != NULL){ |
| 80 |
if(mif->pid > 0){ |
| 81 |
OSDTerminateProcess(mif->pid); |
| 82 |
success = OSDWaitProcess(mif->pid, &exitcode); |
| 83 |
if(!success || exitcode != 0){ |
| 84 |
ret = RET_NG; |
| 85 |
} |
| 86 |
mif->pid = 0; |
| 87 |
} |
| 88 |
if(mif->fd_stdout >= 0){ |
| 89 |
OSDFDClose(mif->fd_stdout); |
| 90 |
mif->fd_stdout = -1; |
| 91 |
} |
| 92 |
if(mif->fd_stderr >= 0){ |
| 93 |
OSDFDClose(mif->fd_stderr); |
| 94 |
mif->fd_stderr = -1; |
| 95 |
} |
| 96 |
EbStringFree(mif->src_path); |
| 97 |
EbStringFree(mif->volume); |
| 98 |
EbStringFree(mif->error_message); |
| 99 |
} |
| 100 |
return ret; |
| 101 |
} |
| 102 |
|
| 103 |
/** |
| 104 |
* @brief ISOイメージを作成する元のディレクトリパスを設定する |
| 105 |
* @param[in] mif MKISOFS構造体 |
| 106 |
* @param[in] src_path 設定するディレクトリパス |
| 107 |
* @retval RET_OK 正常終了 |
| 108 |
* @retval RET_NG エラー |
| 109 |
*/ |
| 110 |
int MIFSetSrcPath(MKISOFS *mif, const char *src_path) |
| 111 |
{ |
| 112 |
char *check_path; |
| 113 |
char *wp; |
| 114 |
int ret; |
| 115 |
|
| 116 |
if(mif != NULL){ |
| 117 |
if(mif->src_path != NULL){ |
| 118 |
EbStringFree(mif->src_path); |
| 119 |
} |
| 120 |
mif->src_path = EbStringNew(src_path); |
| 121 |
/* VIDEO_TSフォルダがあるか確認 */ |
| 122 |
check_path = EbStringNew(src_path); |
| 123 |
check_path = EbStringAppendPath(check_path, "VIDEO_TS"); |
| 124 |
mif->video = FALSE; |
| 125 |
if(access(check_path, |
| 126 |
#if defined(WIN32) |
| 127 |
R_OK |
| 128 |
#else |
| 129 |
R_OK|X_OK |
| 130 |
#endif |
| 131 |
) == 0){ |
| 132 |
ret = UIDispMessage(MSG_VIDEO_MODE, UIDMT_QUESTION); |
| 133 |
if(ret == UIDMRET_OK){ |
| 134 |
mif->video = TRUE; |
| 135 |
} |
| 136 |
} |
| 137 |
if(mif->video){ |
| 138 |
/* フォルダ名をボリュームラベルに */ |
| 139 |
wp = strrchr(check_path, PATH_SEPARATOR); |
| 140 |
if(wp != NULL){ |
| 141 |
*wp = '\0'; |
| 142 |
wp = strrchr(check_path, PATH_SEPARATOR); |
| 143 |
if(wp != NULL){ |
| 144 |
wp++; |
| 145 |
} |
| 146 |
else{ |
| 147 |
wp = check_path; |
| 148 |
} |
| 149 |
mif->volume = EbStringNew(wp); |
| 150 |
} |
| 151 |
} |
| 152 |
EbStringFree(check_path); |
| 153 |
} |
| 154 |
return RET_OK; |
| 155 |
} |
| 156 |
|
| 157 |
/** |
| 158 |
* @brief mkisofsオプションを追加する |
| 159 |
* @param[in] mif MKISOFS構造体 |
| 160 |
* @param[in] cmdline コマンドライン |
| 161 |
* @return 追加したコマンドライン文字列を返す。 |
| 162 |
*/ |
| 163 |
static char *AppendMkisofsOptions(MKISOFS *mif, char *cmdline) |
| 164 |
{ |
| 165 |
cmdline = EbStringAppend(cmdline, " -J -r"); |
| 166 |
cmdline = EbStringAppend(cmdline, " -input-charset UTF-8"); |
| 167 |
if(mif->video){ |
| 168 |
cmdline = EbStringAppendWithFormat(cmdline, " %s", VIDEO_OPTION); |
| 169 |
if(mif->volume != NULL){ |
| 170 |
cmdline = EbStringAppendWithFormat(cmdline, " -V \"%s\"", |
| 171 |
mif->volume); |
| 172 |
} |
| 173 |
} |
| 174 |
return cmdline; |
| 175 |
} |
| 176 |
|
| 177 |
|
| 178 |
/** |
| 179 |
* @brief ISOイメージのブロックサイズを取得 |
| 180 |
* @param[in] mif MKISOFS構造体 |
| 181 |
* @return ブロックサイズを返す。取得できない場合は 0 を返す。 |
| 182 |
*/ |
| 183 |
DWORD MIFGetBlockCount(MKISOFS *mif) |
| 184 |
{ |
| 185 |
char *cmdline = NULL; |
| 186 |
BOOL success = TRUE; |
| 187 |
OSD_PID pid; |
| 188 |
OSD_FD sout; |
| 189 |
OSD_FD serr; |
| 190 |
BYTE buff[256]; |
| 191 |
int read_length = 0; |
| 192 |
int exitcode = 0; |
| 193 |
char *stderr_string = NULL; |
| 194 |
|
| 195 |
cmdline = EbStringNewWithFormat("%s -print-size", MKISOFS_CMD); |
| 196 |
cmdline = AppendMkisofsOptions(mif, cmdline); |
| 197 |
cmdline = EbStringAppendWithFormat(cmdline, " %s", mif->src_path); |
| 198 |
DebugLog("run [%s]\n", cmdline); |
| 199 |
success = OSDCreateProcess(cmdline, &pid, NULL, &sout, &serr); |
| 200 |
if(!success){ |
| 201 |
cmdline = EbStringFree(cmdline); |
| 202 |
return 0; |
| 203 |
} |
| 204 |
cmdline = EbStringFree(cmdline); |
| 205 |
|
| 206 |
memset(buff, 0, sizeof(buff)); |
| 207 |
read_length = OSDRead(sout, serr, buff, sizeof(buff)-1, &stderr_string); |
| 208 |
success = OSDWaitProcess(pid, &exitcode); |
| 209 |
DebugLog("exitcode=%d, read_length=%d\n", exitcode, read_length); |
| 210 |
if(!success || read_length <= 0){ |
| 211 |
SetErrorMessage(mif, stderr_string); |
| 212 |
EbStringFree(stderr_string); |
| 213 |
return 0; |
| 214 |
} |
| 215 |
DebugLog("block count=%ld\n", atol((char *)buff)); |
| 216 |
EbStringFree(stderr_string); |
| 217 |
return (DWORD)atol((char *)buff); |
| 218 |
} |
| 219 |
|
| 220 |
/** |
| 221 |
* @brief mkisofs開始 |
| 222 |
* @param[in] mif MKISOFS構造体 |
| 223 |
* @retval RET_OK 成功 |
| 224 |
* @retval RET_NG 失敗 |
| 225 |
*/ |
| 226 |
static int StartMkisofs(MKISOFS *mif) |
| 227 |
{ |
| 228 |
char *cmdline = NULL; |
| 229 |
BOOL success = TRUE; |
| 230 |
|
| 231 |
cmdline = EbStringNewWithFormat("%s -quiet", MKISOFS_CMD); |
| 232 |
cmdline = AppendMkisofsOptions(mif, cmdline); |
| 233 |
cmdline = EbStringAppendWithFormat(cmdline, " %s", mif->src_path); |
| 234 |
DebugLog("run [%s]\n", cmdline); |
| 235 |
success = OSDCreateProcess(cmdline, &mif->pid, NULL, |
| 236 |
&mif->fd_stdout, &mif->fd_stderr); |
| 237 |
if(!success){ |
| 238 |
cmdline = EbStringFree(cmdline); |
| 239 |
return RET_NG; |
| 240 |
} |
| 241 |
cmdline = EbStringFree(cmdline); |
| 242 |
|
| 243 |
mif->started = TRUE; |
| 244 |
return RET_OK; |
| 245 |
} |
| 246 |
|
| 247 |
/** |
| 248 |
* @brief mkisofsの標準出力を読み込む |
| 249 |
* @param[in] mif MKISOFS構造体 |
| 250 |
* @param[out] buff バッファ |
| 251 |
* @param[in] len 読み込むバイト数 |
| 252 |
* @retval RET_OK 正常終了 |
| 253 |
* @retval RET_NG エラー |
| 254 |
*/ |
| 255 |
int MIFRead(MKISOFS *mif, BYTE *buff, DWORD len) |
| 256 |
{ |
| 257 |
int ret; |
| 258 |
int read_length = 0; |
| 259 |
char *err = NULL; |
| 260 |
|
| 261 |
if(!mif->started){ |
| 262 |
ret = StartMkisofs(mif); |
| 263 |
if(ret != RET_OK){ |
| 264 |
return ret; |
| 265 |
} |
| 266 |
DebugLog("mkisofs started\n"); |
| 267 |
} |
| 268 |
|
| 269 |
read_length = OSDRead(mif->fd_stdout, mif->fd_stderr, |
| 270 |
buff, len, &err); |
| 271 |
if(read_length < len){ |
| 272 |
char *message = EbStringNewWithFormat(MSG_MKISOFS_ERROR_, err); |
| 273 |
DebugLog("read_length=%d len=%ld\n", read_length, len); |
| 274 |
DebugLog("stderr=%s\n", err); |
| 275 |
UIDispMessage(message, UIDMT_ERROR); |
| 276 |
EbStringFree(message); |
| 277 |
EbStringFree(err); |
| 278 |
return RET_NG; |
| 279 |
} |
| 280 |
EbStringFree(err); |
| 281 |
return RET_OK; |
| 282 |
} |