GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_media_volume_set.c Lines: 103 103 100.0 %
Date: 2024-03-11 05:15:45 Branches: 54 54 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_set                                PORTABLE C      */
39
/*                                                           6.1          */
40
/*  AUTHOR                                                                */
41
/*                                                                        */
42
/*    William E. Lamie, Microsoft Corporation                             */
43
/*                                                                        */
44
/*  DESCRIPTION                                                           */
45
/*                                                                        */
46
/*    This function sets the volume name to the name supplied by the      */
47
/*    caller.                                                             */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    media_ptr                             Media control block pointer   */
52
/*    volume_name                           New volume name               */
53
/*                                                                        */
54
/*  OUTPUT                                                                */
55
/*                                                                        */
56
/*    return status                                                       */
57
/*                                                                        */
58
/*  CALLS                                                                 */
59
/*                                                                        */
60
/*    _fx_directory_entry_read              Read a directory entry        */
61
/*    _fx_utility_logical_sector_read       Read directory sector         */
62
/*    _fx_utility_logical_sector_write      Write directory sector        */
63
/*                                                                        */
64
/*  CALLED BY                                                             */
65
/*                                                                        */
66
/*    Application Code                                                    */
67
/*                                                                        */
68
/*  RELEASE HISTORY                                                       */
69
/*                                                                        */
70
/*    DATE              NAME                      DESCRIPTION             */
71
/*                                                                        */
72
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
73
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
74
/*                                            resulting in version 6.1    */
75
/*                                                                        */
76
/**************************************************************************/
77
1028
UINT  _fx_media_volume_set(FX_MEDIA *media_ptr, CHAR *volume_name)
78
{
79
80
ULONG        i, j;
81
FX_DIR_ENTRY dir_entry, dir_entry1;
82
UINT         status, offset;
83
UCHAR       *work_ptr;
84
CHAR         alpha;
85
86
87
    /* Check the media to make sure it is open.  */
88
1028
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
89
    {
90
91
        /* Return the media not opened error.  */
92
1001
        return(FX_MEDIA_NOT_OPEN);
93
    }
94
95
27
    dir_entry.fx_dir_entry_log_sector = 0;
96
27
    dir_entry.fx_dir_entry_byte_offset = 0;
97
98
    /* If trace is enabled, insert this event into the trace buffer.  */
99
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_MEDIA_VOLUME_SET, media_ptr, volume_name, 0, 0, FX_TRACE_MEDIA_EVENTS, 0, 0)
100
101
    /* Protect against other threads accessing the media.  */
102
27
    FX_PROTECT
103
104
105
   /* First, check for an invalid volume name.  */
106
27
        if (volume_name[0] == 0)
107
        {
108
109
        /* Yes, volume name is invalid.  Return an error.  */
110
1
        return(FX_INVALID_NAME);
111
    }
112
113
    /* Read the logical directory sector 0 - we just do this to get a memory_buffer pointer */
114
26
    status =  _fx_utility_logical_sector_read(media_ptr, ((ULONG64) 0),
115
26
                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
116
117
    /* Check the read status.  */
118
26
    if (status != FX_SUCCESS)
119
    {
120
121
        /* Release media protection.  */
122
1
        FX_UNPROTECT
123
124
        /* Return the error status.  */
125
1
        return(status);
126
    }
127
128
#ifndef FX_MEDIA_STATISTICS_DISABLE
129
130
    /* Increment the number of driver read boot sector requests.  */
131
25
    media_ptr -> fx_media_driver_boot_read_requests++;
132
#endif
133
134
    /* Build a driver request to read the boot record.  */
135
25
    media_ptr -> fx_media_driver_request =      FX_DRIVER_BOOT_READ;
136
25
    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
137
25
    media_ptr -> fx_media_driver_buffer =       media_ptr -> fx_media_memory_buffer;
138
25
    media_ptr -> fx_media_driver_sectors =      1;
139
25
    media_ptr -> fx_media_driver_sector_type =  FX_BOOT_SECTOR;
140
141
    /* If trace is enabled, insert this event into the trace buffer.  */
142
    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)
143
144
    /* Invoke the driver to read the boot sector.  */
145
25
        (media_ptr -> fx_media_driver_entry) (media_ptr);
146
147
    /* Determine if the request is successful.  */
148
25
    if (media_ptr -> fx_media_driver_status)
149
    {
150
151
        /* Release media protection.  */
152
1
        FX_UNPROTECT
153
154
        /* An error occurred in the driver.  */
155
1
        return(media_ptr -> fx_media_driver_status);
156
    }
