@@ -4165,6 +4165,7 @@ SARA_R5_error_t SARA_R5::gpsAidingServerConf(const char *primaryServer, const ch
4165
4165
return err;
4166
4166
}
4167
4167
4168
+ // OK for text files. But will fail with binary files (containing \0) on some platforms.
4168
4169
SARA_R5_error_t SARA_R5::getFileContents (String filename, String *contents)
4169
4170
{
4170
4171
SARA_R5_error_t err;
@@ -4251,6 +4252,9 @@ SARA_R5_error_t SARA_R5::getFileContents(String filename, String *contents)
4251
4252
while (bytesRead < readFileSize)
4252
4253
{
4253
4254
searchPtr++; // Increment searchPtr then copy file char into contents
4255
+ // Important Note: some implementations of concat, like the one on ESP32, are binary-compatible.
4256
+ // But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's.
4257
+ // The only true binary-compatible solution is to use getFileContents(String filename, char *contents)...
4254
4258
contents->concat (*(searchPtr)); // Append file char to contents
4255
4259
bytesRead++;
4256
4260
}
@@ -4283,6 +4287,124 @@ SARA_R5_error_t SARA_R5::getFileContents(String filename, String *contents)
4283
4287
return err;
4284
4288
}
4285
4289
4290
+ // OK for binary files. Make sure contents can hold the entire file. Get the size first with getFileSize.
4291
+ SARA_R5_error_t SARA_R5::getFileContents (String filename, char *contents)
4292
+ {
4293
+ SARA_R5_error_t err;
4294
+ char *command;
4295
+ char *response;
4296
+
4297
+ // Start by getting the file size so we know in advance how much data to expect
4298
+ int fileSize = 0 ;
4299
+ err = getFileSize (filename, &fileSize);
4300
+ if (err != SARA_R5_SUCCESS)
4301
+ {
4302
+ if (_printDebug == true )
4303
+ {
4304
+ _debugPort->print (F (" getFileContents: getFileSize returned err " ));
4305
+ _debugPort->println (err);
4306
+ }
4307
+ return err;
4308
+ }
4309
+
4310
+ command = sara_r5_calloc_char (strlen (SARA_R5_FILE_SYSTEM_READ_FILE) + filename.length () + 8 );
4311
+ if (command == NULL )
4312
+ return SARA_R5_ERROR_OUT_OF_MEMORY;
4313
+ sprintf (command, " %s=\" %s\" " , SARA_R5_FILE_SYSTEM_READ_FILE, filename.c_str ());
4314
+
4315
+ response = sara_r5_calloc_char (fileSize + minimumResponseAllocation);
4316
+ if (response == NULL )
4317
+ {
4318
+ if (_printDebug == true )
4319
+ {
4320
+ _debugPort->print (F (" getFileContents: response alloc failed: " ));
4321
+ _debugPort->println (fileSize + minimumResponseAllocation);
4322
+ }
4323
+ free (command);
4324
+ return SARA_R5_ERROR_OUT_OF_MEMORY;
4325
+ }
4326
+
4327
+ // A large file will completely fill the backlog buffer - but it will be pruned afterwards
4328
+ // Note to self: if the file contents contain "OK\r\n" sendCommandWithResponse will return true too early...
4329
+ // To try and avoid this, look for \"\r\nOK\r\n
4330
+ const char fileReadTerm[] = " \"\r\n OK\r\n " ;
4331
+ err = sendCommandWithResponse (command, fileReadTerm,
4332
+ response, (5 * SARA_R5_STANDARD_RESPONSE_TIMEOUT),
4333
+ (fileSize + minimumResponseAllocation));
4334
+
4335
+ if (err != SARA_R5_ERROR_SUCCESS)
4336
+ {
4337
+ if (_printDebug == true )
4338
+ {
4339
+ _debugPort->print (F (" getFileContents: sendCommandWithResponse returned err " ));
4340
+ _debugPort->println (err);
4341
+ }
4342
+ free (command);
4343
+ free (response);
4344
+ return err;
4345
+ }
4346
+
4347
+ // Response format: \r\n+URDFILE: "filename",36,"these bytes are the data of the file"\r\n\r\nOK\r\n
4348
+ int scanned = 0 ;
4349
+ int readFileSize = 0 ;
4350
+ char *searchPtr = strstr (response, " +URDFILE: " );
4351
+ if (searchPtr != NULL )
4352
+ {
4353
+ searchPtr = strchr (searchPtr, ' \" ' ); // Find the first quote
4354
+ searchPtr = strchr (++searchPtr, ' \" ' ); // Find the second quote
4355
+
4356
+ scanned = sscanf (searchPtr, " \" ,%d," , &readFileSize); // Get the file size (again)
4357
+ if (scanned == 1 )
4358
+ {
4359
+ searchPtr = strchr (++searchPtr, ' \" ' ); // Find the third quote
4360
+
4361
+ if (searchPtr == NULL )
4362
+ {
4363
+ if (_printDebug == true )
4364
+ {
4365
+ _debugPort->println (F (" getFileContents: third quote not found!" ));
4366
+ }
4367
+ free (command);
4368
+ free (response);
4369
+ return SARA_R5_ERROR_UNEXPECTED_RESPONSE;
4370
+ }
4371
+
4372
+ int bytesRead = 0 ;
4373
+
4374
+ while (bytesRead < readFileSize)
4375
+ {
4376
+ searchPtr++; // Increment searchPtr then copy file char into contents
4377
+ contents[bytesRead] = *searchPtr; // Append file char to contents
4378
+ bytesRead++;
4379
+ }
4380
+ if (_printDebug == true )
4381
+ {
4382
+ _debugPort->print (F (" getFileContents: total bytes read: " ));
4383
+ _debugPort->println (bytesRead);
4384
+ }
4385
+ err = SARA_R5_ERROR_SUCCESS;
4386
+ }
4387
+ else
4388
+ {
4389
+ if (_printDebug == true )
4390
+ {
4391
+ _debugPort->print (F (" getFileContents: sscanf failed! scanned is " ));
4392
+ _debugPort->println (scanned);
4393
+ }
4394
+ err = SARA_R5_ERROR_UNEXPECTED_RESPONSE;
4395
+ }
4396
+ }
4397
+ else
4398
+ {
4399
+ if (_printDebug == true )
4400
+ _debugPort->println (F (" getFileContents: strstr failed!" ));
4401
+ err = SARA_R5_ERROR_UNEXPECTED_RESPONSE;
4402
+ }
4403
+
4404
+ free (command);
4405
+ free (response);
4406
+ return err;
4407
+ }
4286
4408
SARA_R5_error_t SARA_R5::getFileSize (String filename, int *size)
4287
4409
{
4288
4410
SARA_R5_error_t err;
@@ -4920,7 +5042,11 @@ SARA_R5_error_t SARA_R5::parseSocketReadIndication(int socket, int length)
4920
5042
if (_socketReadCallback != NULL )
4921
5043
{
4922
5044
String dataAsString = " " ; // Create an empty string
4923
- for (int i = 0 ; i < bytesRead; i++) // Copy the data from readDest into the String in a binary-compatible way
5045
+ // Copy the data from readDest into the String in a binary-compatible way
5046
+ // Important Note: some implementations of concat, like the one on ESP32, are binary-compatible.
5047
+ // But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's.
5048
+ // The only true binary-compatible solution is to use socketReadCallbackPlus...
5049
+ for (int i = 0 ; i < bytesRead; i++)
4924
5050
dataAsString.concat (readDest[i]);
4925
5051
_socketReadCallback (socket, dataAsString);
4926
5052
}
@@ -4969,6 +5095,9 @@ SARA_R5_error_t SARA_R5::parseSocketReadIndicationUDP(int socket, int length)
4969
5095
if (_socketReadCallback != NULL )
4970
5096
{
4971
5097
String dataAsString = " " ; // Create an empty string
5098
+ // Important Note: some implementations of concat, like the one on ESP32, are binary-compatible.
5099
+ // But some, like SAMD, are not. They use strlen or strcpy internally - which don't like \0's.
5100
+ // The only true binary-compatible solution is to use socketReadCallbackPlus...
4972
5101
for (int i = 0 ; i < bytesRead; i++) // Copy the data from readDest into the String in a binary-compatible way
4973
5102
dataAsString.concat (readDest[i]);
4974
5103
_socketReadCallback (socket, dataAsString);
0 commit comments