@@ -1855,3 +1855,206 @@ int64_t taosWritevFile(TdFilePtr pFile, const TaosIOVec *iov, int iovcnt) {
18551855 return (int64_t )totalWritten ;
18561856#endif
18571857}
1858+
1859+ // ============================================================================
1860+ // Encrypted File Operations Implementation
1861+ // ============================================================================
1862+
1863+ /**
1864+ * Write file with encryption header using atomic file replacement.
1865+ *
1866+ * This function writes data to a file with an encryption header at the beginning.
1867+ * The encryption header contains:
1868+ * - Magic number "tdEncrypt" for quick identification
1869+ * - Algorithm identifier (e.g., SM4 = 1)
1870+ * - File format version
1871+ * - Length of encrypted data
1872+ *
1873+ * Atomic file replacement strategy:
1874+ * 1. Write to temporary file: filepath.tmp.timestamp
1875+ * 2. Sync temporary file to disk
1876+ * 3. Atomically rename temporary file to target filepath
1877+ * 4. Remove old file if rename succeeds
1878+ *
1879+ * This ensures the operation is atomic - no partial writes or corrupted files
1880+ * even if the process is interrupted.
1881+ *
1882+ * @param filepath Target file path
1883+ * @param algorithm Encryption algorithm identifier
1884+ * @param data Data buffer to write (can be NULL for empty file with header only)
1885+ * @param dataLen Length of data to write (0 for empty file)
1886+ * @return 0 on success, error code on failure
1887+ */
1888+ int32_t taosWriteEncryptFileHeader (const char * filepath , int32_t algorithm , const void * data , int32_t dataLen ) {
1889+ if (filepath == NULL ) {
1890+ terrno = TSDB_CODE_INVALID_PARA ;
1891+ return terrno ;
1892+ }
1893+
1894+ // Validate algorithm
1895+ if (algorithm < 0 ) {
1896+ terrno = TSDB_CODE_INVALID_PARA ;
1897+ return terrno ;
1898+ }
1899+
1900+ // Validate data parameters
1901+ if (dataLen > 0 && data == NULL ) {
1902+ terrno = TSDB_CODE_INVALID_PARA ;
1903+ return terrno ;
1904+ }
1905+
1906+ int32_t code = 0 ;
1907+ int64_t now = taosGetTimestampMs ();
1908+
1909+ // Prepare encryption header (plaintext)
1910+ STdEncryptFileHeader header ;
1911+ memset (& header , 0 , sizeof (STdEncryptFileHeader ));
1912+ strncpy (header .magic , TD_ENCRYPT_FILE_MAGIC , TD_ENCRYPT_MAGIC_LEN - 1 );
1913+ header .algorithm = algorithm ;
1914+ header .version = TD_ENCRYPT_FILE_VERSION ;
1915+ header .dataLen = dataLen ;
1916+
1917+ // Create temporary file for atomic write
1918+ char tempFile [PATH_MAX ];
1919+ snprintf (tempFile , sizeof (tempFile ), "%s.tmp.%ld" , filepath , now );
1920+
1921+ // Open temp file
1922+ TdFilePtr pFile = taosOpenFile (tempFile , TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC );
1923+ if (pFile == NULL ) {
1924+ code = terrno ;
1925+ return code ;
1926+ }
1927+
1928+ // Write header (plaintext)
1929+ int64_t written = taosWriteFile (pFile , & header , sizeof (STdEncryptFileHeader ));
1930+ if (written != sizeof (STdEncryptFileHeader )) {
1931+ code = (terrno != 0 ) ? terrno : TSDB_CODE_FILE_CORRUPTED ;
1932+ taosCloseFile (& pFile );
1933+ taosRemoveFile (tempFile );
1934+ terrno = code ;
1935+ return code ;
1936+ }
1937+
1938+ // Write data if present
1939+ if (dataLen > 0 && data != NULL ) {
1940+ written = taosWriteFile (pFile , data , dataLen );
1941+ if (written != dataLen ) {
1942+ code = (terrno != 0 ) ? terrno : TSDB_CODE_FILE_CORRUPTED ;
1943+ taosCloseFile (& pFile );
1944+ taosRemoveFile (tempFile );
1945+ terrno = code ;
1946+ return code ;
1947+ }
1948+ }
1949+
1950+ // Sync to disk
1951+ code = taosFsyncFile (pFile );
1952+ if (code != 0 ) {
1953+ taosCloseFile (& pFile );
1954+ taosRemoveFile (tempFile );
1955+ return code ;
1956+ }
1957+
1958+ // Close temp file
1959+ taosCloseFile (& pFile );
1960+
1961+ #ifndef WINDOWS
1962+ // Set file permissions (600 - owner read/write only) for security
1963+ chmod (tempFile , 0600 );
1964+ #endif
1965+
1966+ // Atomic replacement - rename temp file to target
1967+ code = taosRenameFile (tempFile , filepath );
1968+ if (code != 0 ) {
1969+ taosRemoveFile (tempFile );
1970+ return code ;
1971+ }
1972+
1973+ return 0 ;
1974+ }
1975+
1976+ /**
1977+ * Read encryption header from file.
1978+ *
1979+ * Reads and validates the encryption header from the beginning of a file.
1980+ * Checks:
1981+ * - Magic number matches "tdEncrypt"
1982+ * - Version is supported
1983+ *
1984+ * @param filepath File path to read
1985+ * @param header Output parameter for header data
1986+ * @return 0 on success, error code on failure
1987+ */
1988+ int32_t taosReadEncryptFileHeader (const char * filepath , STdEncryptFileHeader * header ) {
1989+ if (filepath == NULL || header == NULL ) {
1990+ terrno = TSDB_CODE_INVALID_PARA ;
1991+ return terrno ;
1992+ }
1993+
1994+ // Open file for reading
1995+ TdFilePtr pFile = taosOpenFile (filepath , TD_FILE_READ );
1996+ if (pFile == NULL ) {
1997+ return terrno ;
1998+ }
1999+
2000+ // Read header
2001+ int64_t nread = taosReadFile (pFile , header , sizeof (STdEncryptFileHeader ));
2002+ taosCloseFile (& pFile );
2003+
2004+ if (nread != sizeof (STdEncryptFileHeader )) {
2005+ terrno = TSDB_CODE_FILE_CORRUPTED ;
2006+ return terrno ;
2007+ }
2008+
2009+ // Verify magic number
2010+ if (strncmp (header -> magic , TD_ENCRYPT_FILE_MAGIC , strlen (TD_ENCRYPT_FILE_MAGIC )) != 0 ) {
2011+ terrno = TSDB_CODE_FILE_CORRUPTED ;
2012+ return terrno ;
2013+ }
2014+
2015+ // Verify version (currently only version 1 is supported)
2016+ if (header -> version != TD_ENCRYPT_FILE_VERSION ) {
2017+ terrno = TSDB_CODE_FILE_CORRUPTED ;
2018+ return terrno ;
2019+ }
2020+
2021+ return 0 ;
2022+ }
2023+
2024+ /**
2025+ * Check if file has encryption header.
2026+ *
2027+ * Quickly checks if a file begins with the encryption magic number.
2028+ * This is faster than reading the full header when you only need to
2029+ * know if the file is encrypted.
2030+ *
2031+ * @param filepath File path to check
2032+ * @param algorithm Output parameter for algorithm (can be NULL)
2033+ * @return true if file is encrypted, false otherwise
2034+ */
2035+ bool taosIsEncryptedFile (const char * filepath , int32_t * algorithm ) {
2036+ if (filepath == NULL ) {
2037+ terrno = TSDB_CODE_INVALID_PARA ;
2038+ return false;
2039+ }
2040+
2041+ // Check if file exists
2042+ if (!taosCheckExistFile (filepath )) {
2043+ return false;
2044+ }
2045+
2046+ // Read header
2047+ STdEncryptFileHeader header ;
2048+ int32_t code = taosReadEncryptFileHeader (filepath , & header );
2049+
2050+ if (code != 0 ) {
2051+ return false;
2052+ }
2053+
2054+ // Return algorithm if requested
2055+ if (algorithm != NULL ) {
2056+ * algorithm = header .algorithm ;
2057+ }
2058+
2059+ return true;
2060+ }
0 commit comments