trunk 20080912
[gitenigma.git] / src / enigma_mount.cpp
blob9d95215dc7e49f8d7d3923cef238748175ae16eb
1 /*
2 * $Id: enigma_mount.cpp,v 1.64 2007/02/18 18:00:57 digi_casi Exp $
4 * (C) 2005, 2007 by digi_casi <digi_casi@tuxbox.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #ifdef ENABLE_EXPERT_WEBIF
23 #include <errno.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <time.h>
28 #include <sys/wait.h>
29 #include <sys/mount.h>
30 #include <iostream>
31 #include <sstream>
32 #include <fstream>
33 #include <pthread.h>
34 #include <string.h>
35 #include <vector>
36 #include <lib/base/estring.h>
37 #include <lib/gui/enumber.h>
38 #include <configfile.h>
39 #include <enigma_dyn_utils.h>
40 #include <enigma_mount.h>
41 #include <configfile.h>
42 #include <enigma_main.h>
44 using namespace std;
46 eMountMgr *eMountMgr::instance;
48 eMountPoint::~eMountPoint()
52 eMountPoint::eMountPoint(t_mount pmp)
54 mp = pmp;
57 void eMountPoint::save(FILE *out, int pid)
59 mp.id = pid;
60 fprintf(out,"ip_%d=%d.%d.%d.%d\n", mp.id, mp.ip[0], mp.ip[1], mp.ip[2], mp.ip[3]);
61 fprintf(out,"fstype_%d=%d\n", mp.id, mp.fstype);
62 fprintf(out,"localdir_%d=%s\n", mp.id, mp.localDir.c_str());
63 fprintf(out,"mountdir_%d=%s\n", mp.id, mp.mountDir.c_str());
64 fprintf(out,"username_%d=%s\n", mp.id, mp.userName.c_str());
65 fprintf(out,"password_%d=%s\n", mp.id, mp.password.c_str());
66 fprintf(out,"options_%d=%s\n", mp.id, mp.options.c_str());
67 fprintf(out,"description_%d=%s\n", mp.id, mp.description.c_str());
68 fprintf(out,"automount_%d=%d\n", mp.id, mp.automount);
69 fprintf(out,"\n");
72 bool eMountPoint::fileSystemIsSupported(eString fsname)
74 eString s;
75 bool found = false;
76 fsname = fsname.upper();
77 std::ifstream in("/proc/filesystems", std::ifstream::in);
79 while (in >> s)
81 if (found = (s.upper() == fsname))
82 break;
85 in.close();
86 return found;
89 bool eMountPoint::isMounted()
91 std::ifstream in;
92 eString mountDev;
93 eString mountOn;
94 eString mountType;
95 eString buffer;
96 std::stringstream tmp;
98 bool found = false;
99 in.open("/proc/mounts", std::ifstream::in);
100 while (getline(in, buffer, '\n'))
102 mountDev = mountOn = mountType = "";
103 tmp.str(buffer);
104 tmp >> mountDev >> mountOn >> mountType;
105 tmp.clear();
106 if (found = isIdentical(mountOn, mountDev))
107 break;
109 in.close();
110 return found;
113 bool eMountPoint::isIdentical(eString mountOn, eString mountDev)
115 bool found = false;
117 if (mountOn == mp.localDir)
119 switch (mp.fstype)
121 case 0: //NFS
122 found = (eString().sprintf("%d.%d.%d.%d:%s", mp.ip[0], mp.ip[1], mp.ip[2], mp.ip[3], mp.mountDir.c_str()) == mountDev);
123 break;
124 case 1: //CIFS
125 case 3: //SMBFS
126 found = (eString().sprintf("//%d.%d.%d.%d/%s", mp.ip[0], mp.ip[1], mp.ip[2], mp.ip[3], mp.mountDir.c_str()).upper() == mountDev.upper());
127 break;
128 case 2: //DEVICE
129 found = ((mountOn == mp.localDir) && (mountDev == mp.mountDir) && (mp.ip[0] == 0) && (mp.ip[1] == 0) && (mp.ip[2] == 0) && (mp.ip[3] == 0));
130 break;
131 default:
132 break;
135 return found;
138 int eMountPoint::mount()
140 eString cmd;
141 eString ip;
142 int rc = 0;
144 if (!mp.mounted)
146 if (!isMounted())
148 if (access(mp.localDir.c_str(), R_OK) == -1)
149 system(eString("mkdir " + mp.localDir).c_str());
150 if (access(mp.localDir.c_str(), R_OK) == 0)
152 ip.sprintf("%d.%d.%d.%d", mp.ip[0], mp.ip[1], mp.ip[2], mp.ip[3]);
153 switch (mp.fstype)
155 case 0: /* NFS */
156 if (fileSystemIsSupported("nfs"))
158 cmd = "mount -t nfs ";
159 cmd += ip + ":" + mp.mountDir + " " + mp.localDir;
160 cmd += (mp.options) ? (" -o " + mp.options) : "";
162 else
163 rc = -4; //NFS filesystem not supported
164 break;
165 case 1: /* CIFS */
166 if (fileSystemIsSupported("cifs"))
168 cmd = "mount -t cifs //";
169 cmd += ip + "/" + mp.mountDir + " " + mp.localDir + " -o user=";
170 cmd += (mp.userName) ? mp.userName : "anonymous";
171 cmd += (mp.password) ? (",pass=" + mp.password) : "";
172 cmd += ",unc=//" + ip + "/" + mp.mountDir;
173 cmd += (mp.options) ? ("," + mp.options) : "";
175 else
176 rc = -3; //CIFS filesystem not supported
177 break;
178 case 2:
179 cmd = "mount " + mp.mountDir + " " + mp.localDir;
180 break;
181 case 3: /* SMBFS */
182 if (fileSystemIsSupported("smbfs"))
184 cmd = "smbmount ";
185 cmd += "//" + ip + "/" + mp.mountDir;
186 cmd += " " + ((mp.password) ? mp.password : "guest");
187 cmd += " -U " + ((mp.userName) ? mp.userName : "guest");
188 cmd += " -I " + ip;
189 cmd += " -c \"mount " + mp.localDir + "\"";
191 else
192 rc = -3; //SMBFS filesystem not supported
193 break;
196 if (rc == 0)
198 eDebug("[ENIGMA_MOUNT] mounting: %s", cmd.c_str());
200 switch (fork())
202 case -1:
203 eDebug("[ENIGMA_MOUNT] fork failed!");
204 rc = -5;
205 break;
206 case 0:
208 for (unsigned int i = 0; i < 90; ++i )
209 close(i);
211 rc = system(cmd.c_str());
212 if (mp.localDir == "/hdd")
213 system("sleep 5 && wget -O /dev/null http://127.0.0.1/cgi-bin/reloadRecordings&");
214 _exit(0);
215 break;
220 else
221 rc = -10; //couldn't create local dir
223 else
224 rc = -2; //local dir is already a mountpoint
226 else
227 rc = -1; //mount point is already mounted
229 return rc;
231 -1: "Mountpoint is already mounted.";
232 -2: "Local directory is already used as mount point.";
233 -3: "CIFS is not supported.";
234 -4: "NFS is not supported.";
235 -5: "Mount failed (timeout).";
236 -10: "Unable to create mount dir.";
240 int eMountPoint::unmount()
242 mp.mounted = false;
243 int rc = umount2(mp.localDir.c_str(), MNT_FORCE);
244 if (mp.localDir == "/hdd")
245 system("sleep 5 && wget -O /dev/null http://127.0.0.1/cgi-bin/reloadRecordings&");
246 return rc;
249 eMountMgr::eMountMgr()
251 if (!instance)
252 instance = this;
254 init();
257 eMountMgr::~eMountMgr()
259 mountPoints.clear();
260 instance = NULL;
263 int eMountMgr::addMountPoint(t_mount pmp)
265 pmp.id = mountPoints.size();
266 mountPoints.push_back(eMountPoint(pmp));
267 save();
268 return pmp.id;
271 t_mount eMountMgr::getMountPointData(int pid)
273 t_mount tmp;
274 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
276 if (mp_it->mp.id == pid)
278 tmp = mp_it->mp;
279 break;
282 return tmp;
285 void eMountMgr::changeMountPoint(int pid, t_mount pmp)
287 int rc = 0;
288 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
290 if (mp_it->mp.id == pid)
292 if (mp_it->mp.mounted)
294 rc = mp_it->unmount();
295 mp_it->mp = pmp;
296 rc = mp_it->mount();
298 else
299 mp_it->mp = pmp;
300 save();
301 break;
304 save();
307 void eMountMgr::removeMountPoint(int id)
309 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
311 if (mp_it->mp.id == id)
313 mountPoints.erase(mp_it);
314 break;
317 save();
320 int eMountMgr::mountMountPoint(int id)
322 int rc = 0;
323 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
325 if (mp_it->mp.id == id)
327 rc = mp_it->mount();
328 break;
331 return rc;
334 int eMountMgr::mountMountPoint(eString localDir)
336 int rc = 0;
337 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
339 if (mp_it->mp.localDir == localDir)
341 if (!mp_it->mp.mounted)
342 rc = mp_it->mount();
343 break;
346 return rc;
349 bool eMountMgr::isMountPointMounted(eString localDir)
351 bool rc = false;
352 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
354 if (mp_it->mp.localDir == localDir)
356 if (mp_it->mp.mounted)
357 rc = true;
358 break;
361 return rc;
364 int eMountMgr::unmountMountPoint(int id)
366 int rc = 0;
367 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
369 if (mp_it->mp.id == id)
371 rc = mp_it->unmount();
372 break;
375 return rc;
378 int eMountMgr::selectMovieSource(int id)
380 int rc = 0;
381 eDebug("[ENIGMA_MOUNT] selectMovieSource id: %d", id);
382 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
384 if ((mp_it->mp.localDir == "/hdd") && mp_it->mp.mounted)
386 eDebug("[ENIGMA_MOUNT] selectMovieSource unmounting: %s", mp_it->mp.mountDir.c_str());
387 rc = mp_it->unmount();
391 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
393 if (mp_it->mp.id == id)
395 eDebug("[ENIGMA_MOUNT] selectMovieSource mounting: %s", mp_it->mp.mountDir.c_str());
396 mp_it->mp.localDir = "/hdd"; // force /hdd
397 rc = mp_it->mount();
398 save();
399 break;
403 eDebug("[ENIGMA_MOUNT] selectMovieSource rc: %d", rc);
404 return rc;
407 void eMountMgr::automountMountPoints(void)
409 eDebug("[ENIGMA_MOUNT] automountMountPoints...");
410 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
412 eDebug("[ENIGMA_MOUNT] automountMountPoints: %s - %d", mp_it->mp.mountDir.c_str(), mp_it->mp.automount);
413 if (mp_it->mp.automount == 1)
415 eDebug("[ENIGMA_MOUNT] automounting %s", mp_it->mp.mountDir.c_str());
416 mp_it->mount();
421 void eMountMgr::unmountAllMountPoints(void)
423 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
425 if (mp_it->mp.mounted == 1 && mp_it->mp.automount == 1)
426 mp_it->unmount();
430 eString eMountMgr::listMountPoints(eString skelleton)
432 eString result, mountStatus, action;
433 init();
434 if (mountPoints.size() > 0)
435 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
437 eString tmp = skelleton;
438 if (mp_it->mp.mounted)
440 mountStatus = "<img src=\"on.gif\" alt=\"online\" border=0>";
441 action = button(75, "Unmount", RED, "javascript:unmountMountPoint('" + eString().sprintf("%d", mp_it->mp.id) + "')", "#FFFFFF");
443 else
445 mountStatus = "<img src=\"off.gif\" alt=\"offline\" border=0>";
446 action = button(75, "Mount", BLUE, "javascript:mountMountPoint('" + eString().sprintf("%d", mp_it->mp.id) + "')", "#FFFFFF");
448 tmp.strReplace("#ACTIONBUTTON#", action);
449 tmp.strReplace("#CHANGEID#", eString().sprintf("%d", mp_it->mp.id));
450 tmp.strReplace("#DELETEID#", eString().sprintf("%d", mp_it->mp.id));
451 tmp.strReplace("#MOUNTED#", mountStatus);
452 tmp.strReplace("#LDIR#", mp_it->mp.localDir);
453 tmp.strReplace("#MDIR#", mp_it->mp.mountDir);
454 tmp.strReplace("#IP#", eString().sprintf("%3d.%3d.%3d.%3d", mp_it->mp.ip[0], mp_it->mp.ip[1], mp_it->mp.ip[2], mp_it->mp.ip[3]));
455 tmp.strReplace("#USER#", mp_it->mp.userName);
456 tmp.strReplace("#PW#", mp_it->mp.password);
457 eString type = "DEV";
458 if (mp_it->mp.fstype == 0)
459 type = "NFS";
460 else
461 if (mp_it->mp.fstype == 1)
462 type = "CIFS";
463 else
464 if (mp_it->mp.fstype == 3)
465 type = "SMBFS";
466 tmp.strReplace("#FSTYPE#", type);
467 tmp.strReplace("#AUTO#", eString().sprintf("%d", mp_it->mp.automount));
468 tmp.strReplace("#OPTIONS#", mp_it->mp.options);
469 tmp.strReplace("#DESCRIPTION#", mp_it->mp.description);
470 result += tmp + "\n";
472 else
473 result = "<tr><td>No mount points available.</td></tr>";
475 return result;
478 eString eMountMgr::listMovieSources()
480 eString tmp, result;
481 init();
482 if (mountPoints.size() > 0)
483 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
485 if (mp_it->mp.localDir == "/hdd")
487 tmp = "<option #SEL# value=\"" + eString().sprintf("%d", mp_it->mp.id) + "\">" + ((mp_it->mp.description) ? mp_it->mp.description : mp_it->mp.mountDir) + "</option>";
488 if (mp_it->mp.mounted)
489 tmp.strReplace("#SEL#", "selected");
490 else
491 tmp.strReplace("#SEL#", "");
493 result += tmp + "\n";
496 else
497 result = "<option selected value=\"0\">No movie source available.</option>";
499 if (result.find("selected") == eString::npos)
500 result = "<option selected value=\"0\">No movie source selected.</option>\n" + result;
502 return result;
505 void eMountMgr::addMountedFileSystems()
507 std::ifstream in;
508 eString mountDev;
509 eString mountOn;
510 eString mountType;
511 eString buffer;
512 std::stringstream tmp;
513 bool found = false;
514 t_mount mp;
516 in.open("/proc/mounts", std::ifstream::in);
517 while (getline(in, buffer, '\n'))
519 mountDev = mountOn = mountType = "";
520 tmp.str(buffer);
521 tmp >> mountDev >> mountOn >> mountType;
522 tmp.clear();
524 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
526 if (found = mp_it->isIdentical(mountOn, mountDev))
527 break;
530 if (!found)
532 //add the mount point
533 if (mountType.upper() == "NFS")
535 if (mountDev.find("/dev") != eString::npos)
537 sscanf(mountDev.c_str(), "%d.%d.%d.%d:%*s", &mp.ip[0], &mp.ip[1], &mp.ip[2], &mp.ip[3]);
538 mp.mountDir = getRight(mountDev, ':');
539 mp.localDir = mountOn;
540 mp.fstype = 0;
541 mp.password = "";
542 mp.userName = "";
543 mp.automount = 0;
544 mp.options = "";
545 mp.description = "";
546 mp.mounted = true;
547 mp.id = -1; //don't care
548 addMountPoint(mp);
551 else
552 if (mountType.upper() == "CIFS")
554 sscanf(mountDev.c_str(), "//%d.%d.%d.%d/%*s", &mp.ip[0], &mp.ip[1], &mp.ip[2], &mp.ip[3]);
555 mountDev = mountDev.right(mountDev.length() - 2); //strip off leading slashes
556 mp.mountDir = getRight(mountDev, '/');
557 mp.localDir = mountOn;
558 mp.fstype = 1;
559 mp.password = "";
560 mp.userName = "";
561 mp.automount = 0;
562 mp.options = "";
563 mp.description = "";
564 mp.mounted = true;
565 mp.id = -1; //don't care
566 addMountPoint(mp);
568 else
569 if (mountType.upper() == "SMBFS")
571 sscanf(mountDev.c_str(), "//%d.%d.%d.%d/%*s", &mp.ip[0], &mp.ip[1], &mp.ip[2], &mp.ip[3]);
572 mountDev = mountDev.right(mountDev.length() - 2); //strip off leading slashes
573 mp.mountDir = getRight(mountDev, '/');
574 mp.localDir = mountOn;
575 mp.fstype = 3;
576 mp.password = "";
577 mp.userName = "";
578 mp.automount = 0;
579 mp.options = "";
580 mp.description = "";
581 mp.mounted = true;
582 mp.id = -1; //don't care
583 addMountPoint(mp);
585 else
586 if (!((mountOn == "/") ||(mountOn == "/dev") || (mountOn == "/tmp") || (mountOn == "/proc") || (mountOn == "/dev/pts") ||
587 (mountDev.find("/dev/mtdblock") != eString::npos) || (mountDev == "usbfs") || (mountOn == "")))
589 //other file system
590 sscanf("//0.0.0.0/nothing", "//%d.%d.%d.%d/%*s", &mp.ip[0], &mp.ip[1], &mp.ip[2], &mp.ip[3]);
591 mp.mountDir = mountDev;
592 mp.localDir = mountOn;
593 mp.fstype = 2;
594 mp.password = "";
595 mp.userName = "";
596 mp.automount = 0;
597 mp.options = "";
598 mp.description = "";
599 mp.mounted = true;
600 mp.id = -1; //don't care
601 addMountPoint(mp);
605 in.close();
608 void eMountMgr::init()
610 t_mount mp;
611 mountPoints.clear();
612 CConfigFile *config = new CConfigFile(',');
613 if (config->loadConfig(MOUNTCONFIGFILE))
615 for (int i = 0; true; i++)
617 if (config->getString(eString().sprintf("localdir_%d", i)) != "")
619 mp.localDir = config->getString(eString().sprintf("localdir_%d", i));
620 mp.fstype = config->getInt32(eString().sprintf("fstype_%d", i));
621 mp.password = config->getString(eString().sprintf("password_%d", i));
622 mp.userName = config->getString(eString().sprintf("username_%d", i));
623 mp.mountDir = config->getString(eString().sprintf("mountdir_%d", i));
624 mp.automount = config->getInt32(eString().sprintf("automount_%d", i));
625 mp.options = config->getString(eString().sprintf("options_%d", i));
626 mp.description = config->getString(eString().sprintf("description_%d", i));
627 eString sip = config->getString(eString().sprintf("ip_%d", i));
628 sscanf(sip.c_str(), "%d.%d.%d.%d", &mp.ip[0], &mp.ip[1], &mp.ip[2], &mp.ip[3]);
629 mp.id = i;
630 eMountPoint m = eMountPoint(mp);
631 m.mp.mounted = m.isMounted();
632 mountPoints.push_back(m);
634 else
635 break;
638 delete config;
640 addMountedFileSystems();
643 void eMountMgr::save()
645 FILE *out = fopen(MOUNTCONFIGFILE, "w");
646 if (out)
648 int i = 0;
649 for (mp_it = mountPoints.begin(); mp_it != mountPoints.end(); mp_it++)
651 if ((mp_it->mp.fstype != 2) || (mp_it->mp.mountDir.find("disc") != eString::npos) || (mp_it->mp.mountDir.find("part1") != eString::npos)) // just save NFS, CIFS, and SMBFS
653 mp_it->save(out, i);
654 i++;
657 fclose(out);
661 #endif