/** @file * File splitter: splits a text file according to ###### markers in it. */ /* * Copyright (C) 2006-2009 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. */ #include #include #include #include #include static unsigned long lineNumber(const char *pStr, const char *pPos) { unsigned long cLine = 0; while (*pStr && pStr < pPos) { pStr = strchr(pStr, '\n'); if (!pStr) break; ++cLine; ++pStr; } return cLine; } int main(int argc, char *argv[]) { int rc = 0; const char *pcszBeginMarker = "\n// ##### BEGINFILE \""; const char *pcszEndMarker = "\n// ##### ENDFILE"; const size_t cbBeginMarker = strlen(pcszBeginMarker); FILE *pFileIn = NULL; char *pBuffer = NULL; do { if (argc != 3) { fprintf(stderr, "filesplitter: Must be started with exactly two arguments,\n" "1) the input file and 2) the directory where to put the output files\n"); rc = 2; break; } struct stat lStat; if ( stat(argv[2], &lStat) != 0 || (lStat.st_mode & S_IFDIR) != S_IFDIR) { fprintf(stderr, "filesplitter: Given argument \"%s\" is not a valid directory.\n", argv[2]); rc = 2; break; } if ( stat(argv[1], &lStat) || !(pFileIn = fopen(argv[1], "r"))) { fprintf(stderr, "filesplitter: Cannot open file \"%s\" for reading.\n", argv[1]); rc = 2; break; } if (!(pBuffer = (char*)malloc(lStat.st_size + 1))) { fprintf(stderr, "filesplitter: Failed to allocate %ld bytes.\n", (long)lStat.st_size); rc = 2; break; } if (fread(pBuffer, 1, lStat.st_size, pFileIn) != (size_t)lStat.st_size) { fprintf(stderr, "filesplitter: Failed to read %ld bytes from input file.\n", (long)lStat.st_size); rc = 2; break; } pBuffer[lStat.st_size] = '\0'; const char *pSearch = pBuffer; unsigned long cFiles = 0; size_t cbDirName = strlen(argv[2]); do { /* find begin marker */ const char *pBegin = strstr(pSearch, pcszBeginMarker); if (!pBegin) break; /* find line after begin marker */ const char *pLineAfterBegin = strchr(pBegin + cbBeginMarker, '\n'); if (!pLineAfterBegin) { fprintf(stderr, "filesplitter: No newline after begin-file marker found.\n"); rc = 2; break; } ++pLineAfterBegin; /* find second quote in begin marker line */ const char *pSecondQuote = strchr(pBegin + cbBeginMarker, '\"'); if ( !pSecondQuote || pSecondQuote >= pLineAfterBegin) { fprintf(stderr, "filesplitter: Can't parse filename after begin-file marker (line %lu).\n", lineNumber(pBuffer, pcszBeginMarker)); rc = 2; break; } /* find end marker */ const char *pEnd = strstr(pLineAfterBegin, pcszEndMarker); if (!pEnd) { fprintf(stderr, "filesplitter: No matching end-line marker for begin-file marker found (line %lu).\n", lineNumber(pBuffer, pcszBeginMarker)); rc = 2; break; } /* construct output filename */ char *pszFilename; size_t cbFilename; cbFilename = pSecondQuote - (pBegin + cbBeginMarker); if (!(pszFilename = (char*)malloc(cbDirName + 1 + cbFilename + 1))) { fprintf(stderr, "filesplitter: Can't allocate memory for filename.\n"); rc = 2; break; } memcpy(pszFilename, argv[2], cbDirName); pszFilename[cbDirName] = '/'; memcpy(pszFilename + cbDirName + 1, pBegin + cbBeginMarker, cbFilename); pszFilename[cbFilename + 1 + cbDirName] = '\0'; /* create output file and write file contents */ FILE *pFileOut; if (!(pFileOut = fopen(pszFilename, "w"))) { fprintf(stderr, "filesplitter: Failed to open file \"%s\" for writing\n", pszFilename); rc = 2; } else { size_t cbFile = pEnd - pLineAfterBegin; if (fwrite(pLineAfterBegin, 1, cbFile, pFileOut) != cbFile) { fprintf(stderr, "filesplitter: Failed to write %ld bytes to file \"%s\"\n", (long)cbFile, pszFilename); rc = 2; } fclose(pFileOut); if (!rc) { ++cFiles; pSearch = strchr(pEnd, '\n'); } } free(pszFilename); if (rc) break; } while (pSearch); printf("filesplitter: Created %lu files.\n", cFiles); } while (0); if (pBuffer) free(pBuffer); if (pFileIn) fclose(pFileIn); return rc; }