@@ -46,9 +46,20 @@ File::File (Adafruit_LittleFS &fs)
4646File::File (char const *filename, uint8_t mode, Adafruit_LittleFS &fs)
4747 : File(fs)
4848{
49+ // public constructor calls public API open(), which will obtain the mutex
4950 this ->open (filename, mode);
5051}
5152
53+ File::File (uint8_t differentiator, char const *filename, uint8_t mode, Adafruit_LittleFS &fs)
54+ : File(fs)
55+ {
56+ // private constructor calls private API _open(), which does NOT obtain the mutex
57+ (void )differentiator;
58+ this ->_open (filename, mode);
59+ }
60+
61+
62+
5263bool File::_open_file (char const *filepath, uint8_t mode)
5364{
5465 int flags = (mode == FILE_O_READ) ? LFS_O_RDONLY :
@@ -99,12 +110,23 @@ bool File::_open_dir (char const *filepath)
99110 return true ;
100111}
101112
113+ // TODO: wrap close() because it must be called by open()
114+ // TODO: wrap open() because it is called by openNextFile()
115+
102116bool File::open (char const *filepath, uint8_t mode)
117+ {
118+ bool ret = false ;
119+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
120+ ret = this ->_open (filepath, mode);
121+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
122+ return ret;
123+ }
124+ bool File::_open (char const *filepath, uint8_t mode)
103125{
104126 bool ret = false ;
105127
106128 // close if currently opened
107- if ( (* this ) ) close ();
129+ if ( this -> _isOpen ( ) ) _close ();
108130
109131 struct lfs_info info;
110132 int rc = lfs_stat (_fs->getFS (), filepath, &info);
@@ -130,151 +152,260 @@ bool File::open (char const *filepath, uint8_t mode)
130152 char const * splash = strrchr (filepath, ' /' );
131153 strncpy (_name, splash ? (splash + 1 ) : filepath, LFS_NAME_MAX);
132154 }
133-
134155 return ret;
135156}
136157
137158size_t File::write (uint8_t ch)
138159{
139- VERIFY (!_is_dir, 0 );
140160 return write (&ch, 1 );
141161}
142162
143163size_t File::write (uint8_t const *buf, size_t size)
144164{
145- VERIFY (!_is_dir, 0 );
146-
147- lfs_ssize_t wrcount = lfs_file_write (_fs->getFS (), _file, buf, size);
148- VERIFY (wrcount > 0 , 0 );
165+ lfs_ssize_t wrcount = 0 ;
166+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
167+ if (!this ->_is_dir )
168+ {
169+ wrcount = lfs_file_write (_fs->getFS (), _file, buf, size);
170+ if (wrcount < 0 )
171+ {
172+ wrcount = 0 ;
173+ };
174+ }
175+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
149176 return wrcount;
150177}
151178
152179int File::read (void )
153180{
154- VERIFY (!_is_dir, -1 );
181+ // this thin wrapper relies on called function to synchronize
182+ int ret = -1 ;
155183 uint8_t ch;
156- return (read (&ch, 1 ) > 0 ) ? ch : -1 ;
184+ if (read (&ch, 1 ) > 0 )
185+ {
186+ ret = static_cast <int >(ch);
187+ }
188+ return ret;
157189}
158190
159191int File::read (void *buf, uint16_t nbyte)
160192{
161- VERIFY (!_is_dir, 0 );
162- return lfs_file_read (_fs->getFS (), _file, buf, nbyte);
193+ int ret = 0 ;
194+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
195+ if (!this ->_is_dir )
196+ {
197+ ret = lfs_file_read (_fs->getFS (), _file, buf, nbyte);
198+ }
199+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
200+ return ret;
163201}
164202
165203int File::peek (void )
166204{
167- VERIFY (!_is_dir, -1 );
168-
169- int ch = read ();
170- uint32_t pos = position ();
171- seek ((pos > 0 ) ? (pos - 1 ) : 0 );
172- return ch;
205+ int ret = -1 ;
206+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
207+ if (!this ->_is_dir )
208+ {
209+ uint32_t pos = lfs_file_tell (_fs->getFS (), _file);
210+ uint8_t ch = 0 ;
211+ if (lfs_file_read (_fs->getFS (), _file, &ch, 1 ) > 0 )
212+ {
213+ ret = static_cast <int >(ch);
214+ }
215+ (void )lfs_file_seek (_fs->getFS (), _file, pos, LFS_SEEK_SET);
216+ }
217+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
218+ return ret;
173219}
174220
175221int File::available (void )
176222{
177- return size () - position ();
223+ int ret = 0 ;
224+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
225+ if (!this ->_is_dir )
226+ {
227+ uint32_t size = lfs_file_size (_fs->getFS (), _file);
228+ uint32_t pos = lfs_file_tell (_fs->getFS (), _file);
229+ ret = size - pos;
230+ }
231+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
232+ return ret;
178233}
179234
180235bool File::seek (uint32_t pos)
181236{
182- VERIFY (!_is_dir, false );
183- return lfs_file_seek (_fs->getFS (), _file, pos, LFS_SEEK_SET) >= 0 ;
237+ bool ret = false ;
238+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
239+ if (!this ->_is_dir )
240+ {
241+ ret = lfs_file_seek (_fs->getFS (), _file, pos, LFS_SEEK_SET) >= 0 ;
242+ }
243+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
244+ return ret;
184245}
185246
186247uint32_t File::position (void )
187248{
188- VERIFY (!_is_dir, 0 );
189- return lfs_file_tell (_fs->getFS (), _file);
249+ uint32_t ret = 0 ;
250+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
251+ if (!this ->_is_dir )
252+ {
253+ ret = lfs_file_tell (_fs->getFS (), _file);
254+ }
255+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
256+ return ret;
190257}
191258
192259uint32_t File::size (void )
193260{
194- VERIFY (!_is_dir, 0 );
195- return lfs_file_size (_fs->getFS (), _file);
261+ uint32_t ret = 0 ;
262+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
263+ if (!this ->_is_dir )
264+ {
265+ ret = lfs_file_size (_fs->getFS (), _file);
266+ }
267+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
268+ return ret;
269+
196270}
197271
198272void File::flush (void )
199273{
200- VERIFY (!_is_dir,);
201- lfs_file_sync (_fs->getFS (), _file);
274+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
275+ if (!this ->_is_dir )
276+ {
277+ lfs_file_sync (_fs->getFS (), _file);
278+ }
279+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
280+ return ;
202281}
203282
204283void File::close (void )
205284{
206- if ( (*this ) )
285+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
286+ this ->_close ();
287+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
288+ }
289+ void File::_close (void )
290+ {
291+ if ( this ->_isOpen () )
207292 {
208- if ( _is_dir )
293+ if ( this -> _is_dir )
209294 {
210295 lfs_dir_close (_fs->getFS (), _dir);
211296 rtos_free (_dir);
212297 _dir = NULL ;
213298
214- if ( _dir_path ) rtos_free (_dir_path);
299+ if ( this -> _dir_path ) rtos_free (_dir_path);
215300 _dir_path = NULL ;
216301 }
217302 else
218303 {
219- lfs_file_close (_fs->getFS (), _file);
304+ lfs_file_close (this -> _fs ->getFS (), _file);
220305 rtos_free (_file);
221306 _file = NULL ;
222307 }
223308 }
224309}
225310
311+ [[deprecated(" Recommend use of isOpen() for clarity" )]]
226312File::operator bool (void )
313+ {
314+ bool ret = false ;
315+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
316+ ret = this ->_isOpen ();
317+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
318+ return ret;
319+ }
320+ bool File::isOpen (void )
321+ {
322+ bool ret = 0 ;
323+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
324+ ret = this ->_isOpen ();
325+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
326+ return ret;
327+ }
328+ bool File::_isOpen (void )
227329{
228330 return (_file != NULL ) || (_dir != NULL );
229331}
230332
333+ // WARNING -- although marked as `const`, the values pointed
334+ // to may change. For example, if the same File
335+ // object has `open()` called with a different
336+ // file or directory name, this same pointer will
337+ // suddenly (unexpectedly?) have different values.
231338char const * File::name (void )
232339{
233- return _name;
340+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
341+ char const * ret = this ->_name ;
342+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
343+ return ret;
234344}
235345
236346bool File::isDirectory (void )
237347{
238- return _is_dir;
348+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
349+ bool ret = this ->_is_dir ;
350+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
351+ return ret;
352+
239353}
240354
241355File File::openNextFile (uint8_t mode)
242356{
243- File file (*_fs);
244-
245- if ( !_is_dir ) return file;
246-
247- struct lfs_info info;
248-
249- int rc;
357+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
250358
251- // lfs_dir_read return 0 when reaching end of directory, 1 if found an entry
252- // skip "." and ".." entries
253- do
359+ File ret (*_fs);
360+ if (this ->_is_dir )
254361 {
255- rc = lfs_dir_read (_fs-> getFS (), _dir, & info) ;
256- } while ( rc == 1 && (! strcmp ( " . " , info. name ) || ! strcmp ( " .. " , info. name )) ) ;
362+ struct lfs_info info;
363+ int rc;
257364
258- if ( rc == 1 )
259- {
260- // string cat name with current folder
261- char filepath[strlen (_dir_path) + 1 + strlen (info.name ) + 1 ];
365+ // lfs_dir_read returns 0 when reaching end of directory, 1 if found an entry
366+ // Skip the "." and ".." entries ...
367+ do
368+ {
369+ rc = lfs_dir_read (_fs->getFS (), _dir, &info);
370+ } while ( rc == 1 && (!strcmp (" ." , info.name ) || !strcmp (" .." , info.name )) );
262371
263- strcpy (filepath, _dir_path);
264- if ( !(_dir_path[0 ] == ' /' && _dir_path[1 ] == 0 ) ) strcat (filepath, " /" ); // only add '/' if cwd is not root
265- strcat (filepath, info.name );
372+ if ( rc == 1 )
373+ {
374+ // string cat name with current folder
375+ char filepath[strlen (_dir_path) + 1 + strlen (info.name ) + 1 ]; // potential for significant stack usage
376+ strcpy (filepath, _dir_path);
377+ if ( !(_dir_path[0 ] == ' /' && _dir_path[1 ] == 0 ) ) strcat (filepath, " /" ); // only add '/' if cwd is not root
378+ strcat (filepath, info.name );
266379
267- file.open (filepath, mode);
380+ (void )ret._open (filepath, mode); // return value is ignored ... caller is expected to check isOpened()
381+ }
382+ else if ( rc < 0 )
383+ {
384+ PRINT_LFS_ERR (rc);
385+ }
268386 }
269- else if ( rc < 0 )
387+ this ->DoNotCallFromOutsideClass_UnlockFilesystem ();
388+ return ret;
389+ }
390+
391+ void File::rewindDirectory (void )
392+ {
393+ this ->DoNotCallFromOutsideClass_LockFilesystem ();
394+ if (this ->_is_dir )
270395 {
271- PRINT_LFS_ERR (rc );
396+ lfs_dir_rewind (_fs-> getFS (), _dir );
272397 }
273-
274- return file ;
398+ this -> DoNotCallFromOutsideClass_UnlockFilesystem ();
399+ return ;
275400}
276401
277- void File::rewindDirectory (void )
402+ void File::DoNotCallFromOutsideClass_LockFilesystem (void )
278403{
279- VERIFY_LFS ( lfs_dir_rewind ( _fs->getFS (), _dir), );
404+ xSemaphoreTake ( this -> _fs ->_mutex , portMAX_DELAY );
280405}
406+ void File::DoNotCallFromOutsideClass_UnlockFilesystem (void )
407+ {
408+ xSemaphoreGive (this ->_fs ->_mutex );
409+ }
410+
411+
0 commit comments