File indexing completed on 2025-05-11 08:24:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039
0040 #include <rtems/libio_.h>
0041 #include <rtems/score/todimpl.h>
0042
0043 #include <fcntl.h>
0044 #include <string.h>
0045
0046
0047
0048
0049
0050
0051
0052
0053 bool rtems_filesystem_utime_tv_nsec_valid(struct timespec time)
0054 {
0055 if ( time.tv_nsec == UTIME_NOW ) {
0056 return true;
0057 }
0058
0059 if ( time.tv_nsec == UTIME_OMIT ) {
0060 return true;
0061 }
0062
0063 if ( time.tv_nsec < 0 ) {
0064 return false;
0065 }
0066
0067 if ( time.tv_nsec >= TOD_NANOSECONDS_PER_SECOND ) {
0068 return false;
0069 }
0070
0071 return true;
0072 }
0073
0074
0075 int rtems_filesystem_utime_check_permissions(
0076 const rtems_filesystem_location_info_t * currentloc,
0077 const struct timespec times[2]
0078 )
0079 {
0080 struct stat st = {};
0081 int rv;
0082 bool write_access;
0083
0084 rv = (*currentloc->handlers->fstat_h)( currentloc, &st );
0085 if ( rv != 0 ) {
0086 rtems_set_errno_and_return_minus_one( ENOENT );
0087 }
0088
0089 write_access = rtems_filesystem_check_access(
0090 RTEMS_FS_PERMS_WRITE,
0091 st.st_mode,
0092 st.st_uid,
0093 st.st_gid
0094 );
0095
0096
0097
0098
0099
0100 if ( (times == NULL) ||
0101 ( (times[0].tv_nsec == UTIME_NOW) && (times[1].tv_nsec == UTIME_NOW) )) {
0102 if ( !write_access ) {
0103 rtems_set_errno_and_return_minus_one( EACCES );
0104 }
0105 } else {
0106 if ( times[0].tv_nsec != UTIME_OMIT || times[1].tv_nsec != UTIME_OMIT ) {
0107 if ( !write_access ) {
0108 rtems_set_errno_and_return_minus_one( EPERM );
0109 }
0110 }
0111 }
0112
0113 return 0;
0114 }
0115
0116
0117
0118
0119
0120 int rtems_filesystem_utime_update(
0121 const struct timespec times[2],
0122 struct timespec new_times[2]
0123 )
0124 {
0125 bool got_time = false;
0126 struct timespec now;
0127
0128
0129
0130
0131
0132 if ( times == NULL ) {
0133 _Timespec_Set( &new_times[0], 0, UTIME_NOW );
0134 _Timespec_Set( &new_times[1], 0, UTIME_NOW );
0135 } else {
0136 new_times[0] = times[0];
0137 new_times[1] = times[1];
0138 }
0139
0140 if ( new_times[0].tv_nsec == UTIME_NOW ) {
0141 clock_gettime( CLOCK_REALTIME, &now );
0142 new_times[0] = now;
0143 got_time = true;
0144 }
0145
0146 if ( new_times[1].tv_nsec == UTIME_NOW ) {
0147 if ( !got_time ) {
0148 clock_gettime( CLOCK_REALTIME, &now );
0149 }
0150 new_times[1] = now;
0151 }
0152
0153 if ( !_Timespec_Is_non_negative( &new_times[0] ) ) {
0154 rtems_set_errno_and_return_minus_one( EINVAL );
0155 }
0156
0157 if ( !_Timespec_Is_non_negative( &new_times[1] ) ) {
0158 rtems_set_errno_and_return_minus_one( EINVAL );
0159 }
0160
0161 if ( !rtems_filesystem_utime_tv_nsec_valid( new_times[0] ) ) {
0162 rtems_set_errno_and_return_minus_one( EINVAL );
0163 }
0164
0165 if ( !rtems_filesystem_utime_tv_nsec_valid( new_times[1] ) ) {
0166 rtems_set_errno_and_return_minus_one( EINVAL );
0167 }
0168
0169 return 0;
0170 }
0171
0172
0173
0174
0175
0176
0177 int utimensat(
0178 int fd,
0179 const char *path,
0180 const struct timespec times[2],
0181 int flag
0182 )
0183 {
0184 int rv = 0;
0185 rtems_filesystem_eval_path_context_t ctx;
0186 int eval_flags = RTEMS_FS_FOLLOW_LINK;
0187 const rtems_filesystem_location_info_t *currentloc = NULL;
0188 struct timespec new_times[2];
0189
0190
0191
0192
0193 if ( fd != AT_FDCWD ) {
0194 rtems_set_errno_and_return_minus_one( ENOSYS );
0195 }
0196
0197
0198
0199
0200 if ( flag != 0 ) {
0201 rtems_set_errno_and_return_minus_one( ENOSYS );
0202 }
0203
0204 rv = rtems_filesystem_utime_update( times, new_times );
0205 if ( rv != 0 ) {
0206 return rv;
0207 }
0208
0209 currentloc = rtems_filesystem_eval_path_start( &ctx, path, eval_flags );
0210
0211 rv = rtems_filesystem_utime_check_permissions( currentloc, times );
0212 if ( rv != 0 ) {
0213 rtems_filesystem_eval_path_cleanup( &ctx );
0214 return rv;
0215 }
0216
0217 rv = (*currentloc->mt_entry->ops->utimens_h)(
0218 currentloc,
0219 new_times
0220 );
0221
0222 rtems_filesystem_eval_path_cleanup( &ctx );
0223
0224 return rv;
0225 }