tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / fs / exfat / exfat_oal.c
1 /* Some of the source code in this file came from "linux/fs/fat/misc.c".  */
2 /*
3  *  linux/fs/fat/misc.c
4  *
5  *  Written 1992,1993 by Werner Almesberger
6  *  22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980
7  *         and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru)
8  */
9
10 /*
11  *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
12  *
13  *  This program is free software; you can redistribute it and/or
14  *  modify it under the terms of the GNU General Public License
15  *  as published by the Free Software Foundation; either version 2
16  *  of the License, or (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, write to the Free Software
25  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26  */
27
28 #include <linux/semaphore.h>
29 #include <linux/time.h>
30
31 #include "exfat_config.h"
32 #include "exfat_global.h"
33 #include "exfat_api.h"
34 #include "exfat_oal.h"
35
36 DECLARE_MUTEX(z_sem);
37
38 INT32 sm_init(struct semaphore *sm)
39 {
40         sema_init(sm, 1);
41         return(0);
42 }
43
44 INT32 sm_P(struct semaphore *sm)
45 {
46         down(sm);
47         return 0;
48 }
49
50 void sm_V(struct semaphore *sm)
51 {
52         up(sm);
53 }
54
55 extern struct timezone sys_tz;
56
57 #define UNIX_SECS_1980   315532800L
58
59 #if BITS_PER_LONG == 64
60 #define UNIX_SECS_2108   4354819200L
61 #endif
62
63 #define DAYS_DELTA_DECADE       (365 * 10 + 2)
64 #define NO_LEAP_YEAR_2100    (120)
65 #define IS_LEAP_YEAR(y)  (!((y) & 3) && (y) != NO_LEAP_YEAR_2100)
66
67 #define SECS_PER_MIN     (60)
68 #define SECS_PER_HOUR    (60 * SECS_PER_MIN)
69 #define SECS_PER_DAY     (24 * SECS_PER_HOUR)
70
71 #define MAKE_LEAP_YEAR(leap_year, year)                         \
72         do {                                                    \
73                 if (unlikely(year > NO_LEAP_YEAR_2100))         \
74                         leap_year = ((year + 3) / 4) - 1;       \
75                 else                                            \
76                         leap_year = ((year + 3) / 4);           \
77         } while(0)
78
79
80
81 static time_t accum_days_in_year[] = {
82         0,   0, 31, 59, 90,120,151,181,212,243,273,304,334, 0, 0, 0,
83 };
84
85
86 TIMESTAMP_T *tm_current(TIMESTAMP_T *tp, UINT8 tz_utc)
87 {
88         struct timespec ts = CURRENT_TIME_SEC;
89         time_t second = ts.tv_sec;
90         time_t day, leap_day, month, year;
91
92         if (!tz_utc)
93                 second -= sys_tz.tz_minuteswest * SECS_PER_MIN;
94
95         if (second < UNIX_SECS_1980) {
96                 tp->sec  = 0;
97                 tp->min  = 0;
98                 tp->hour = 0;
99                 tp->day  = 1;
100                 tp->mon  = 1;
101                 tp->year = 0;
102                 return(tp);
103         }
104 #if BITS_PER_LONG == 64
105         if (second >= UNIX_SECS_2108) {
106                 tp->sec  = 59;
107                 tp->min  = 59;
108                 tp->hour = 23;
109                 tp->day  = 31;
110                 tp->mon  = 12;
111                 tp->year = 127;
112                 return(tp);
113         }
114 #endif
115
116         day = second / SECS_PER_DAY - DAYS_DELTA_DECADE;
117         year = day / 365;
118
119         MAKE_LEAP_YEAR(leap_day, year);
120         if (year * 365 + leap_day > day)
121                 year--;
122
123         MAKE_LEAP_YEAR(leap_day, year);
124
125         day -= year * 365 + leap_day;
126
127         if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) {
128                 month = 2;
129         } else {
130                 if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3])
131                         day--;
132                 for (month = 1; month < 12; month++) {
133                         if (accum_days_in_year[month + 1] > day)
134                                 break;
135                 }
136         }
137         day -= accum_days_in_year[month];
138
139         tp->sec  = second % SECS_PER_MIN;
140         tp->min  = (second / SECS_PER_MIN) % 60;
141         tp->hour = (second / SECS_PER_HOUR) % 24;
142         tp->day  = day + 1;
143         tp->mon  = month;
144         tp->year = year;
145
146         return(tp);
147 }