source: rtems/cpukit/libfs/src/dosfs/msdos_conv.c @ 93fabe27

4.104.114.84.95
Last change on this file since 93fabe27 was 93fabe27, checked in by Ralf Corsepius <ralf.corsepius@…>, on Oct 21, 2003 at 5:32:10 AM

2003-10-21 Ralf Corsepius <corsepiu@…>

  • src/dosfs/msdos_conv.c: Remove isupper, islower, toupper, tolower (Unused).
  • Property mode set to 100644
File size: 7.7 KB
Line 
1/*
2 * Adaptation of NetBSD code for RTEMS by Victor V. Vengerov <vvv@oktet.ru>
3 */
4/*      $NetBSD: msdosfs_conv.c,v 1.10 1994/12/27 18:36:24 mycroft Exp $        */
5/*
6 * Written by Paul Popelka (paulp@uts.amdahl.com)
7 *
8 * You can do anything you want with this software, just don't say you wrote
9 * it, and don't remove this notice.
10 *
11 * This software is provided "as is".
12 *
13 * The author supplies this software to be publicly redistributed on the
14 * understanding that the author is not responsible for the correct
15 * functioning of this software in any circumstances and is not liable for
16 * any damages caused by this software.
17 *
18 * October 1992
19 */
20
21#if HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include <rtems.h>
26#include "msdos.h"
27/*
28 * Days in each month in a regular year.
29 */
30static u_short regyear[] = {
31        31, 28, 31, 30, 31, 30,
32        31, 31, 30, 31, 30, 31
33};
34
35/*
36 * Days in each month in a leap year.
37 */
38static u_short leapyear[] = {
39        31, 29, 31, 30, 31, 30,
40        31, 31, 30, 31, 30, 31
41};
42
43/*
44 * Variables used to remember parts of the last time conversion.  Maybe we
45 * can avoid a full conversion.
46 */
47static u_long lasttime;
48static u_long lastday;
49static u_short lastddate;
50static u_short lastdtime;
51
52/*
53 * Convert the unix version of time to dos's idea of time to be used in
54 * file timestamps. The passed in unix time is assumed to be in GMT.
55 */
56void
57msdos_date_unix2dos(unsigned int t, unsigned short *ddp, 
58                    unsigned short *dtp)
59{
60        u_long days;
61        u_long inc;
62        u_long year;
63        u_long month;
64        u_short *months;
65
66        /*
67         * If the time from the last conversion is the same as now, then
68         * skip the computations and use the saved result.
69         */
70        if (lasttime != t) {
71                lasttime = t;
72                lastdtime = (((t % 60) >> 1) << MSDOS_DT_2SECONDS_SHIFT)
73                    + (((t / 60) % 60) << MSDOS_DT_MINUTES_SHIFT)
74                    + (((t / 3600) % 24) << MSDOS_DT_HOURS_SHIFT);
75
76                /*
77                 * If the number of days since 1970 is the same as the last
78                 * time we did the computation then skip all this leap year
79                 * and month stuff.
80                 */
81                days = t / (24 * 60 * 60);
82                if (days != lastday) {
83                        lastday = days;
84                        for (year = 1970;; year++) {
85                                inc = year & 0x03 ? 365 : 366;
86                                if (days < inc)
87                                        break;
88                                days -= inc;
89                        }
90                        months = year & 0x03 ? regyear : leapyear;
91                        for (month = 0; month < 12; month++) {
92                                if (days < months[month])
93                                        break;
94                                days -= months[month];
95                        }
96                        lastddate = ((days + 1) << MSDOS_DD_DAY_SHIFT)
97                            + ((month + 1) << MSDOS_DD_MONTH_SHIFT);
98                        /*
99                         * Remember dos's idea of time is relative to 1980.
100                         * unix's is relative to 1970.  If somehow we get a
101                         * time before 1980 then don't give totally crazy
102                         * results.
103                         */
104                        if (year > 1980)
105                                lastddate += (year - 1980) << 
106                                             MSDOS_DD_YEAR_SHIFT;
107                }
108        }
109        *dtp = lastdtime;
110        *ddp = lastddate;
111}
112
113/*
114 * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
115 * interval there were 8 regular years and 2 leap years.
116 */
117#define SECONDSTO1980   (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
118
119static u_short lastdosdate;
120static u_long lastseconds;
121
122/*
123 * Convert from dos' idea of time to unix'. This will probably only be
124 * called from the stat(), and fstat() system calls and so probably need
125 * not be too efficient.
126 */
127unsigned int
128msdos_date_dos2unix(unsigned int dd, unsigned int dt)
129{
130        u_long seconds;
131        u_long m, month;
132        u_long y, year;
133        u_long days;
134        u_short *months;
135
136        seconds = ((dt & MSDOS_DT_2SECONDS_MASK) >> MSDOS_DT_2SECONDS_SHIFT)
137            + ((dt & MSDOS_DT_MINUTES_MASK) >> MSDOS_DT_MINUTES_SHIFT) * 60
138            + ((dt & MSDOS_DT_HOURS_MASK) >> MSDOS_DT_HOURS_SHIFT) * 3600;
139        /*
140         * If the year, month, and day from the last conversion are the
141         * same then use the saved value.
142         */
143        if (lastdosdate != dd) {
144                lastdosdate = dd;
145                days = 0;
146                year = (dd & MSDOS_DD_YEAR_MASK) >> MSDOS_DD_YEAR_SHIFT;
147                for (y = 0; y < year; y++)
148                        days += y & 0x03 ? 365 : 366;
149                months = year & 0x03 ? regyear : leapyear;
150                /*
151                 * Prevent going from 0 to 0xffffffff in the following
152                 * loop.
153                 */
154                month = (dd & MSDOS_DD_MONTH_MASK) >> MSDOS_DD_MONTH_SHIFT;
155                if (month == 0) {
156                        month = 1;
157                }
158                for (m = 0; m < month - 1; m++)
159                        days += months[m];
160                days += ((dd & MSDOS_DD_DAY_MASK) >> MSDOS_DD_DAY_SHIFT) - 1;
161                lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
162        }
163        return seconds + lastseconds;
164}
165
166static const u_char msdos_map[] = {
167/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169/* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171/* 20 */ 0x00, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, /*  !"#$%&' */
172/* 28 */ 0x28, 0x29, 0x00, 0x00, 0x00, 0x2D, 0x2E, 0x00, /* ()*+,-./ */
173/* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */
174/* 38 */ 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 89:;<=>? */
175/* 40 */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */
176/* 48 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* HIJKLMNO */
177/* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* PQRSTUVW */
178/* 58 */ 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* XYZ[\]^_ */
179/* 60 */ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* `abcdefg */
180/* 68 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* hijklmno */
181/* 70 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* pqrstuvw */
182/* 78 */ 0x58, 0x59, 0x5A, 0x5B, 0x7C, 0x00, 0x7E, 0x00, /* xyz{|}~  */
183/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186/* 98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187/* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188/* A8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189/* B0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190/* B8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191/* C0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192/* C8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193/* D0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194/* D8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195/* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196/* E8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197/* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198/* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199};
200/*
201 * Convert a unix filename to a DOS filename. Return -1 if wrong name is
202 * supplied.
203 */
204int
205msdos_filename_unix2dos(char *un, int unlen, char *dn)
206{
207        int i;
208        u_char c;
209
210        /*
211         * Fill the dos filename string with blanks. These are DOS's pad
212         * characters.
213         */
214        for (i = 0; i <= 10; i++)
215                dn[i] = ' ';
216
217        /*
218         * The filenames "." and ".." are handled specially, since they
219         * don't follow dos filename rules.
220         */
221        if (un[0] == '.' && unlen == 1) {
222                dn[0] = '.';
223                return 0;
224        }
225        if (un[0] == '.' && un[1] == '.' && unlen == 2) {
226                dn[0] = '.';
227                dn[1] = '.';
228                return 0;
229        }
230
231        /*
232         * Copy the unix filename into the dos filename string upto the end
233         * of string, a '.', or 8 characters. Whichever happens first stops
234         * us. This forms the name portion of the dos filename. Fold to
235         * upper case.
236         */
237        for (i = 0; i <= 7 && unlen && (c = *un) && c != '.'; i++) {
238                if ((dn[i] = msdos_map[c]) == 0)
239                        return -1;
240                un++;
241                unlen--;
242        }
243
244        /*
245         * Strip any further characters up to a '.' or the end of the
246         * string.
247         */
248        while (unlen && (c = *un)) {
249                un++;
250                unlen--;
251                /* Make sure we've skipped over the dot before stopping. */
252                if (c == '.')
253                        break;
254        }
255
256        /*
257         * Copy in the extension part of the name, if any. Force to upper
258         * case. Note that the extension is allowed to contain '.'s.
259         * Filenames in this form are probably inaccessable under dos.
260         */
261        for (i = 8; i <= 10 && unlen && (c = *un); i++) {
262                if ((dn[i] = msdos_map[c]) == 0)
263                        return -1;
264                un++;
265                unlen--;
266        }
267        return 0;
268}
Note: See TracBrowser for help on using the repository browser.