change usb control process name to usb-server
[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 <syspopup_caller.h>
31 #include "ss_device_handler.h"
32 #include "ss_log.h"
33
34 #define BUF_MAX                 512     
35
36 #define FS_TYPE_CHECKER         "/sbin/fs-type-checker"
37 #define TEMP_FILE               "/tmp/mountd.tmp"
38 #define MTAB_FILE               "/etc/mtab"
39 #define MOUNT_POINT             "/opt/storage/usb"
40
41 static int added_noti_value = 0; 
42 static int removed_noti_value = 0; 
43 static int tempfs_mounted = 0;
44
45 static int __ss_mount_device(char *dev)
46 {
47         if (access(dev, F_OK) != 0) {
48                 PRT_TRACE_ERR("Failed to find device: DEVICE(%s)", dev);
49                 return -1;
50         }
51
52         int fd = -1;
53         int r = -1;
54         char *rel_mnt_point;
55         char buf_mnt_point[BUF_MAX];
56
57         rel_mnt_point = strrchr(dev, '/');
58         if (rel_mnt_point == NULL) {
59                 PRT_TRACE_ERR("Get Relative Mount Path Failed");
60                 return -1;
61         }
62
63         snprintf(buf_mnt_point, BUF_MAX, "%s%s", MOUNT_POINT, rel_mnt_point);
64
65         /* Make directory to mount */
66         r = mkdir(buf_mnt_point, 0755);
67         if (r < 0) {
68                 if (errno == EEXIST) {
69                         PRT_TRACE("Directory is already exsited: PATH(%s)", buf_mnt_point);
70                 } else {
71                         PRT_TRACE_ERR("Make Directory Failed: PATH(%s)", buf_mnt_point);
72                         return -1;
73                 }
74         }
75
76         /* Mount block device on mount point */
77         r = mount(dev, buf_mnt_point, "vfat", 0, "uid=0,gid=0,dmask=0000,fmask=0111,iocharset=iso8859-1,utf8,shortname=mixed,smackfsroot=*,smackfsdef=*");
78         if (r < 0) {
79                 r = rmdir(buf_mnt_point);
80                 PRT_TRACE_ERR("Mount failed: MOUNT PATH(%s", buf_mnt_point);
81                 return -1;
82         }
83         PRT_TRACE("Mount Complete: MOUNT PATH(%s)", buf_mnt_point);
84
85         return 0;
86 }
87
88 static int __ss_unmount_device(char *mnt_point)
89 {
90         if (access(mnt_point, F_OK) != 0) {
91                 PRT_TRACE_ERR("Failed to find path: MOUNT PATH(%s)", mnt_point);
92                 return -1;
93         }
94
95         int ret = -1;
96
97         /* Umount block device */
98         ret = umount2(mnt_point, MNT_DETACH);
99         if (ret < 0) {
100                 PRT_TRACE_ERR("Unmounting is unabled: MOUNT PATH(%s)", mnt_point);
101                 ret = rmdir(mnt_point);
102                 if (ret < 0) {
103                         PRT_TRACE_ERR("Removing Directory is unabled: PATH(%s)", mnt_point);
104                 }
105                 return -1;
106         }
107
108         bundle *b = NULL;
109         b = bundle_create();
110         bundle_add(b, "_SYSPOPUP_CONTENT_", "otg_remove");
111         ret = syspopup_launch("usbotg-syspopup", b);
112         if (ret < 0) {
113                 PRT_TRACE_EM("popup lauch failed\n");
114         }
115         bundle_free(b);
116
117         /* Clean up unmounted directory */
118         ret = rmdir(mnt_point);
119         if (ret < 0) {
120                 PRT_TRACE_ERR("Removing Directory is unabled: PATH(%s)", mnt_point);
121         }
122         PRT_TRACE("Unmount/Remove Complete: MOUNT PATH(%s)", mnt_point);
123         
124         return 0;
125 }
126
127 static int __ss_usb_storage_added(int argc, char *argv[])
128 {
129         if (argc != 1 || argv[0] == NULL) {
130                 PRT_TRACE_ERR("Get Vconf Value Failed: KEY(%s)", VCONFKEY_SYSMAN_ADDED_USB_STORAGE);
131                 return -1;
132         }
133
134         int ret = -1;
135         int fd = -1;
136         int part_num = 0;
137
138         char *buf_dev = argv[0];
139         char buf_part_dev[BUF_MAX];
140         char *disk_path;
141         char *mounted_check;
142
143         char *rel_mnt_point;
144         char buf_mnt_point[BUF_MAX];
145
146         /* Check whether mount point directory is exist */
147         if (access(MOUNT_POINT, F_OK) < 0) {
148                 if (mkdir(MOUNT_POINT, 0755) < 0) {
149                         PRT_TRACE_ERR("Make Mount Directory Failed: DIRECTORY(%s)", MOUNT_POINT);
150                         return -1;
151                 }
152         }
153
154         /* Mount tmpfs for protecting user data */
155         if (tempfs_mounted != 1) {
156                 if (mount("tmpfs", MOUNT_POINT, "tmpfs", 0, "") < 0) {
157                         if (errno != EBUSY) {
158                                 PRT_TRACE_ERR("Failed to mount USB Storage Mount Directory: DIRECTORY(%s)", MOUNT_POINT);
159                                 return -1;
160                         }
161                 } else {
162                         /* Change permission to avoid to write user data on tmpfs */
163                         if (chmod(MOUNT_POINT, 0755) < 0) {
164                                 PRT_TRACE_ERR("Failed to change mode: DIRCTORY(%s)", MOUNT_POINT);
165                                 umount2(MOUNT_POINT, MNT_DETACH);
166                                 return -1;
167                         }
168                         tempfs_mounted = 1;
169                 }
170         }
171
172         rel_mnt_point = strrchr(buf_dev, '/');
173         if (rel_mnt_point == NULL) {
174                 PRT_TRACE_ERR("Get Relative Mount Path Failed");
175                 return -1;
176         }
177         snprintf(buf_mnt_point, BUF_MAX, "%s%s", MOUNT_POINT, rel_mnt_point);
178
179         if (__ss_mount_device(buf_dev) < 0) {
180                 PRT_TRACE_ERR("Failed to mount %d", buf_dev);
181         }
182
183         FILE *file = setmntent(MTAB_FILE, "r");
184         struct mntent *mnt_entry;
185
186         /* Check whether block deivce is mounted */
187         while (mnt_entry = getmntent(file)) {
188                 mounted_check = strstr(mnt_entry->mnt_fsname, buf_dev);
189                 if (mounted_check != NULL) {
190                         if (added_noti_value < INT_MAX) {
191                                 ++added_noti_value;
192                         } else {
193                                 added_noti_value = 1;
194                         }
195                         /* Broadcast mounting notification */
196                         if (vconf_set_int(VCONFKEY_SYSMAN_ADDED_USB_STORAGE, added_noti_value) < 0) {
197                                 PRT_TRACE_ERR("Setting vconf value is failed: KEY(%s)", VCONFKEY_SYSMAN_ADDED_USB_STORAGE);
198                                 vconf_set_int(VCONFKEY_SYSMAN_ADDED_USB_STORAGE, -1);
199                         }
200
201                         PRT_TRACE("Setting vconf value: KEY(%s) DEVICE(%s)", VCONFKEY_SYSMAN_ADDED_USB_STORAGE, buf_dev);
202                         fclose(file);
203
204                         bundle *b = NULL;
205                         b = bundle_create();
206                         bundle_add(b, "_SYSPOPUP_CONTENT_", "otg_add");
207                         bundle_add(b, "path", buf_mnt_point);
208                         ret = syspopup_launch("usbotg-syspopup", b);
209                         if (ret < 0) {
210                                 PRT_TRACE_EM("popup lauch failed\n");
211                         }
212                         bundle_free(b);
213
214                         return 0;
215                 }
216         }
217
218         /* Failed to mount storage device */
219         PRT_TRACE_ERR("Nothing to be mounted: DEVICE(%s)", buf_dev);
220         fclose(file);
221         return -1;
222 }
223
224 static int __ss_usb_storage_removed(int argc, char *argv[])
225 {
226         if (argc != 1 || argv[0] == NULL) {
227                 PRT_TRACE_ERR("Get Vonf Value Failed: KEY(%s)", VCONFKEY_SYSMAN_REMOVED_USB_STORAGE);
228                 return -1;
229         }
230
231         int fd = -1;
232         int part_num = 0;
233
234         char *buf_dev_name = argv[0];
235         char buf_mnt_point[BUF_MAX];
236         char *mounted_check;
237
238         snprintf(buf_mnt_point, BUF_MAX, "%s/%s", MOUNT_POINT, buf_dev_name);
239
240         if (__ss_unmount_device(buf_mnt_point) == 0) {
241                 if(umount2(MOUNT_POINT, MNT_DETACH) == 0)
242                         tempfs_mounted = 1;
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         PRT_TRACE("Usb storage removed fail");
259         return 0;
260 }
261
262 int _ss_usb_storage_init()
263 {
264         ss_action_entry_add_internal(PREDEF_USB_STORAGE_ADD, __ss_usb_storage_added, NULL, NULL);
265         ss_action_entry_add_internal(PREDEF_USB_STORAGE_REMOVE, __ss_usb_storage_removed, NULL, NULL);
266
267         return 0;
268 }
269