GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_unicode_directory_entry_change.c Lines: 74 74 100.0 %
Date: 2024-03-11 05:15:45 Branches: 40 40 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
/**   Unicode                                                             */
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_unicode.h"
29
#include "fx_utility.h"
30
#ifdef FX_ENABLE_FAULT_TOLERANT
31
#include "fx_fault_tolerant.h"
32
#endif /* FX_ENABLE_FAULT_TOLERANT */
33
34
35
/**************************************************************************/
36
/*                                                                        */
37
/*  FUNCTION                                               RELEASE        */
38
/*                                                                        */
39
/*    _fx_unicode_directory_entry_change                  PORTABLE C      */
40
/*                                                           6.1          */
41
/*  AUTHOR                                                                */
42
/*                                                                        */
43
/*    William E. Lamie, Microsoft Corporation                             */
44
/*                                                                        */
45
/*  DESCRIPTION                                                           */
46
/*                                                                        */
47
/*    This function changes the unicode name of a directory entry.        */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    media_ptr                             Pointer to media              */
52
/*    entry_ptr                             Directory entry               */
53
/*    unicode_name                          Destination unicode name      */
54
/*    unicode_name_length                   Unicode name size             */
55
/*                                                                        */
56
/*  OUTPUT                                                                */
57
/*                                                                        */
58
/*    Completion Status                                                   */
59
/*                                                                        */
60
/*  CALLS                                                                 */
61
/*                                                                        */
62
/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
63
/*    _fx_utility_logical_sector_read       Read a logical sector         */
64
/*    _fx_utility_logical_sector_write      Write a logical sector        */
65
/*    _fx_fault_tolerant_add_dir_log        Add directory redo log        */
66
/*                                                                        */
67
/*  CALLED BY                                                             */
68
/*                                                                        */
69
/*    Unicode Utilities                                                   */
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
/*                                                                        */
79
/**************************************************************************/
80
371
UINT  _fx_unicode_directory_entry_change(FX_MEDIA *media_ptr, FX_DIR_ENTRY *entry_ptr, UCHAR *unicode_name, ULONG unicode_name_length)
81
{
82
83
UCHAR *work_ptr, *sector_base_ptr;
84
UINT   status;
85
UINT   i, j, k, u, card, lfn_entries;
86
UCHAR  eof_marker;
87
ULONG  logical_sector, relative_sector;
88
ULONG  byte_offset;
89
ULONG  cluster, next_cluster;
90
91
#ifdef FX_ENABLE_FAULT_TOLERANT
92
UCHAR *changed_ptr;
93
UINT   changed_size;
94
ULONG  changed_offset;
95
#endif /* FX_ENABLE_FAULT_TOLERANT */
96
97
98
#ifndef FX_MEDIA_STATISTICS_DISABLE
99
100
    /* Increment the number of directory entry write requests.  */
101
371
    media_ptr -> fx_media_directory_entry_writes++;
102
#endif
103
104
    /* Pickup the byte offset of the entry.  */
105
371
    byte_offset = entry_ptr -> fx_dir_entry_byte_offset;
106
107
    /* Pickup the logical sector of the entry.  */
108
371
    logical_sector = (ULONG)entry_ptr -> fx_dir_entry_log_sector;
109
110
    /* Figure out where what cluster we are in.  */
111
371
    if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
112
    {
113
114
        /* Calculate the cluster that this logical sector is in.  */
115
260
        cluster =  (logical_sector - media_ptr -> fx_media_data_sector_start) / (media_ptr -> fx_media_sectors_per_cluster) + FX_FAT_ENTRY_START;
116
117
        /* Calculate the relative cluster.  */
118
260
        relative_sector =  logical_sector -  (((ULONG)media_ptr -> fx_media_data_sector_start) +
119
260
                                              (((ULONG)cluster - FX_FAT_ENTRY_START) *
120
260
                                               ((ULONG)media_ptr -> fx_media_sectors_per_cluster)));
121
    }
122
    else
123
    {
124
125
        /* Clear the cluster and the relative sector.  */
126
111
        cluster =  0;
127
111
        relative_sector =  0;
128
    }
129
130
    /* Read the logical directory sector.  */
131
371
    status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) entry_ptr -> fx_dir_entry_log_sector,
132
371
                                              media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
133
134
    /* Determine if an error occurred.  */
135
371
    if (status != FX_SUCCESS)
136
    {
137
138
        /* Return the error status.  */
139
4
        return(status);
140
    }
141
142
    /* Setup a pointer into the buffer.  */
