GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_media_volume_get_extended.c Lines: 65 65 100.0 %
Date: 2024-03-11 05:15:45 Branches: 38 38 100.0 %

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

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