From: jhurst Date: Sun, 5 Apr 2009 19:16:53 +0000 (+0000) Subject: new functions for KM_fileIO X-Git-Tag: rel_2_10_32~402 X-Git-Url: https://git.carlh.net/gitweb/?a=commitdiff_plain;h=bf54b7e8b0100eaf39a1914a089a524c4a66ebba;p=asdcplib.git new functions for KM_fileIO comment updates in AS_DCP.h additional frame rates in AS_DCP.h --- diff --git a/configure.ac b/configure.ac index c2bb969..24bca11 100644 --- a/configure.ac +++ b/configure.ac @@ -37,7 +37,7 @@ AC_PREREQ([2.59]) # For example, if asdcplib version 1.0.0 were modified to accomodate changes # in file format, and if no changes were made to AS_DCP.h, the new version would be # 1.0.1. If changes were also required in AS_DCP.h, the new version would be 1.1.1. -AC_INIT([asdcplib], [1.4.21], [asdcplib@cinecert.com]) +AC_INIT([asdcplib], [1.4.22], [asdcplib@cinecert.com]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_SRCDIR([src/KM_error.h]) diff --git a/src/AS_DCP.h b/src/AS_DCP.h index d8d734b..a6be6d2 100755 --- a/src/AS_DCP.h +++ b/src/AS_DCP.h @@ -28,15 +28,12 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \version $Id$ \brief AS-DCP library, public interface -The asdcplib library is a set of wrapper objects that offer simplified -access to files conforming to the file formats proposed by the SMPTE -D-Cinema packaging working group DC28.20. The file format, labeled -AS-DCP, is described in series of separate documents which include but -may not be limited to: +The asdcplib library is a set of file access objects that offer simplified +access to files conforming to the standards published by the SMPTE +D-Cinema Technology Committee 21DC. The file format, labeled AS-DCP, +is described in series of separate documents which include but may not +be be limited to: - o MXF Interop Track File Specification - o MXF Interop Track File Essence Encryption Specification - o MXF Interop Operational Constraints Specification o SMPTE 429-2-2009 DCP Operational Constraints o SMPTE 429-3-2006 Track File Specification o SMPTE 429-4-2006 JPEG 2000 for D-Cinema @@ -54,29 +51,29 @@ may not be limited to: o IETF RFC 2104 - HMAC/SHA1 o NIST FIPS 197 - AES (Rijndael) + o MXF Interop Track File Specification + o MXF Interop Track File Essence Encryption Specification + o MXF Interop Operational Constraints Specification + - Note: the MXF Interop documents are not formally published. + Contact the asdcplib support address to get copies. + The following use cases are supported by the library: - o Write a plaintext MPEG2 Video Elementary Stream to a plaintext ASDCP file - o Write a plaintext MPEG2 Video Elementary Stream to a ciphertext ASDCP file - o Read a plaintext MPEG2 Video Elementary Stream from a plaintext ASDCP file - o Read a plaintext MPEG2 Video Elementary Stream from a ciphertext ASDCP file - o Read a ciphertext MPEG2 Video Elementary Stream from a ciphertext ASDCP file - o Write one or more plaintext JPEG 2000 codestreams to a plaintext ASDCP file - o Write one or more plaintext JPEG 2000 codestreams to a ciphertext ASDCP file - o Read one or more plaintext JPEG 2000 codestreams from a plaintext ASDCP file - o Read one or more plaintext JPEG 2000 codestreams from a ciphertext ASDCP file - o Read one or more ciphertext JPEG 2000 codestreams from a ciphertext ASDCP file - o Write one or more plaintext JPEG 2000 stereoscopic codestream pairs to a plaintext ASDCP file - o Write one or more plaintext JPEG 2000 stereoscopic codestream pairs to a ciphertext ASDCP file - o Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a plaintext ASDCP file - o Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file - o Read one or more ciphertext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file - o Write one or more plaintext PCM audio streams to a plaintext ASDCP file - o Write one or more plaintext PCM audio streams to a ciphertext ASDCP file - o Read one or more plaintext PCM audio streams from a plaintext ASDCP file - o Read one or more plaintext PCM audio streams from a ciphertext ASDCP file - o Read one or more ciphertext PCM audio streams from a ciphertext ASDCP file - o Read header metadata from an ASDCP file + o Write essence to a plaintext or ciphertext AS-DCP file: + MPEG2 Video Elementary Stream + JPEG 2000 codestreams + JPEG 2000 stereoscopic codestream pairs + PCM audio streams + SMPTE 429-7 Timed Text XML with font and image resources + + o Read essence from a plaintext or ciphertext AS-DCP file: + MPEG2 Video Elementary Stream + JPEG 2000 codestreams + JPEG 2000 stereoscopic codestream pairs + PCM audio streams + SMPTE 429-7 Timed Text XML with font and image resources + + o Read header metadata from an AS-DCP file This project depends upon the following libraries: - OpenSSL http://www.openssl.org/ @@ -258,6 +255,14 @@ namespace ASDCP { const Rational SampleRate_48k(48000,1); const Rational SampleRate_96k(96000,1); + // Additional frame rates, see SMPTE 428-11 + // These rates are new and not supported by all systems. Do not assume that a package + // made using on of these rates will work just anywhere! + const Rational EditRate_25(25,1); + const Rational EditRate_30(30,1); + const Rational EditRate_50(50,1); + const Rational EditRate_60(60,1); + // Non-reference counting container for internal member objects. // Please do not use this class for any other purpose. template diff --git a/src/KM_error.h b/src/KM_error.h index c17fe76..b0d40d1 100755 --- a/src/KM_error.h +++ b/src/KM_error.h @@ -88,6 +88,8 @@ namespace Kumu const Result_t RESULT_FILEEXISTS (-18, "Filename already exists."); const Result_t RESULT_NOTAFILE (-19, "Filename not found."); const Result_t RESULT_UNKNOWN (-20, "Unknown result code."); + const Result_t RESULT_DIR_CREATE (-21, "Unable to create directory."); + } // namespace Kumu //-------------------------------------------------------------------------------- diff --git a/src/KM_fileio.cpp b/src/KM_fileio.cpp index 978f6f9..8625e69 100644 --- a/src/KM_fileio.cpp +++ b/src/KM_fileio.cpp @@ -32,7 +32,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include + #include + #ifdef KM_WIN32 #include #endif @@ -52,6 +54,13 @@ struct iovec { int iov_len; }; #else +# if defined(__linux__) +# include +# else +# include +# endif + +#include #include typedef struct stat fstat_t; #endif @@ -1125,6 +1134,57 @@ Kumu::WriteObjectIntoFile(const Kumu::IArchive& Object, const std::string& Filen //------------------------------------------------------------------------------------------ // +// +Result_t +Kumu::ReadFileIntoBuffer(const std::string& Filename, Kumu::ByteString& Buffer, ui32_t max_size) +{ + ui32_t file_size = FileSize(Filename); + Result_t result = Buffer.Capacity(file_size); + + if ( KM_SUCCESS(result) ) + { + ui32_t read_count = 0; + FileWriter Reader; + + result = Reader.OpenRead(Filename.c_str()); + + if ( KM_SUCCESS(result) ) + result = Reader.Read(Buffer.Data(), file_size, &read_count); + + if ( KM_SUCCESS(result) ) + { + if ( file_size != read_count) + return RESULT_READFAIL; + + Buffer.Length(read_count); + } + } + + return result; +} + +// +Result_t +Kumu::WriteBufferIntoFile(const Kumu::ByteString& Buffer, const std::string& Filename) +{ + ui32_t write_count = 0; + FileWriter Writer; + + Result_t result = Writer.OpenWrite(Filename.c_str()); + + if ( KM_SUCCESS(result) ) + result = Writer.Write(Buffer.RoData(), Buffer.Length(), &write_count); + + if ( KM_SUCCESS(result) && Buffer.Length() != write_count) + return RESULT_WRITEFAIL; + + return result; +} + +//------------------------------------------------------------------------------------------ +// + + // Win32 directory scanner // #ifdef KM_WIN32 @@ -1277,6 +1337,181 @@ Kumu::DirScanner::GetNext(char* filename) #endif // KM_WIN32 +//------------------------------------------------------------------------------------------ + +// note: when moving to KM_fileio, don't forget to write the Win32 versions +// note: add error messages and remove RESULT_FAIL form DirScanner + +#ifdef KM_WIN32 +#else // KM_WIN32 + +// given a path string, create any missing directories so that PathIsDirectory(Path) is true. +// +Result_t +Kumu::CreateDirectoriesInPath(const std::string& Path) +{ + bool abs = PathIsAbsolute(Path); + assert(abs); + PathCompList_t PathComps, TmpPathComps; + + PathToComponents(Path, PathComps); + + while ( ! PathComps.empty() ) + { + TmpPathComps.push_back(PathComps.front()); + PathComps.pop_front(); + std::string tmp_path = abs ? ComponentsToAbsolutePath(TmpPathComps) : ComponentsToPath(TmpPathComps); + + if ( ! PathIsDirectory(tmp_path) ) + { + if ( mkdir(tmp_path.c_str(), 0775) != 0 ) + { + DefaultLogSink().Error("CreateDirectoriesInPath mkdir %s: %s\n", + tmp_path.c_str(), strerror(errno)); + return RESULT_DIR_CREATE; + } + } + } + + return RESULT_OK; +} +#endif // KM_WIN32 + + +#ifdef KM_WIN32 +#else // KM_WIN32 + +// +Result_t +Kumu::DeleteFile(const std::string& filename) +{ + if ( unlink(filename.c_str()) == 0 ) + return RESULT_OK; + + switch ( errno ) + { + case ENOENT: + case ENOTDIR: return RESULT_NOTAFILE; + + case EROFS: + case EBUSY: + case EACCES: + case EPERM: return RESULT_NO_PERM; + } + + DefaultLogSink().Error("DeleteFile %s: %s\n", filename.c_str(), strerror(errno)); + return RESULT_FAIL; +} + +// +Result_t +h__DeletePath(const std::string& pathname) +{ + fprintf(stderr, "h__DeletePath %s\n", pathname.c_str()); + Result_t result = RESULT_OK; + + if ( ! PathIsDirectory(pathname) ) + { + result = DeleteFile(pathname); + } + else + { + { + DirScanner TestDir; + char next_file[Kumu::MaxFilePath]; + result = TestDir.Open(pathname.c_str()); + + while ( KM_SUCCESS(result) && KM_SUCCESS(TestDir.GetNext(next_file)) ) + { + if ( next_file[0] == '.' ) + { + if ( next_file[1] == 0 ) + continue; // don't delete 'this' + + if ( next_file[1] == '.' && next_file[2] == 0 ) + continue; // don't delete 'this' parent + } + + result = h__DeletePath(pathname + std::string("/") + next_file); + } + } + + if ( rmdir(pathname.c_str()) != 0 ) + { + switch ( errno ) + { + case ENOENT: + case ENOTDIR: + result = RESULT_NOTAFILE; + break; + + case EROFS: + case EBUSY: + case EACCES: + case EPERM: + result = RESULT_NO_PERM; + break; + + default: + DefaultLogSink().Error("DeletePath %s: %s\n", pathname.c_str(), strerror(errno)); + result = RESULT_FAIL; + } + } + } + + return result; +} + +// +Result_t +Kumu::DeletePath(const std::string& pathname) +{ + std::string c_pathname = PathMakeAbsolute(PathMakeCanonical(pathname)); + DefaultLogSink().Debug("DeletePath (%s) c(%s)\n", pathname.c_str(), c_pathname.c_str()); + return h__DeletePath(c_pathname); +} + +#endif // KM_WIN32 + +//------------------------------------------------------------------------------------------ +// + + +#ifdef KM_WIN32 +#else // KM_WIN32 + +// +Result_t +Kumu::FreeSpaceForPath(const std::string& path, Kumu::fsize_t& free_space, Kumu::fsize_t& total_space) +{ + struct statfs s; + + if ( statfs(path.c_str(), &s) == 0 ) + { + if ( s.f_blocks < 1 ) + { + DefaultLogSink().Error("File system %s has impossible size: %ld\n", + path.c_str(), s.f_blocks); + return RESULT_FAIL; + } + + free_space = (Kumu::fsize_t)s.f_bsize * (Kumu::fsize_t)s.f_bavail; + total_space = (Kumu::fsize_t)s.f_bsize * (Kumu::fsize_t)s.f_blocks; + return RESULT_OK; + } + + switch ( errno ) + { + case ENOENT: + case ENOTDIR: return RESULT_NOTAFILE; + case EACCES: return RESULT_NO_PERM; + } + + DefaultLogSink().Error("FreeSpaceForPath statfs %s: %s\n", path.c_str(), strerror(errno)); + return RESULT_FAIL; +} + +#endif // KM_WIN32 // // end KM_fileio.cpp diff --git a/src/KM_fileio.h b/src/KM_fileio.h index 448cf76..738a316 100755 --- a/src/KM_fileio.h +++ b/src/KM_fileio.h @@ -119,18 +119,26 @@ namespace Kumu const ui32_t MaxFilePath = Kilobyte; + + //------------------------------------------------------------------------------------------ // Path Manglers - // + //------------------------------------------------------------------------------------------ + + // types typedef std::list PathCompList_t; // a list of path components typedef std::list PathList_t; // a list of paths + // tests bool PathExists(const std::string& Path); // true if the path exists in the filesystem bool PathIsFile(const std::string& Path); // true if the path exists in the filesystem and is a file bool PathIsDirectory(const std::string& Path); // true if the path exists in the filesystem and is a directory fsize_t FileSize(const std::string& Path); // returns the size of a regular file, 0 for a directory or device bool PathsAreEquivalent(const std::string& lhs, const std::string& rhs); // true if paths point to the same filesystem entry - // split and reassemble pats as lists of path components + // Returns free space and total space available for the given path + Result_t FreeSpaceForPath(const std::string& path, Kumu::fsize_t& free_space, Kumu::fsize_t& total_space); + + // split and reassemble paths as lists of path components PathCompList_t& PathToComponents(const std::string& Path, PathCompList_t& CList, char separator = '/'); // removes '//' std::string ComponentsToPath(const PathCompList_t& CList, char separator = '/'); std::string ComponentsToAbsolutePath(const PathCompList_t& CList, char separator = '/'); // add separator to the front @@ -141,12 +149,18 @@ namespace Kumu std::string PathMakeLocal(const std::string& Path, const std::string& Parent); // remove Parent from front of Path, if it exists std::string PathMakeCanonical(const std::string& Path, char separator = '/'); // remove '.' and '..' + // common operations std::string PathBasename(const std::string& Path, char separator = '/'); // returns right-most path element (list back()) std::string PathDirname(const std::string& Path, char separator = '/'); // returns everything but the right-most element std::string PathGetExtension(const std::string& Path); // returns everything in the right-most element following the right-most '.' std::string PathSetExtension(const std::string& Path, const std::string& Extension); // empty extension removes '.' as well - // + + //------------------------------------------------------------------------------------------ + // Path Search + //------------------------------------------------------------------------------------------ + + // An interface for a path matching function, used by FindInPath() and FindInPaths() below // class IPathMatch { @@ -155,6 +169,7 @@ namespace Kumu virtual bool Match(const std::string& s) const = 0; }; + // matches any pathname class PathMatchAny : public IPathMatch { public: @@ -163,6 +178,7 @@ namespace Kumu }; #ifndef KM_WIN32 + // matches pathnames using a regular expression class PathMatchRegex : public IPathMatch { regex_t m_regex; @@ -176,6 +192,7 @@ namespace Kumu bool Match(const std::string& s) const; }; + // matches pathnames using a Bourne shell glob expression class PathMatchGlob : public IPathMatch { regex_t m_regex; @@ -198,6 +215,22 @@ namespace Kumu PathList_t& FindInPaths(const IPathMatch& Pattern, const PathList_t& SearchPaths, PathList_t& FoundPaths, bool one_shot = false, char separator = '/'); + //------------------------------------------------------------------------------------------ + // Directory Manipulation + //------------------------------------------------------------------------------------------ + + // Create a directory, creates intermediate directories as necessary + Result_t CreateDirectoriesInPath(const std::string& Path); + + // Delete a file (fails if the path points to a directory) + Result_t DeleteFile(const std::string& filename); + + // Recursively remove a file or directory + Result_t DeletePath(const std::string& pathname); + + //------------------------------------------------------------------------------------------ + // File I/O Wrappers + //------------------------------------------------------------------------------------------ // Instant IO for strings // @@ -215,6 +248,20 @@ namespace Kumu // Archives an object into a file Result_t WriteObjectIntoFile(const IArchive& Object, const std::string& Filename); + // Instant IO for memory buffers + // + // Unarchives a file into a buffer + Result_t ReadFileIntoBuffer(const std::string& Filename, Kumu::ByteString& Buffer, + ui32_t max_size = 8 * Kumu::Megabyte); + + // Archives a buffer into a file + Result_t WriteBufferIntoFile(const Kumu::ByteString& Buffer, const std::string& Filename); + + + //------------------------------------------------------------------------------------------ + // File I/O + //------------------------------------------------------------------------------------------ + // class FileReader { @@ -274,6 +321,11 @@ namespace Kumu Result_t Write(const byte_t*, ui32_t, ui32_t* = 0); // write buffer to disk }; + Result_t CreateDirectoriesInPath(const std::string& Path); + Result_t FreeSpaceForPath(const std::string& path, Kumu::fsize_t& free_space, Kumu::fsize_t& total_space); + Result_t DeleteFile(const std::string& filename); + Result_t DeletePath(const std::string& pathname); + } // namespace Kumu