143
367
    sector_base_ptr = (UCHAR *)media_ptr -> fx_media_memory_buffer;
144
367
    work_ptr =  sector_base_ptr + (UINT)entry_ptr -> fx_dir_entry_byte_offset;
145
146
    /* Initialize the unicode index.  */
147
367
    u =  0;
148
149
#ifdef FX_ENABLE_FAULT_TOLERANT
150
    /* Initialize data for fault tolerant. */
151
    changed_ptr = work_ptr;
152
    changed_size = 0;
153
    changed_offset = entry_ptr -> fx_dir_entry_byte_offset;
154
#endif /* FX_ENABLE_FAULT_TOLERANT */
155
156
    /* Check for a valid long name.  */
157
367
    if ((0x40 & (*work_ptr)))
158
    {
159
160
        /* Get the lower 5 bit containing the cardinality.  */
161
366
        card = (*work_ptr & (UCHAR)0x1f);
162
366
        lfn_entries =  card;
163
164
        /* Loop through the file name.  */
165
847
        for (j = 0; j < lfn_entries; j++)
166
        {
167
168
            /* Clear the eof marker.  */
169
486
            eof_marker =  0;
170
171
            /* Loop through file name fields.  */
172
8262
            for (i = 1, k = (26 * (card - 1)) & 0xFFFFFFFF; i < FX_DIR_ENTRY_SIZE; i += 2)
173
            {
174
175
                /* Process relative to specific fields.  */
176

7776
                if ((i == 11) || (i == 26))
177
                {
178
972
                    continue;
179
                }
180
181
6804
                if (i == 13)
182
                {
183
486
                    i = 12;
184
486
                    continue;
185
                }
186
187
                /* Determine if the EOF marker is present.  */
188
6318
                if (eof_marker)
189
                {
190
191
3368
                    work_ptr[i] = eof_marker;
192
3368
                    work_ptr[i + 1] = eof_marker;
193
                }
194
2950
                else if (k < (unicode_name_length * 2))
195
                {
196
197
2458
                    work_ptr[i] = unicode_name[k];
198
2458
                    work_ptr[i + 1] = unicode_name[k + 1];
199
2458
                    u =  u + 2;
200
                }
201
492
                else if (k == (unicode_name_length * 2))
202
                {
203
204
362
                    work_ptr[i] = 0;
205
362
                    work_ptr[i + 1] =  0;
206
207
                    /* end of name, pad with 0xff.  */
208
362
                    eof_marker =  (UCHAR)0xff;
209
                }
210
211
6318
                k =  k + 2;
212
            }
213
214
            /* Decrement the card.  */
215
486
            card--;
216
217
            /* Setup pointers for the name write.  */
218
486
            work_ptr += FX_DIR_ENTRY_SIZE;
219
486
            byte_offset += FX_DIR_ENTRY_SIZE;
220
221
#ifdef FX_ENABLE_FAULT_TOLERANT
222
            /* Update changed_size. */
223
            changed_size += FX_DIR_ENTRY_SIZE;
224
#endif /* FX_ENABLE_FAULT_TOLERANT */
225
226
            /* Determine if the write is within the current sector.   */
227
486
            if (byte_offset >= media_ptr -> fx_media_bytes_per_sector)
228
            {
229
#ifdef FX_ENABLE_FAULT_TOLERANT
230
                if (media_ptr -> fx_media_fault_tolerant_enabled)
231
                {
232
233
                    /* Redirect this request to log file. */
234
                    status = _fx_fault_tolerant_add_dir_log(media_ptr, (ULONG64) logical_sector, changed_offset, changed_ptr, changed_size);
235
                }
236
                else
237
                {
238
239
                    /* Write the current sector out.  */
240
                    status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
241
                                                               sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
242
                }
243
244
245
                /* Determine if an error occurred.  */
246
                if (status != FX_SUCCESS)
247
                {
248
249
                    /* Return the error status.  */
250
                    return(status);
251
                }
252
#else /* FX_ENABLE_FAULT_TOLERANT */
253
254
                /* Write the current sector out.  */
255
                /* Note: Since the sector is in the cache after a sector read, therefore _fx_utility_logical_sector_write
256
                   always returns success when FX_ENABLE_FAULT_TOLERANT is not defined.  In other words, the checking
257
                   on the return value is needed only when FX_ENABLE_FAULT_TOLERANT is defined. */
258
85
                _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
259
                                                 sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
260
#endif /* FX_ENABLE_FAULT_TOLERANT */
261
262
                /* Determine if we are in the root directory.  */
263
85
                if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
264
                {
265
266
                    /* Determine the next sector of the directory entry.  */
267
69
                    if (relative_sector < (media_ptr -> fx_media_sectors_per_cluster - 1))
268
                    {
269
270
                        /* More sectors in this cluster.  */
271
272
                        /* Simply increment the logical sector.  */
273
15
                        logical_sector++;
274
275
                        /* Increment the relative sector.  */
276
15
                        relative_sector++;
277
                    }
278
                    else
279
                    {
280
281
                        /* We need to move to the next cluster.  */
282
283
                        /* Pickup the next cluster.  */
284
54
                        status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
285
286
                        /* Check for I/O error.  */
287
54
                        if (status != FX_SUCCESS)
288
                        {
289
290
                            /* Return error code.  */
291
1
                            return(status);
292
                        }
293
294
                        /* Copy next cluster to the current cluster.  */
295
53
                        cluster =  next_cluster;
296
297
                        /* Check the value of the new cluster - it must be a valid cluster number
298
                           or something is really wrong!  */
299

53
                        if ((cluster < FX_FAT_ENTRY_START) || (cluster > media_ptr -> fx_media_fat_reserved))
300
                        {
301
302
                            /* Send error message back to caller.  */
303
2
                            return(FX_FILE_CORRUPT);
304
                        }
305
306
                        /* Setup the relative sector (this is zero for subsequent cluster.  */
307
51
                        relative_sector =  0;
308
309
                        /* Calculate the next logical sector.  */
310
51
                        logical_sector =   ((ULONG)media_ptr -> fx_media_data_sector_start) +
311
51
                            (((ULONG)cluster - FX_FAT_ENTRY_START) *
312
51
                             ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
313
                    }
314
                }
315
                else
316
                {
317
318
                    /* Increment the logical sector.  */
319
16
                    logical_sector++;
320
321
                    /* Determine if the logical sector is valid.  */
322
16
                    if (logical_sector >= (ULONG)(media_ptr -> fx_media_data_sector_start))
323
                    {
324
325
                        /* We have exceeded the root directory.  */
326
327
                        /* Send error message back to caller.  */
328
1
                        return(FX_FILE_CORRUPT);
329
                    }
330
                }
331
332
                /* Read the next logical sector.  */
333
81
                status =  _fx_utility_logical_sector_read(media_ptr, (ULONG64) logical_sector,
334
81
                                                          media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DIRECTORY_SECTOR);
335
336
                /* Determine if an error occurred.  */
337
81
                if (status != FX_SUCCESS)
338
                {
339
340
                    /* Return the error status.  */
341
1
                    return(status);
342
                }
343
344
                /* Move to the next sector buffer.  */
345
80
                sector_base_ptr = media_ptr -> fx_media_memory_buffer;
346
347
                /* Setup new buffer pointers.  */
348
80
                byte_offset =  0;
349
80
                work_ptr = sector_base_ptr;
350
351
#ifdef FX_ENABLE_FAULT_TOLERANT
352
                /* Initialize data for fault tolerant. */
353
                changed_ptr = work_ptr;
354
                changed_size = 0;
355
                changed_offset = 0;
356
#endif /* FX_ENABLE_FAULT_TOLERANT */
357
            }
358
        }
359
    }
360
361
    /* Check for an error!  */
362
362
    if (u != (unicode_name_length * 2))
363
    {
364
365
        /* Return an error!  */
366
1
        return(FX_FILE_CORRUPT);
367
    }
368
369
#ifdef FX_ENABLE_FAULT_TOLERANT
370
    if (media_ptr -> fx_media_fault_tolerant_enabled)
371
    {
372
373
        /* Redirect this request to log file. */
374
        status = _fx_fault_tolerant_add_dir_log(media_ptr, (ULONG64) logical_sector, changed_offset, changed_ptr, changed_size);
375
    }
376
    else
377
    {
378
#endif /* FX_ENABLE_FAULT_TOLERANT */
379
380
        /* Write the directory sector to the media.  */
381
361
        status =  _fx_utility_logical_sector_write(media_ptr, (ULONG64) logical_sector,
382
                                                   sector_base_ptr, ((ULONG) 1), FX_DIRECTORY_SECTOR);
383
#ifdef FX_ENABLE_FAULT_TOLERANT
384
    }
385
#endif /* FX_ENABLE_FAULT_TOLERANT */
386
387
361
    return(status);
388
}
389