GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_media_volume_get_extended.c Lines: 65 65 100.0 %
Date: 2026-03-06 18:49:02 Branches: 38 38 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** FileX Component                                                       */
17
/**                                                                       */
18
/**   Media                                                               */
19
/**                                                                       */
20
/**************************************************************************/
21
/**************************************************************************/
22
23
#define FX_SOURCE_CODE
24
25
26
/* Include necessary system files.  */
27
28
#include "fx_api.h"
29
#include "fx_system.h"
30
#include "fx_directory.h"
31
#include "fx_media.h"
32
#include "fx_utility.h"
33
34
35
/**************************************************************************/
36
/*                                                                        */
37
/*  FUNCTION                                               RELEASE        */
38
/*                                                                        */
39
/*    _fx_media_volume_get_extended                       PORTABLE C      */
40
/*                                                           6.1.11       */
41
/*  AUTHOR                                                                */
42
/*                                                                        */
43
/*    William E. Lamie, Microsoft Corporation                             */
44
/*                                                                        */
45
/*  DESCRIPTION                                                           */
46
/*                                                                        */
47
/*    This function reads the volume name stored in the media's boot      */
48
/*    record or root directory.                                           */
49
/*                                                                        */
50
/*  INPUT                                                                 */
51
/*                                                                        */
52
/*    media_ptr                             Media control block pointer   */
53
/*    volume_name                           Pointer to destination for    */
54
/*                                            the volume name (maximum    */
55
/*                                            11 characters + NULL)       */
56
/*    volume_name_buffer_length             Buffer length for volume_name */
57
/*    volume_source                         Source of volume              */
58
/*                                                                        */
59
/*  OUTPUT                                                                */
60
/*                                                                        */
61
/*    return status                                                       */
62
/*                                                                        */
63
/*  CALLS                                                                 */
64
/*                                                                        */
65
/*    _fx_utility_logical_sector_read       Read directory sector         */
66
/*    _fx_directory_entry_read              Directory entry read          */
67
/*                                                                        */
68
/*  CALLED BY                                                             */
69
/*                                                                        */
70
/*    Application Code                                                    */
71
/*                                                                        */
72
/**************************************************************************/
73
1023
UINT  _fx_media_volume_get_extended(FX_MEDIA *media_ptr, CHAR *volume_name, UINT volume_name_buffer_length, UINT volume_source)
74
{
75
76
UINT         status, offset;
77
ULONG        i;
78
INT          j;
79
80
FX_DIR_ENTRY dir_entry;
81
82
83
    /* Clear the volume name.  */
84
1023
    volume_name[0] =  FX_NULL;
85
86
    /* Check the media to make sure it is open.  */
87
1023
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
88
    {
89
90
        /* Return the media not opened error.  */
91
1001
        return(FX_MEDIA_NOT_OPEN);
92
    }
93
94
    /* If trace is enabled, insert this event into the trace buffer.  */
95
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_VOLUME_GET, media_ptr, volume_name, volume_source, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
96
97
    /* Protect against other threads accessing the media.  */
98
22
    FX_PROTECT
99
100
101
    /* Ensure the volume name is NULL initially.  */
102
22
    volume_name[0] =  FX_NULL;
103
104
22
    if (volume_source == FX_DIRECTORY_SECTOR)
105
    {
106
107
        /* Setup pointer to media name buffer.  */
108
13
        dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer;
109
110
        /* Clear the short name string.  */
111
13
        dir_entry.fx_dir_entry_short_name[0] =  0;
112
113
        /* Attempt to find the volume name in the root directory.  */
114
13
        i =  0;
115
        do
116
        {
117
118
            /* Read an entry from the root directory.  */
119
90
            status =  _fx_directory_entry_read(media_ptr, FX_NULL, &i, &dir_entry);
120
121
            /* Check for error status.  */
122
90
            if (status != FX_SUCCESS)
123
            {
124
125
                /* Release media protection.  */
126
1
                FX_UNPROTECT
127
128
                /* Return to caller.  */
129
1
                return(status);
130
            }
131
132
            /* Check for a volume name.  */
133

89
            if ((dir_entry.fx_dir_entry_attributes & FX_VOLUME) && ((UCHAR)dir_entry.fx_dir_entry_name[0] != (UCHAR)FX_DIR_ENTRY_FREE))
134
            {
135
136
                /* Yes, we have found a previously set volume name.  */
137
9
                break;
138
            }
139
140
            /* Move to next directory entry.  */
141
80
            i++;
142
80
        } while (i < media_ptr -> fx_media_root_directory_entries);
143
144
        /* Determine if a volume entry has been found.  */
145
12
        if (i < media_ptr -> fx_media_root_directory_entries)
146
        {
147
148
            /* Read the logical directory sector.  */
149
9
            status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
150
9
                                                      media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
151
152
            /* Determine if an error occurred.  */
153
9
            if (status != FX_SUCCESS)
154
            {
155
156
                /* Release media protection.  */
157
1
                FX_UNPROTECT
158
159
                /* Return error code.  */
160
1
                return(status);
161
            }
162
163
            /* Offset to volume label entry.  */
164
8
            offset = dir_entry.fx_dir_entry_byte_offset;
165
166
167
            /* Skip trailing space characters of volume name. */
168
63
            for (j = 10; j >= 0; j--)
169
            {
170
171
                /* Check for space character.  */
172
61
                if (media_ptr -> fx_media_memory_buffer[offset + (UINT)j] != (UCHAR)' ')
173
                {
174
175
                    /* Last character found. */
176
6
                    break;
177
                }
178
            }
179
180
            /* Check if the buffer is too short for the name.  */
181
8
            if (j >= (INT)volume_name_buffer_length - 1)
182
            {
183
184
                /* Buffer too short, return error.  */
185
1
                status =  FX_BUFFER_ERROR;
186
187
                /* Set character count to fit for the buffer.  */
188
1
                j = (INT)volume_name_buffer_length - 2;
189
            }
190
191
            /* NULL terminate the volume name.  */
192
8
            volume_name[j + 1] =  FX_NULL;
193
194
            /* Pickup the remaining characters of the volume name from the boot sector.  */
195
40
            for (; j >= 0; j--)
196
            {
197
198
                /* Pickup byte of volume name.  */
199
32
                volume_name[j] =  (CHAR)media_ptr -> fx_media_memory_buffer[offset + (UINT)j];
200
            }
201
202
            /* Release media protection.  */
203
8
            FX_UNPROTECT
204
205
            /* Return the completion status.  */
206
8
            return(status);
207
        }
208
    }
209
210
    /* Read volume name from boot record.  */
211
    /* Read the logical directory sector 0 - we just do this to get a memory_buffer pointer */
212
12
    status =  _fx_utility_logical_sector_read(media_ptr, ((ULONG64) 0),
213
12
                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
214
215
    /* Check the return status.  */
216
12
    if (status != FX_SUCCESS)
217
    {
218
219
        /* Release media protection.  */
220
1
        FX_UNPROTECT
221
222
        /* Return the error status.  */
223
1
        return(status);
224
    }
225
226
#ifndef FX_MEDIA_STATISTICS_DISABLE
227
228
    /* Increment the number of driver read boot sector requests.  */
229
11
    media_ptr -> fx_media_driver_boot_read_requests++;
230
#endif
231
232
    /* Build the driver request to read the boot record.  */
233
11
    media_ptr -> fx_media_driver_request =      FX_DRIVER_BOOT_READ;
234
11
    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
235
11
    media_ptr -> fx_media_driver_buffer =       media_ptr -> fx_media_memory_buffer;
236
11
    media_ptr -> fx_media_driver_sectors =      1;
237
11
    media_ptr -> fx_media_driver_sector_type =  FX_BOOT_SECTOR;
238
239
    /* If trace is enabled, insert this event into the trace buffer.  */
240
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_READ, media_ptr, media_ptr -> fx_media_memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
241
242
    /* Invoke the driver to read the boot sector.  */
243
11
    (media_ptr -> fx_media_driver_entry) (media_ptr);
244
245
    /* Determine if the request is successful.  */
246
11
    if (media_ptr -> fx_media_driver_status)
247
    {
248
249
        /* Release media protection.  */
250
1
        FX_UNPROTECT
251
252
        /* An error occurred in the driver.  */
253
1
        return(media_ptr -> fx_media_driver_status);
254
    }
255
256
    /* Calculate the offset to the volume name based on the type of FAT.  */
257
10
    if (media_ptr -> fx_media_32_bit_FAT)
258
    {
259
260
        /* FAT32 offset to volume name.  */
261
4
        offset =  FX_VOLUME_LABEL_32;
262
    }
263
    else
264
    {
265
266
        /* FAT12/16 offset to volume name.  */
267
6
        offset =  FX_VOLUME_LABEL;
268
    }
269
270
    /* Skip trailing space characters of volume name. */
271
52
    for (j = 10; j >= 0; j--)
272
    {
273
274
        /* Check for space character.  */
275
51
        if (media_ptr -> fx_media_memory_buffer[offset + (UINT)j] != (UCHAR)' ')
276
        {
277
278
            /* Last character found. */
279
9
            break;
280
        }
281
    }
282
283
    /* Check if the buffer is too short for the name.  */
284
10
    if (j >= (INT)volume_name_buffer_length - 1)
285
    {
286
287
        /* Buffer too short, return error.  */
288
1
        status =  FX_BUFFER_ERROR;
289
290
        /* Set character count to fit for the buffer.  */
291
1
        j = (INT)volume_name_buffer_length - 2;
292
    }
293
294
    /* NULL terminate the volume name.  */
295
10
    volume_name[j + 1] =  FX_NULL;
296
297
    /* Pickup the remaining characters of the volume name from the boot sector.  */
298
68
    for (; j >= 0; j--)
299
    {
300
301
        /* Pickup byte of volume name.  */
302
58
        volume_name[j] =  (CHAR)media_ptr -> fx_media_memory_buffer[offset + (UINT)j];
303
    }
304
305
    /* Release media protection.  */
306
10
    FX_UNPROTECT
307
308
    /* Return the completion status.  */
309
10
    return(status);
310
}
311