157
158
    /* Calculate the offset based on the FAT present.  */
159
24
    if (media_ptr -> fx_media_32_bit_FAT)
160
    {
161
162
        /* FAT32 is present.  */
163
5
        offset =  FX_VOLUME_LABEL_32;
164
    }
165
    else
166
    {
167
168
        /* FAT12/16 is present.  */
169
19
        offset =  FX_VOLUME_LABEL;
170
    }
171
172
    /* Loop to store the volume name.  */
173
169
    for (i = 0; volume_name[i]; i++)
174
    {
175
176
        /* Have we reached the end?  */
177
147
        if (i == 11)
178
        {
179
180
2
            break;
181
        }
182
183
        /* Pickup volume name byte.  */
184
145
        alpha =  volume_name[i];
185
186
        /* Determine if alpha needs to be converted to upper case.  */
187

145
        if ((alpha >= 'a') && (alpha <= 'z'))
188
        {
189
190
            /* Convert alpha to upper case.  */
191
25
            alpha =  (CHAR)((INT)alpha - 0x20);
192
        }
193
194
        /* Store a byte of the volume name.  */
195
145
        media_ptr -> fx_media_memory_buffer[offset + i] =  (UCHAR)alpha;
196
    }
197
198
    /* Now pad with spaces.  */
199
143
    for (; i < 11; i++)
200
    {
201
202
        /* Append space character to volume name.  */
203
119
        media_ptr -> fx_media_memory_buffer[offset + i] =  0x20;
204
    }
205
206
#ifndef FX_MEDIA_STATISTICS_DISABLE
207
208
    /* Increment the number of driver write boot sector requests.  */
209
24
    media_ptr -> fx_media_driver_boot_write_requests++;
210
#endif
211
212
    /* Write the boot sector with the new volume name.  */
213
24
    media_ptr -> fx_media_driver_request =      FX_DRIVER_BOOT_WRITE;
214
24
    media_ptr -> fx_media_driver_status =       FX_IO_ERROR;
215
24
    media_ptr -> fx_media_driver_buffer =       media_ptr -> fx_media_memory_buffer;
216
24
    media_ptr -> fx_media_driver_sectors =      1;
217
24
    media_ptr -> fx_media_driver_sector_type =  FX_BOOT_SECTOR;
218
219
    /* Set the system write flag since we are writing the boot sector.  */
220
24
    media_ptr -> fx_media_driver_system_write =  FX_TRUE;
221
222
    /* If trace is enabled, insert this event into the trace buffer.  */
223
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_INTERNAL_IO_DRIVER_BOOT_WRITE, media_ptr, media_ptr -> fx_media_memory_buffer, 0, 0, FX_TRACE_INTERNAL_EVENTS, 0, 0)
224
225
    /* Invoke the driver to write the boot sector.  */
226
24
        (media_ptr -> fx_media_driver_entry) (media_ptr);
227
228
    /* Clear the system write flag.  */
229
24
    media_ptr -> fx_media_driver_system_write =  FX_FALSE;
230
231
    /* Determine if the request is successful.  */
232
24
    if (media_ptr -> fx_media_driver_status)
233
    {
234
235
        /* Release media protection.  */
236
1
        FX_UNPROTECT
237
238
        /* An error occurred in the driver.  */
239
1
        return(media_ptr -> fx_media_driver_status);
240
    }
241
242
    /* Setup pointer to media name buffer.  */
243
23
    dir_entry1.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer;
244
245
    /* Clear the short name string.  */
246
23
    dir_entry1.fx_dir_entry_short_name[0] =  0;
247
248
    /* Now we need to find the copy of the volume name in the root directory.  */
249
23
    i =  0;
250
23
    j =  media_ptr -> fx_media_root_directory_entries + 1;
251
    do
