d7c443cee858fc700c9803ceb413dccab6867fdd
[framework/system/system-server.git] / ss_usb_storage_handler.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.tizenopensource.org/license
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15 */
16
17
18 #include <stdio.h>
19 #include <glib.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/mount.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <vconf.h>
28 #include <mntent.h>
29 #include <limits.h>
30 #include "ss_device_handler.h"
31 #include "ss_log.h"
32
33 #define BUF_MAX                 512     
34
35 #define FS_TYPE_CHECKER         "/sbin/fs-type-checker"
36 #define TEMP_FILE               "/tmp/mountd.tmp"
37 #define MTAB_FILE               "/etc/mtab"
38 #define MOUNT_POINT             "/opt/storage/usb"
39
40 static int added_noti_value = 0; 
41 static int removed_noti_value = 0; 
42
43 static int __ss_mount_device(char *dev)
44 {
45         if (access(dev, F_OK) != 0) {
46                 PRT_TRACE_ERR("Failed to find device: DEVICE(%s)", dev);
47                 return -1;
48         }
49
50         int fd = -1;
51         int r = -1;
52         char *rel_mnt_point;
53         char buf_mnt_point[BUF_MAX];
54
55         rel_mnt_point = strrchr(dev, '/');
56         if (rel_mnt_point == NULL) {
57                 PRT_TRACE_ERR("Get Relative Mount Path Failed");
58                 return -1;
59         }
60
61         snprintf(buf_mnt_point, BUF_MAX, "%s%s", MOUNT_POINT, rel_mnt_point);
62
63         /* Make directory to mount */
64         r = mkdir(buf_mnt_point, 0755);
65         if (r < 0) {
66                 if (errno == EEXIST) {
67                         PRT_TRACE("Directory is already exsited: PATH(%s)", buf_mnt_point);
68                 } else {
69                         PRT_TRACE_ERR("Make Directory Failed: PATH(%s)", buf_mnt_point);
70                         return -1;
71                 }
72         }
73
74         /* Mount block device on mount point */
75         r = mount(dev, buf_mnt_point, "vfat", 0, "uid=0,gid=0,dmask=0000,fmask=0111,iocharset=iso8859-1,utf8,shortname=mixed");
76         if (r < 0) {
77                 r = rmdir(buf_mnt_point);
78                 PRT_TRACE_ERR("Mount failed: MOUNT PATH(%s", buf_mnt_point);
79                 return -1;
80         }
81         PRT_TRACE("Mount Complete: MOUNT PATH(%s)", buf_mnt_point);
82
83         return 0;
84 }
85
86 static int __ss_unmount_device(char *mnt_point)
87 {
88         if (access(mnt_point, F_OK) != 0) {
89                 PRT_TRACE_ERR("Failed to find path: MOUNT PATH(%s)", mnt_point);
90                 return -1;
91         }
92
93         int r = -1;
94
95         /* Umount block device */
96         r = umount2(mnt_point, MNT_DETACH);
97         if (r < 0) {
98                 PRT_TRACE_ERR("Unmounting is unabled: MOUNT PATH(%s)", mnt_point);
99                 r = rmdir(mnt_point);
100                 if (r < 0) {
101                         PRT_TRACE_ERR("Removing Directory is unabled: PATH(%s)", mnt_point);
102                 }
103                 return -1;
104         }
105
106         /* Clean up unmounted directory */
107         r = rmdir(mnt_point);
108         if (r < 0) {
109                 PRT_TRACE_ERR("Removing Directory is unabled: PATH(%s)", mnt_point);
110         }
111         PRT_TRACE("Unmount/Remove Complete: MOUNT PATH(%s)", mnt_point);
112         
113         return 0;
114 }
115
116 static int __ss_usb_storage_added(int argc, char *argv[])
117 {
118         if (argc != 1 || argv[0] == NULL) {
119                 PRT_TRACE_ERR("Get Vconf Value Failed: KEY(%s)", VCONFKEY_SYSMAN_ADDED_USB_STORAGE);
120                 return -1;
121         }
122
123         int fd = -1;
124         int part_num = 0;
125
126         char *buf_dev = argv[0];
127         char buf_part_dev[BUF_MAX];
128         char *disk_path;
129         char *mounted_check;
130
131         /* Check whether mount point directory is exist */
132         if (access(MOUNT_POINT, F_OK) < 0) {
133                 if (mkdir(MOUNT_POINT, 0755) < 0) {
134                         PRT_TRACE_ERR("Make Mount Directory Failed: DIRECTORY(%s)", MOUNT_POINT);
135                         return -1;
136                 }
137         }
138
139         /* Mount tmpfs for protecting user data */
140         if (mount("tmpfs", MOUNT_POINT, "tmpfs", 0, "") < 0) {
141                 if (errno != EBUSY) {
142                         PRT_TRACE_ERR("Failed to mount USB Storage Mount Directory: DIRECTORY(%s)", MOUNT_POINT);
143                         return -1;
144                 }
145         }
146
147         /* Change permission to avoid to write user data on tmpfs */
148         if (chmod(MOUNT_POINT, 0755) < 0) {
149                 PRT_TRACE_ERR("Failed to change mode: DIRCTORY(%s)", MOUNT_POINT);
150                 return -1;
151         }
152
153         /* Mount a single partition storage device */
154         if (__ss_mount_device(buf_dev) < 0) {
155                 /* Mount a multi partition storage device */
156                 for (part_num = 1; part_num < 10; part_num++) {
157                         snprintf(buf_part_dev, BUF_MAX, "%s%d", buf_dev, part_num);
158                         if (__ss_mount_device(buf_part_dev) < 0) {
159                                 PRT_TRACE("Mounting partition is unabled: PARTITION(%s)", buf_part_dev);
160                                 continue;       
161                         }
162                 }
163         }
164
165         FILE *file = setmntent(MTAB_FILE, "r");
166         struct mntent *mnt_entry;
167
168         /* Check whether block deivce is mounted */
169         while (mnt_entry = getmntent(file)) {
170                 mounted_check = strstr(mnt_entry->mnt_fsname, buf_dev);
171                 if (mounted_check != NULL) {
172                         if (added_noti_value < INT_MAX) {
173                                 ++added_noti_value;
174                         } else {
175                                 added_noti_value = 1;
176                         }
177                         /* Broadcast mounting notification */
178                         if (vconf_set_int(VCONFKEY_SYSMAN_ADDED_USB_STORAGE, added_noti_value) < 0) {
179                                 PRT_TRACE_ERR("Setting vconf value is failed: KEY(%s)", VCONFKEY_SYSMAN_ADDED_USB_STORAGE);
180                                 vconf_set_int(VCONFKEY_SYSMAN_ADDED_USB_STORAGE, -1);
181                         }
182
183                         PRT_TRACE("Setting vconf value: KEY(%s) DEVICE(%s)", VCONFKEY_SYSMAN_ADDED_USB_STORAGE, buf_dev);
184                         fclose(file);
185                         return 0;
186                 }
187         }
188
189         /* Failed to mount storage device */
190         PRT_TRACE_ERR("Nothing to be mounted: DEVICE(%s)", buf_dev);
191         fclose(file);
192         return -1;
193 }
194
195 static int __ss_usb_storage_removed(int argc, char *argv[])
196 {
197         if (argc != 1 || argv[0] == NULL) {
198                 PRT_TRACE_ERR("Get Vonf Value Failed: KEY(%s)", VCONFKEY_SYSMAN_REMOVED_USB_STORAGE);
199                 return -1;
200         }
201
202         int fd = -1;
203         int part_num = 0;
204
205         char *buf_dev_name = argv[0];
206         char buf_mnt_point[BUF_MAX];
207         char *mounted_check;
208
209         snprintf(buf_mnt_point, BUF_MAX, "%s/%s", MOUNT_POINT, buf_dev_name);
210
211         if (__ss_unmount_device(buf_mnt_point) == 0) {
212                 umount2(MOUNT_POINT, MNT_DETACH);
213
214                 if (removed_noti_value < INT_MAX) {
215                         ++removed_noti_value;
216                 } else {
217                         removed_noti_value = 1;
218                 }
219                 if (vconf_set_int(VCONFKEY_SYSMAN_REMOVED_USB_STORAGE, removed_noti_value) < 0) {
220                         PRT_TRACE_ERR("Setting vconf value is failed: KEY(%s)", VCONFKEY_SYSMAN_REMOVED_USB_STORAGE);
221                         vconf_set_int(VCONFKEY_SYSMAN_ADDED_USB_STORAGE, -1);
222                 }
223
224                 PRT_TRACE("Setting vconf value: KEY(%s) DEVICE(%s)", VCONFKEY_SYSMAN_REMOVED_USB_STORAGE, buf_dev_name);
225                 return 0;
226         }
227
228         FILE *file = setmntent(MTAB_FILE, "r");
229         struct mntent *mnt_entry;
230
231         while (mnt_entry = getmntent(file)) {
232                 mounted_check = strstr(mnt_entry->mnt_dir, buf_mnt_point);
233                 if (mounted_check != NULL) {
234                         if (__ss_unmount_device(mnt_entry->mnt_dir) < 0) {
235                                 PRT_TRACE_ERR("Unmount Failed: MOUNT PATH(%s)", mnt_entry->mnt_dir);
236                         }
237                         PRT_TRACE("Unmount Success: MOUNT PATH(%s)", mnt_entry->mnt_dir);
238                 }
239         }
240         fclose(file);
241
242         umount2(MOUNT_POINT, MNT_DETACH);
243
244         if (removed_noti_value < INT_MAX) {
245                 ++removed_noti_value;
246         } else {
247                 removed_noti_value = 1;
248         }
249         if (vconf_set_int(VCONFKEY_SYSMAN_REMOVED_USB_STORAGE, removed_noti_value) < 0) {
250                 PRT_TRACE_ERR("Setting vconf value is failed: KEY(%s)", VCONFKEY_SYSMAN_REMOVED_USB_STORAGE);
251                 vconf_set_int(VCONFKEY_SYSMAN_ADDED_USB_STORAGE, -1);
252         }
253
254         PRT_TRACE("Setting vconf value: KEY(%s) DEVICE(%s)", VCONFKEY_SYSMAN_REMOVED_USB_STORAGE, buf_dev_name);
255         return 0;
256 }
257
258 int _ss_usb_storage_init()
259 {
260         ss_action_entry_add_internal(PREDEF_USB_STORAGE_ADD, __ss_usb_storage_added, NULL, NULL);
261         ss_action_entry_add_internal(PREDEF_USB_STORAGE_REMOVE, __ss_usb_storage_removed, NULL, NULL);
262
263         return 0;
264 }
265