void *realloc(void *ptr, size_t size) { void *newptr; size_t oldsize; if(ptr == NULL) { return malloc(size); } oldsize = *((size_t *) (ptr - sizeof(size_t))); if(size == 0) { newptr = NULL; } else { newptr = malloc(size); RedMemCpy(newptr, ptr, REDMIN(size, oldsize)); } free(ptr); return newptr; }
/** @brief Write sectors to a disk. @param bVolNum The volume number of the volume whose block device is being written to. @param ullSectorStart The starting sector number. @param ulSectorCount The number of sectors to write. @param pBuffer The buffer from which to write the sector data. @return A negated ::REDSTATUS code indicating the operation result. @retval 0 Operation was successful. */ static REDSTATUS DiskWrite( uint8_t bVolNum, uint64_t ullSectorStart, uint32_t ulSectorCount, const void *pBuffer) { REDSTATUS ret; if(gapbRamDisk[bVolNum] == NULL) { ret = -RED_EINVAL; } else { uint64_t ullByteOffset = ullSectorStart * gaRedVolConf[bVolNum].ulSectorSize; uint32_t ulByteCount = ulSectorCount * gaRedVolConf[bVolNum].ulSectorSize; RedMemCpy(&gapbRamDisk[bVolNum][ullByteOffset], pBuffer, ulByteCount); ret = 0; } return ret; }
/** @brief Finalize a metadata buffer. This updates the CRC and the sequence number. It also sets the signature, though this is only truly needed if the buffer is new. @param pbBuffer Pointer to the metadata buffer to finalize. @param bVolNum The volume number for the metadata buffer. @param uFlags The associated buffer flags. Used to determine the expected signature. @return A negated ::REDSTATUS code indicating the operation result. @retval 0 Operation was successful. @retval -RED_EINVAL Invalid parameter; or maximum sequence number reached. */ static REDSTATUS BufferFinalize( uint8_t *pbBuffer, uint8_t bVolNum, uint16_t uFlags) { REDSTATUS ret = 0; if((pbBuffer == NULL) || (bVolNum >= REDCONF_VOLUME_COUNT) || ((uFlags & BFLAG_MASK) != uFlags)) { REDERROR(); ret = -RED_EINVAL; } else { uint32_t ulSignature; switch(uFlags & BFLAG_META_MASK) { case BFLAG_META_MASTER: ulSignature = META_SIG_MASTER; break; #if REDCONF_IMAP_EXTERNAL == 1 case BFLAG_META_IMAP: ulSignature = META_SIG_IMAP; break; #endif case BFLAG_META_INODE: ulSignature = META_SIG_INODE; break; #if DINDIR_POINTERS > 0U case BFLAG_META_DINDIR: ulSignature = META_SIG_DINDIR; break; #endif #if REDCONF_DIRECT_POINTERS < INODE_ENTRIES case BFLAG_META_INDIR: ulSignature = META_SIG_INDIR; break; #endif default: ulSignature = 0U; break; } if(ulSignature == 0U) { REDERROR(); ret = -RED_EINVAL; } else { uint64_t ullSeqNum = gaRedVolume[bVolNum].ullSequence; ret = RedVolSeqNumIncrement(bVolNum); if(ret == 0) { uint32_t ulCrc; RedMemCpy(&pbBuffer[NODEHEADER_OFFSET_SIG], &ulSignature, sizeof(ulSignature)); RedMemCpy(&pbBuffer[NODEHEADER_OFFSET_SEQ], &ullSeqNum, sizeof(ullSeqNum)); #ifdef REDCONF_ENDIAN_SWAP BufferEndianSwap(pbBuffer, uFlags); #endif ulCrc = RedCrcNode(pbBuffer); #ifdef REDCONF_ENDIAN_SWAP ulCrc = RedRev32(ulCrc); #endif RedMemCpy(&pbBuffer[NODEHEADER_OFFSET_CRC], &ulCrc, sizeof(ulCrc)); } } } return ret; }
/** Determine whether a metadata buffer is valid. This includes checking its signature, CRC, and sequence number. @param pbBuffer Pointer to the metadata buffer to validate. @param uFlags The buffer flags provided by the caller. Used to determine the expected signature. @return Whether the metadata buffer is valid. @retval true The metadata buffer is valid. @retval false The metadata buffer is invalid. */ static bool BufferIsValid( const uint8_t *pbBuffer, uint16_t uFlags) { bool fValid; if((pbBuffer == NULL) || ((uFlags & BFLAG_MASK) != uFlags)) { REDERROR(); fValid = false; } else { NODEHEADER buf; uint16_t uMetaFlags = uFlags & BFLAG_META_MASK; /* Casting pbBuffer to (NODEHEADER *) would run afoul MISRA-C:2012 R11.3, so instead copy the fields out. */ RedMemCpy(&buf.ulSignature, &pbBuffer[NODEHEADER_OFFSET_SIG], sizeof(buf.ulSignature)); RedMemCpy(&buf.ulCRC, &pbBuffer[NODEHEADER_OFFSET_CRC], sizeof(buf.ulCRC)); RedMemCpy(&buf.ullSequence, &pbBuffer[NODEHEADER_OFFSET_SEQ], sizeof(buf.ullSequence)); #ifdef REDCONF_ENDIAN_SWAP buf.ulCRC = RedRev32(buf.ulCRC); buf.ulSignature = RedRev32(buf.ulSignature); buf.ullSequence = RedRev64(buf.ullSequence); #endif /* Make sure the signature is correct for the type of metadata block requested by the caller. */ switch(buf.ulSignature) { case META_SIG_MASTER: fValid = (uMetaFlags == BFLAG_META_MASTER); break; #if REDCONF_IMAP_EXTERNAL == 1 case META_SIG_IMAP: fValid = (uMetaFlags == BFLAG_META_IMAP); break; #endif case META_SIG_INODE: fValid = (uMetaFlags == BFLAG_META_INODE); break; #if DINDIR_POINTERS > 0U case META_SIG_DINDIR: fValid = (uMetaFlags == BFLAG_META_DINDIR); break; #endif #if REDCONF_DIRECT_POINTERS < INODE_ENTRIES case META_SIG_INDIR: fValid = (uMetaFlags == BFLAG_META_INDIR); break; #endif default: fValid = false; break; } if(fValid) { uint32_t ulComputedCrc; /* Check for disk corruption by comparing the stored CRC with one computed from the data. Also check the sequence number: if it is greater than the current sequence number, the block is from a previous format or the disk is writing blocks out of order. During mount, before the metaroots have been read, the sequence number will be unknown, and the check is skipped. */ ulComputedCrc = RedCrcNode(pbBuffer); if(buf.ulCRC != ulComputedCrc) { fValid = false; } else if(gpRedVolume->fMounted && (buf.ullSequence >= gpRedVolume->ullSequence)) { fValid = false; } else { /* Buffer is valid. No action, fValid is already true. */ } } } return fValid; }