252
    {
253
254
        /* Read an entry from the root directory.  */
255
156
        status =  _fx_directory_entry_read(media_ptr, FX_NULL, &i, &dir_entry1);
256
257
        /* Check for error status.  */
258
156
        if (status != FX_SUCCESS)
259
        {
260
261
            /* Release media protection.  */
262
1
            FX_UNPROTECT
263
264
            /* Return to caller.  */
265
1
            return(status);
266
        }
267
268
        /* Determine if this is an empty entry.  */
269

155
        if ((dir_entry1.fx_dir_entry_name[0] == (CHAR)FX_DIR_ENTRY_FREE) && (dir_entry1.fx_dir_entry_short_name[0] == 0))
270
        {
271
272
            /* Yes, this is free entry.  Is it the first?  */
273
6
            if (i < j)
274
            {
275
276
                /* Yes, first free entry - remember it.  */
277
5
                dir_entry =  dir_entry1;
278
5
                j =  i;
279
            }
280
        }
281
        /* Determine if the directory entries are exhausted.  */
282
149
        else if (dir_entry1.fx_dir_entry_name[0] == FX_DIR_ENTRY_DONE)
283
        {
284
285
            /* Yes, this we are at the end of the directory.  Have there
286
            been any other free entries?  */
287
10
            if (i < j)
288
            {
289
290
                /* No, we need to remember this as the free entry.  */
291
8
                dir_entry =  dir_entry1;
292
8
                j =  i;
293
            }
294
10
            break;
295
        }
296
        /* Check for a volume name.  */
297
139
        else if (dir_entry1.fx_dir_entry_attributes & FX_VOLUME)
298
        {
299
300
            /* Yes, we have found a previously set volume name - use this entry.  */
301
9
            dir_entry =  dir_entry1;
302
9
            j =  i;
303
9
            break;
304
        }
305
306
        /* Move to next directory entry.  */
307
136
        i++;
308
136
    } while (i < media_ptr -> fx_media_root_directory_entries);
309
310
    /* Determine if a volume entry was not found and there are no more empty slots.  */
311
22
    if (i == media_ptr -> fx_media_root_directory_entries)
312
    {
313
314
        /* Determine if there was a free or previous volume name.  */
315
3
        if (j == (media_ptr -> fx_media_root_directory_entries + 1))
316
        {
317
318
            /* No, nothing was available in the root directory.  */
319
320
            /* Release media protection.  */
321
1
            FX_UNPROTECT
322
323
            /* No, existing volume name or space in the root directly was found, return an error.  */
324
1
            return(FX_MEDIA_INVALID);
325
        }
326
    }
327
328
    /* Now set the volume name and attribute.  */
329
330
    /* Read the logical directory sector.  */
331
21
    status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
332
21
                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_BOOT_SECTOR);
333
334
    /* Check the status of reading the directory entry. */
335
21
    if (status != FX_SUCCESS)
336
    {
337
338
        /* Release media protection.  */
339
1
        FX_UNPROTECT
340
341
        /* Return the error status.  */
342
1
        return(status);
343
    }
344
345
    /* Calculate pointer into directory buffer.  */
346
20
    work_ptr =  media_ptr -> fx_media_memory_buffer +
347
20
        (UINT)dir_entry.fx_dir_entry_byte_offset;
348
349
    /* Copy the volume name into the directory entry.  */
350
151
    for (i = 0; volume_name[i]; i++)
351
    {
352
353
        /* Have we reached the end?  */
354
133
        if (i == 11)
355
        {
356
357
2
            break;
358
        }
359
360
        /* Pickup volume name byte.  */
361
131
        alpha =  volume_name[i];
362
363
        /* Determine if alpha needs to be converted to upper case.  */
364

131
        if ((alpha >= 'a') && (alpha <= 'z'))
365
        {
366
367
            /* Convert alpha to upper case.  */
368
25
            alpha =  (CHAR)((INT)alpha - 0x20);
369
        }
370
371
        /* Store volume name.  */
372
131
        work_ptr[i] =  (UCHAR)alpha;
373
    }
374
375
    /* Pad with space characters.  */
376
109
    for (; i < 11; i++)
377
    {
378
89
        work_ptr[i] =  0x20;
379
    }
380
381
    /* Set the appropriate attributes.  */
382
20
    work_ptr[11] =  FX_VOLUME | FX_ARCHIVE;
383
384
    /* Set the other parts of the volume entry.  */
385
386
    /* Clear the hi word of cluster.  */
387
20
    work_ptr[20] =  0;
388
20
    work_ptr[21] =  0;
389
390
    /* Clear the low word of cluster.  */
391
20
    work_ptr[26] =  0;
392
20
    work_ptr[27] =  0;
393
394
    /* Clear the file size.  */
395
20
    work_ptr[28] =  0;
396
20
    work_ptr[29] =  0;
397
20
    work_ptr[30] =  0;
398
20
    work_ptr[31] =  0;
399
400
    /* Write the directory sector to the media.  */
401
20
    status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) dir_entry.fx_dir_entry_log_sector,
402
20
                                               media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
403
404
    /* Release media protection.  */
405
20
    FX_UNPROTECT
406
407
    /* Return the status.  */
408
20
    return(status);
409
}
410