@@ -80,6 +80,17 @@ struct littlefs_mountpt_s
80
80
struct lfs lfs ;
81
81
};
82
82
83
+ struct littlefs_attr_s
84
+ {
85
+ uint32_t at_ver ; /* For the later extension */
86
+ uint32_t at_mode ; /* File type, attributes, and access mode bits */
87
+ uint32_t at_uid ; /* User ID of file */
88
+ uint32_t at_gid ; /* Group ID of file */
89
+ uint64_t at_atim ; /* Time of last access */
90
+ uint64_t at_mtim ; /* Time of last modification */
91
+ uint64_t at_ctim ; /* Time of last status change */
92
+ };
93
+
83
94
/****************************************************************************
84
95
* Private Function Prototypes
85
96
****************************************************************************/
@@ -101,6 +112,8 @@ static int littlefs_dup(FAR const struct file *oldp,
101
112
FAR struct file * newp );
102
113
static int littlefs_fstat (FAR const struct file * filep ,
103
114
FAR struct stat * buf );
115
+ static int littlefs_fchstat (FAR const struct file * filep ,
116
+ FAR const struct stat * buf , int flags );
104
117
static int littlefs_truncate (FAR struct file * filep ,
105
118
off_t length );
106
119
@@ -133,6 +146,9 @@ static int littlefs_rename(FAR struct inode *mountpt,
133
146
FAR const char * newrelpath );
134
147
static int littlefs_stat (FAR struct inode * mountpt ,
135
148
FAR const char * relpath , FAR struct stat * buf );
149
+ static int littlefs_chstat (FAR struct inode * mountpt ,
150
+ FAR const char * relpath ,
151
+ FAR const struct stat * buf , int flags );
136
152
137
153
/****************************************************************************
138
154
* Public Data
@@ -158,7 +174,7 @@ const struct mountpt_operations g_littlefs_operations =
158
174
littlefs_sync , /* sync */
159
175
littlefs_dup , /* dup */
160
176
littlefs_fstat , /* fstat */
161
- NULL , /* fchstat */
177
+ littlefs_fchstat , /* fchstat */
162
178
163
179
littlefs_opendir , /* opendir */
164
180
littlefs_closedir , /* closedir */
@@ -174,7 +190,7 @@ const struct mountpt_operations g_littlefs_operations =
174
190
littlefs_rmdir , /* rmdir */
175
191
littlefs_rename , /* rename */
176
192
littlefs_stat , /* stat */
177
- NULL /* chstat */
193
+ littlefs_chstat /* chstat */
178
194
};
179
195
180
196
/****************************************************************************
@@ -327,6 +343,26 @@ static int littlefs_open(FAR struct file *filep, FAR const char *relpath,
327
343
goto errout ;
328
344
}
329
345
346
+ if (oflags & LFS_O_CREAT )
347
+ {
348
+ struct littlefs_attr_s attr ;
349
+ struct timespec time ;
350
+
351
+ clock_gettime (CLOCK_REALTIME , & time );
352
+ memset (& attr , 0 , sizeof (attr ));
353
+ attr .at_mode = mode ;
354
+ attr .at_ctim = 1000000000ull * time .tv_sec + time .tv_nsec ;
355
+ attr .at_atim = attr .at_ctim ;
356
+ attr .at_mtim = attr .at_ctim ;
357
+ ret = littlefs_convert_result (lfs_setattr (& fs -> lfs , relpath , 0 ,
358
+ & attr , sizeof (attr )));
359
+ if (ret < 0 )
360
+ {
361
+ lfs_remove (& fs -> lfs , relpath );
362
+ goto errout_with_file ;
363
+ }
364
+ }
365
+
330
366
/* In append mode, we need to set the file pointer to the end of the
331
367
* file.
332
368
*/
@@ -690,6 +726,7 @@ static int littlefs_fstat(FAR const struct file *filep, FAR struct stat *buf)
690
726
FAR struct littlefs_mountpt_s * fs ;
691
727
FAR struct littlefs_file_s * priv ;
692
728
FAR struct inode * inode ;
729
+ char path [LFS_NAME_MAX ];
693
730
int ret ;
694
731
695
732
memset (buf , 0 , sizeof (* buf ));
@@ -708,17 +745,57 @@ static int littlefs_fstat(FAR const struct file *filep, FAR struct stat *buf)
708
745
return ret ;
709
746
}
710
747
711
- buf -> st_size = lfs_file_size (& fs -> lfs , & priv -> file );
748
+ ret = lfs_file_path (& fs -> lfs , & priv -> file , path , sizeof ( path ) );
712
749
nxmutex_unlock (& fs -> lock );
750
+ if (ret < 0 )
751
+ {
752
+ return ret ;
753
+ }
713
754
714
- if (buf -> st_size < 0 )
755
+ ret = littlefs_stat (inode , path , buf );
756
+ if (ret < 0 )
715
757
{
716
- return littlefs_convert_result ( buf -> st_size ) ;
758
+ return ret ;
717
759
}
718
760
719
- buf -> st_mode = S_IRWXO | S_IRWXG | S_IRWXU | S_IFREG ;
720
- buf -> st_blksize = fs -> cfg .block_size ;
721
- buf -> st_blocks = (buf -> st_size + buf -> st_blksize - 1 ) / buf -> st_blksize ;
761
+ return OK ;
762
+ }
763
+
764
+ static int littlefs_fchstat (FAR const struct file * filep ,
765
+ FAR const struct stat * buf , int flags )
766
+ {
767
+ FAR struct littlefs_mountpt_s * fs ;
768
+ FAR struct littlefs_file_s * priv ;
769
+ FAR struct inode * inode ;
770
+ char path [LFS_NAME_MAX ];
771
+ int ret ;
772
+
773
+ /* Recover our private data from the struct file instance */
774
+
775
+ priv = filep -> f_priv ;
776
+ inode = filep -> f_inode ;
777
+ fs = inode -> i_private ;
778
+
779
+ /* Call LFS to get file size */
780
+
781
+ ret = nxmutex_lock (& fs -> lock );
782
+ if (ret < 0 )
783
+ {
784
+ return ret ;
785
+ }
786
+
787
+ ret = lfs_file_path (& fs -> lfs , & priv -> file , path , sizeof (path ));
788
+ nxmutex_unlock (& fs -> lock );
789
+ if (ret < 0 )
790
+ {
791
+ return ret ;
792
+ }
793
+
794
+ ret = littlefs_chstat (inode , path , buf , flags );
795
+ if (ret < 0 )
796
+ {
797
+ return ret ;
798
+ }
722
799
723
800
return OK ;
724
801
}
@@ -1445,6 +1522,7 @@ static int littlefs_stat(FAR struct inode *mountpt, FAR const char *relpath,
1445
1522
{
1446
1523
FAR struct littlefs_mountpt_s * fs ;
1447
1524
struct lfs_info info ;
1525
+ struct littlefs_attr_s attr ;
1448
1526
int ret ;
1449
1527
1450
1528
memset (buf , 0 , sizeof (* buf ));
@@ -1462,28 +1540,112 @@ static int littlefs_stat(FAR struct inode *mountpt, FAR const char *relpath,
1462
1540
}
1463
1541
1464
1542
ret = lfs_stat (& fs -> lfs , relpath , & info );
1465
- nxmutex_unlock (& fs -> lock );
1466
-
1467
- if (ret >= 0 )
1543
+ if (ret < 0 )
1468
1544
{
1469
- /* Convert info to stat */
1545
+ goto errout ;
1546
+ }
1470
1547
1471
- buf -> st_mode = S_IRWXO | S_IRWXG | S_IRWXU ;
1472
- if (info .type == LFS_TYPE_REG )
1548
+ ret = littlefs_convert_result (lfs_getattr (& fs -> lfs , relpath , 0 ,
1549
+ & attr , sizeof (attr )));
1550
+ if (ret < 0 )
1551
+ {
1552
+ if (ret != - ENODATA )
1473
1553
{
1474
- buf -> st_mode |= S_IFREG ;
1475
- buf -> st_size = info .size ;
1554
+ goto errout ;
1476
1555
}
1477
- else
1556
+
1557
+ memset (& attr , 0 , sizeof (attr ));
1558
+ }
1559
+
1560
+ buf -> st_mode = attr .at_mode ;
1561
+ buf -> st_uid = attr .at_uid ;
1562
+ buf -> st_gid = attr .at_gid ;
1563
+ buf -> st_atim .tv_sec = attr .at_atim / 1000000000ull ;
1564
+ buf -> st_atim .tv_nsec = attr .at_atim % 1000000000ull ;
1565
+ buf -> st_mtim .tv_sec = attr .at_mtim / 1000000000ull ;
1566
+ buf -> st_mtim .tv_nsec = attr .at_mtim % 1000000000ull ;
1567
+ buf -> st_ctim .tv_sec = attr .at_ctim / 1000000000ull ;
1568
+ buf -> st_ctim .tv_nsec = attr .at_ctim % 1000000000ull ;
1569
+ buf -> st_size = info .size ;
1570
+ buf -> st_blksize = fs -> cfg .block_size ;
1571
+ buf -> st_blocks = (buf -> st_size + buf -> st_blksize - 1 ) /
1572
+ buf -> st_blksize ;
1573
+
1574
+ errout :
1575
+ nxmutex_unlock (& fs -> lock );
1576
+ return ret ;
1577
+ }
1578
+
1579
+ static int littlefs_chstat (FAR struct inode * mountpt ,
1580
+ FAR const char * relpath ,
1581
+ FAR const struct stat * buf , int flags )
1582
+ {
1583
+ FAR struct littlefs_mountpt_s * fs ;
1584
+ struct littlefs_attr_s attr ;
1585
+ int ret ;
1586
+
1587
+ /* Get the mountpoint private data from the inode structure */
1588
+
1589
+ fs = mountpt -> i_private ;
1590
+
1591
+ /* Call LFS to get file size */
1592
+
1593
+ ret = nxmutex_lock (& fs -> lock );
1594
+ if (ret < 0 )
1595
+ {
1596
+ return ret ;
1597
+ }
1598
+
1599
+ ret = littlefs_convert_result (lfs_getattr (& fs -> lfs , relpath , 0 ,
1600
+ & attr , sizeof (attr )));
1601
+ if (ret < 0 )
1602
+ {
1603
+ if (ret != - ENODATA )
1478
1604
{
1479
- buf -> st_mode |= S_IFDIR ;
1480
- buf -> st_size = 0 ;
1605
+ goto errout ;
1481
1606
}
1482
1607
1483
- buf -> st_blksize = fs -> cfg .block_size ;
1484
- buf -> st_blocks = (buf -> st_size + buf -> st_blksize - 1 ) /
1485
- buf -> st_blksize ;
1608
+ memset (& attr , 0 , sizeof (attr ));
1609
+ }
1610
+
1611
+ if ((CH_STAT_MODE & flags ) == CH_STAT_MODE )
1612
+ {
1613
+ attr .at_mode = buf -> st_mode ;
1614
+ }
1615
+
1616
+ if ((CH_STAT_UID & flags ) == CH_STAT_UID )
1617
+ {
1618
+ attr .at_uid = buf -> st_uid ;
1486
1619
}
1487
1620
1621
+ if ((CH_STAT_GID & flags ) == CH_STAT_GID )
1622
+ {
1623
+ attr .at_gid = buf -> st_gid ;
1624
+ }
1625
+
1626
+ attr .at_ctim = 1000000000ull * buf -> st_ctim .tv_sec +
1627
+ buf -> st_ctim .tv_nsec ;
1628
+
1629
+ if ((CH_STAT_ATIME & flags ) == CH_STAT_ATIME )
1630
+ {
1631
+ attr .at_atim = 1000000000ull * buf -> st_atim .tv_sec +
1632
+ buf -> st_atim .tv_nsec ;
1633
+ }
1634
+
1635
+ if ((CH_STAT_MTIME & flags ) == CH_STAT_MTIME )
1636
+ {
1637
+ attr .at_mtim = 1000000000ull * buf -> st_mtim .tv_sec +
1638
+ buf -> st_mtim .tv_nsec ;
1639
+ }
1640
+
1641
+ ret = littlefs_convert_result (lfs_setattr (& fs -> lfs , relpath , 0 ,
1642
+ & attr , sizeof (attr )));
1643
+ if (ret < 0 )
1644
+ {
1645
+ goto errout ;
1646
+ }
1647
+
1648
+ errout :
1649
+ nxmutex_unlock (& fs -> lock );
1488
1650
return ret ;
1489
1651
}
0 commit comments