* Write data to an open file. * * \note Data is moved to the cache but may not be written to the * storage device until sync() is called. * * \param[in] buf Pointer to the location of the data to be written. * * \param[in] nbyte Number of bytes to write. * * \return For success write() returns the number of bytes written, always * \a nbyte. If an error occurs, write() returns -1. Possi
| 2170 | * for a read-only file, device is full, a corrupt file system or an I/O error. |
| 2171 | */ |
| 2172 | int16_t SdBaseFile::write(const void *buf, const uint16_t nbyte) { |
| 2173 | #if ENABLED(SDCARD_READONLY) |
| 2174 | writeError = true; return -1; |
| 2175 | #endif |
| 2176 | |
| 2177 | // convert void* to uint8_t* - must be before goto statements |
| 2178 | const uint8_t *src = reinterpret_cast<const uint8_t*>(buf); |
| 2179 | |
| 2180 | // number of bytes left to write - must be before goto statements |
| 2181 | uint16_t nToWrite = nbyte; |
| 2182 | |
| 2183 | // error if not a normal file or is read-only |
| 2184 | if (!isFile() || !(flags_ & O_WRITE)) goto FAIL; |
| 2185 | |
| 2186 | // seek to end of file if append flag |
| 2187 | if ((flags_ & O_APPEND) && curPosition_ != fileSize_) { |
| 2188 | if (!seekEnd()) goto FAIL; |
| 2189 | } |
| 2190 | |
| 2191 | while (nToWrite > 0) { |
| 2192 | uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); |
| 2193 | uint16_t blockOffset = curPosition_ & 0x1FF; |
| 2194 | if (blockOfCluster == 0 && blockOffset == 0) { |
| 2195 | // start of new cluster |
| 2196 | if (curCluster_ == 0) { |
| 2197 | if (firstCluster_ == 0) { |
| 2198 | // allocate first cluster of file |
| 2199 | if (!addCluster()) goto FAIL; |
| 2200 | } |
| 2201 | else { |
| 2202 | curCluster_ = firstCluster_; |
| 2203 | } |
| 2204 | } |
| 2205 | else { |
| 2206 | uint32_t next; |
| 2207 | if (!vol_->fatGet(curCluster_, &next)) goto FAIL; |
| 2208 | if (vol_->isEOC(next)) { |
| 2209 | // add cluster if at end of chain |
| 2210 | if (!addCluster()) goto FAIL; |
| 2211 | } |
| 2212 | else { |
| 2213 | curCluster_ = next; |
| 2214 | } |
| 2215 | } |
| 2216 | } |
| 2217 | // max space in block |
| 2218 | uint16_t n = 512 - blockOffset; |
| 2219 | |
| 2220 | // lesser of space and amount to write |
| 2221 | NOMORE(n, nToWrite); |
| 2222 | |
| 2223 | // block for data write |
| 2224 | uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; |
| 2225 | if (n == 512) { |
| 2226 | // full block - don't need to use cache |
| 2227 | if (vol_->cacheBlockNumber() == block) { |
| 2228 | // invalidate cache if block is in cache |
| 2229 | vol_->cacheSetBlockNumber(0xFFFFFFFF, false); |
nothing calls this directly
no test coverage detected