bool CFileHelpers::removeDir(const char *Dir) { CFileHelpers* fh = CFileHelpers::getInstance(); fh->clearDebugInfo(); DIR *dir; struct dirent *entry; char path[PATH_MAX]; dir = opendir(Dir); if (dir == NULL) { if (errno == ENOENT) return true; if (!fh->getConsoleQuiet()) dprintf(DEBUG_NORMAL, "[CFileHelpers %s] remove directory %s: %s\n", __func__, Dir, strerror(errno)); char buf[1024]; memset(buf, '\0', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "remove directory %s: %s", Dir, strerror(errno)); fh->setDebugInfo(buf, __path_file__, __func__, __LINE__); return false; } while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) { snprintf(path, (size_t) PATH_MAX, "%s/%s", Dir, entry->d_name); if (entry->d_type == DT_DIR) removeDir(path); else unlink(path); } } closedir(dir); rmdir(Dir); errno = 0; return true; }
// returns: true - success. // false - errno is set bool CFileHelpers::createDir(string& Dir, mode_t mode) { CFileHelpers* fh = CFileHelpers::getInstance(); fh->clearDebugInfo(); int res = 0; for(string::iterator iter = Dir.begin() ; iter != Dir.end();) { string::iterator newIter = find(iter, Dir.end(), '/' ); string newPath = string( Dir.begin(), newIter ); if(!newPath.empty() && !file_exists(newPath.c_str())) { res = mkdir( newPath.c_str(), mode); if (res == -1) { if (errno == EEXIST) { res = 0; } else { // We can assume that if an error // occured, following will fail too, // so break here. if (!fh->getConsoleQuiet()) dprintf(DEBUG_NORMAL, "[CFileHelpers %s] creating directory %s: %s\n", __func__, newPath.c_str(), strerror(errno)); char buf[1024]; memset(buf, '\0', sizeof(buf)); snprintf(buf, sizeof(buf)-1, "creating directory %s: %s", newPath.c_str(), strerror(errno)); fh->setDebugInfo(buf, __path_file__, __func__, __LINE__); break; } } } iter = newIter; if(newIter != Dir.end()) ++ iter; } return (res == 0 ? true : false); }
int CLuaInstFileHelpers::FileHelpersCp(lua_State *L) { CLuaFileHelpers *D = FileHelpersCheckData(L, 1); if (!D) return 0; int numargs = lua_gettop(L) - 1; int min_numargs = 2; if (numargs < min_numargs) { printf("luascript cp: not enough arguments (%d, expected %d)\n", numargs, min_numargs); lua_pushboolean(L, false); return 1; } if (!lua_isstring(L, 2) || !lua_isstring(L, 3)) { printf("%s: argument 1 or 2 is not a string.\n",__func__); lua_pushboolean(L, false); return 1; } const char *from = luaL_checkstring(L, 2); const char *to = luaL_checkstring(L, 3); const char *flags = ""; if (numargs > min_numargs){ if (!lua_isstring(L, 4)) { printf("%s: argument 3 is not a string.\n",__func__); lua_pushboolean(L, false); return 1; } flags = luaL_checkstring(L, 4); } bool ret = false; CFileHelpers fh; fh.setConsoleQuiet(true); ret = fh.cp(from, to, flags); if (ret == false) { helpersDebugInfo di; fh.readDebugInfo(&di); lua_Debug ar; lua_getstack(L, 1, &ar); lua_getinfo(L, "Sl", &ar); printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", ar.short_src, ar.currentline, di.msg.c_str(), di.file.c_str(), di.line); } lua_pushboolean(L, ret); return 1; }
int CLuaInstFileHelpers::FileHelpersMkdir(lua_State *L) { CLuaFileHelpers *D = FileHelpersCheckData(L, 1); if (!D) return 0; int numargs = lua_gettop(L) - 1; int min_numargs = 1; if (numargs < min_numargs) { printf("luascript mkdir: not enough arguments (%d, expected %d)\n", numargs, min_numargs); lua_pushboolean(L, false); return 1; } if (!lua_isstring(L, 2)) { printf("%s: argument 1 is not a string.\n",__func__); lua_pushboolean(L, false); return 1; } const char *dir = luaL_checkstring(L, 2); mode_t mode = 0755; if (numargs > min_numargs) { int mode_i = luaL_checkint(L, 3); /* Hack for convert lua number to octal */ std::string mode_s = itoa(mode_i, 10); mode = (mode_t)(strtol(mode_s.c_str(), (char **)NULL, 8) & 0x0FFF); //printf("\n##### [%s:%d] str: %s, okt: %o \n \n", __func__, __LINE__, mode_s.c_str(), (int)mode); } bool ret = false; CFileHelpers* fh = CFileHelpers::getInstance(); fh->setConsoleQuiet(true); ret = fh->createDir(dir, mode); if (ret == false) { helpersDebugInfo di; fh->readDebugInfo(&di); lua_Debug ar; lua_getstack(L, 1, &ar); lua_getinfo(L, "Sl", &ar); printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", ar.short_src, ar.currentline, di.msg.c_str(), di.file.c_str(), di.line); } lua_pushboolean(L, ret); return 1; }
int CLuaInstFileHelpers::FileHelpersRmdir(lua_State *L) { CLuaFileHelpers *D = FileHelpersCheckData(L, 1); if (!D) return 0; int numargs = lua_gettop(L) - 1; int min_numargs = 1; if (numargs < min_numargs) { printf("luascript rmdir: not enough arguments (%d, expected %d)\n", numargs, min_numargs); lua_pushboolean(L, false); return 1; } if (!lua_isstring(L, 2)) { printf("%s: argument 1 is not a string.\n",__func__); lua_pushboolean(L, false); return 1; } const char *dir = luaL_checkstring(L, 2); bool ret = false; CFileHelpers* fh = CFileHelpers::getInstance(); fh->setConsoleQuiet(true); ret = fh->removeDir(dir); if (ret == false) { helpersDebugInfo di; fh->readDebugInfo(&di); lua_Debug ar; lua_getstack(L, 1, &ar); lua_getinfo(L, "Sl", &ar); printf(">>> Lua script error [%s:%d] %s\n (error from neutrino: [%s:%d])\n", ar.short_src, ar.currentline, di.msg.c_str(), di.file.c_str(), di.line); } lua_pushboolean(L, ret); return 1; }
bool COPKGManager::checkSize(const string& pkg_name) { string pkg_file = pkg_name; string plain_pkg = getBaseName(pkg_file); //exit check size if package already installed, because of auto remove of old stuff during installation if (isInstalled(plain_pkg)) return true; /* this is pretty broken right now for several reasons: * space in /tmp is limited (/tmp being ramfs usually, but wasted by unpacking the archive and then untaring it instead of using a pipe * the file is downloaded for this test, then discarded and later downloaded again for installation so until a better solution is found, simply disable it. */ #if 0 //get available root fs size //TODO: Check writability! struct statfs root_fs; statfs("/", &root_fs); u_int64_t free_size = root_fs.f_bfree*root_fs.f_bsize; /* * To calculate the required size for installation here we make a quasi-dry run, * it is a bit awkward, but relatively specific, other solutions are welcome. * We create a temporary test directory and fill it with downloaded or user uploaded package file. * Then we unpack the package and change into temporary testing directory. * The required size results from the size of generated folders and subfolders. * TODO: size of dependencies are not really considered */ CFileHelpers fh; //create test pkg dir string tmp_dest = OPKG_TEST_DIR; tmp_dest += "/package"; fh.createDir(tmp_dest); //change into test dir chdir(OPKG_TEST_DIR); //copy package into test dir string tmp_dest_file = OPKG_TEST_DIR; tmp_dest_file += "/" + plain_pkg; if(!access( pkg_file.c_str(), F_OK)) //use local package fh.copyFile(pkg_file.c_str(), tmp_dest_file.c_str(), 0644); else execCmd(pkg_types[OM_DOWNLOAD] + plain_pkg); //download package //unpack package into test dir string ar = "ar -x " + plain_pkg + char(0x2a); execCmd(ar); //untar package into test directory string untar_tar_cmd = "tar -xf "; untar_tar_cmd += OPKG_TEST_DIR; untar_tar_cmd += "/data.tar.gz -C " + tmp_dest; execCmd(untar_tar_cmd); //get new current required minimal size from dry run test dir u_int64_t req_size = fh.getDirSize(tmp_dest); //clean up fh.removeDir(OPKG_TEST_DIR); dprintf(DEBUG_INFO, "[COPKGManager] [%s - %d] Package: %s [required size=%" PRId64 " (free size: %" PRId64 ")]\n", __func__, __LINE__, pkg_name.c_str(), req_size, free_size); if (free_size < req_size){ //exit if required size too much dprintf(DEBUG_NORMAL, "[COPKGManager] [%s - %d] WARNING: size check freesize=%" PRId64 " (recommended: %" PRId64 ")\n", __func__, __LINE__, free_size, req_size); return false; } #endif return true; }
bool cYTCache::download(MI_MOVIE_INFO *mi) { std::string file = getName(mi); std::string xml = getName(mi, "xml"); if (!access(file, R_OK) && !access(xml, R_OK)) { fprintf(stderr, "%s: %s already present and valid\n", __func__, file.c_str()); return true; } FILE * fp = fopen(file.c_str(), "wb"); if (!fp) { perror(file.c_str()); return false; } CURL *curl = curl_easy_init(); if (!curl) { fclose(fp); return false; } curl_easy_setopt(curl, CURLOPT_URL, mi->file.Url.c_str()); curl_easy_setopt(curl, CURLOPT_FILE, fp); curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); curl_easy_setopt(curl, CURLOPT_TIMEOUT, URL_TIMEOUT); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, (long)1); curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, cYTCache::curlProgress); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, (long)0); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); char cerror[CURL_ERROR_SIZE]; curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, cerror); if(!g_settings.softupdate_proxyserver.empty()) { curl_easy_setopt(curl, CURLOPT_PROXY, g_settings.softupdate_proxyserver.c_str()); if(!g_settings.softupdate_proxyusername.empty()) { std::string tmp = g_settings.softupdate_proxyusername + ":" + g_settings.softupdate_proxypassword; curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, tmp.c_str()); } } dltotal = 0; dlnow = 0; dlstart = time(NULL); fprintf (stderr, "downloading %s to %s\n", mi->file.Url.c_str(), file.c_str()); CURLcode res = curl_easy_perform(curl); curl_easy_cleanup(curl); fclose(fp); if (res) { fprintf (stderr, "downloading %s to %s failed: %s\n", mi->file.Url.c_str(), file.c_str(), cerror); unlink(file.c_str()); return false; } CMovieInfo cMovieInfo; CFile File; File.Name = xml; cMovieInfo.saveMovieInfo(*mi, &File); std::string thumbnail_dst = getName(mi, "jpg"); CFileHelpers fh; fh.copyFile(mi->tfile.c_str(), thumbnail_dst.c_str(), 0644); return true; }
CFSMounter::MountRes CFSMounter::mount(const std::string &ip, const std::string &dir, const std::string &local_dir, const FSType fstype, const std::string &username, const std::string &password, std::string options1, std::string options2) { std::string cmd; pthread_mutex_init(&g_mut, NULL); pthread_cond_init(&g_cond, NULL); g_mntstatus=-1; FS_Support sup = fsSupported(fstype, true); /* keep modules if necessary */ if (sup == CFSMounter::FS_UNSUPPORTED) { printf("[CFSMounter] FS type %d not supported\n", (int) fstype); return MRES_FS_NOT_SUPPORTED; } printf("[CFSMounter] Mount(%d) %s:%s -> %s\n", (int) fstype, ip.c_str(), dir.c_str(), local_dir.c_str()); CFileHelpers fh; fh.createDir(local_dir.c_str(), 0755); if (isMounted(local_dir)) { printf("[CFSMounter] FS mount error %s already mounted\n", local_dir.c_str()); return MRES_FS_ALREADY_MOUNTED; } if(options1.empty()) { options1 = options2; options2 = ""; } if(options1.empty() && options2.empty()) { if(fstype == NFS) { options1 = "ro,soft,udp"; options2 = "nolock,rsize=8192,wsize=8192"; } else if(fstype == CIFS) { options1 = "ro"; options2 = ""; } else if(fstype == LUFS) { options1 = ""; options2 = ""; } } if(fstype == NFS) { cmd = "mount -t nfs "; cmd += ip; cmd += ':'; cmd += dir; cmd += ' '; cmd += local_dir; cmd += " -o "; cmd += options1; } else if(fstype == CIFS) { cmd = "mount -t cifs //"; cmd += ip; cmd += '/'; cmd += dir; cmd += ' '; cmd += local_dir; cmd += " -o username="******",password="******",iocharset=UTF8"; //cmd += ",unc=//"; for whats needed? //cmd += ip; //cmd += '/'; //cmd += dir; //cmd += ','; //cmd += options1; } else { cmd = "lufsd none "; cmd += local_dir; cmd += " -o fs=ftpfs,username="******",password="******",host="; cmd += ip; cmd += ",root=/"; cmd += dir; cmd += ','; cmd += options1; } if (options2[0] !='\0') { cmd += ','; cmd += options2; } pthread_create(&g_mnt, 0, mount_thread, (void *) cmd.c_str()); struct timespec timeout; int retcode; pthread_mutex_lock(&g_mut); timeout.tv_sec = time(NULL) + 5; timeout.tv_nsec = 0; retcode = pthread_cond_timedwait(&g_cond, &g_mut, &timeout); if (retcode == ETIMEDOUT) { // timeout occurred pthread_cancel(g_mnt); } pthread_mutex_unlock(&g_mut); pthread_join(g_mnt, NULL); if ( g_mntstatus != 0 ) { printf("[CFSMounter] FS mount error: \"%s\"\n", cmd.c_str()); return (retcode == ETIMEDOUT) ? MRES_TIMEOUT : MRES_UNKNOWN; } return MRES_OK; }
bool CFlashTool::program( const std::string & filename, int globalProgressEndErase, int globalProgressEndFlash ) { int fd1; ssize_t filesize; int globalProgressBegin = 0; if(g_settings.epg_save) CNeutrinoApp::getInstance()->saveEpg(true); if(statusViewer) statusViewer->showLocalStatus(0); if (mtdDevice.empty()) { ErrorMessage = "mtd-device not set"; return false; } char buf1[1024]; memset(buf1, 0, sizeof(buf1)); strncpy(buf1, filename.c_str(), sizeof(buf1)-1); char* dn = dirname(buf1); std::string flashfile; bool skipCopy = false; #ifdef BOXMODEL_APOLLO if (strcmp(dn, "/tmp") != 0) { uint64_t btotal = 0, bused = 0; long bsize = 0; if (get_fs_usage("/tmp", btotal, bused, &bsize)) { uint64_t fileSize = (uint64_t)file_size(filename.c_str()) / 1024ULL; uint64_t backupMaxSize = (int)((btotal - bused) * bsize); uint64_t res = 10; // Reserved 10% of available space backupMaxSize = (backupMaxSize - ((backupMaxSize * res) / 100ULL)) / 1024ULL; if (backupMaxSize < fileSize) skipCopy = true; } else skipCopy = true; } #endif if ((strcmp(dn, "/tmp") != 0) && !skipCopy) { memset(buf1, 0, sizeof(buf1)); strncpy(buf1, filename.c_str(), sizeof(buf1)-1); flashfile = (std::string)"/tmp/" + basename(buf1); CFileHelpers fh; printf("##### [CFlashTool::program] copy flashfile to %s\n", flashfile.c_str()); if(statusViewer) statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_COPY_IMAGE)); fh.copyFile(filename.c_str(), flashfile.c_str(), 0644); sync(); if(statusViewer) statusViewer->showGlobalStatus(statusViewer->getGlobalStatus()+5); } else flashfile = filename; // Unmount all NFS & CIFS volumes if (!skipCopy) { nfs_mounted_once = false; CFSMounter::umount(); } if( (fd1 = open( flashfile.c_str(), O_RDONLY )) < 0 ) { ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENFILE); return false; } filesize = (ssize_t)lseek( fd1, 0, SEEK_END); lseek( fd1, 0, SEEK_SET); if(filesize==0) { ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_FILEIS0BYTES); close(fd1); return false; } if(statusViewer) { statusViewer->showLocalStatus(0); statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_ERASING)); // UTF-8 } if(!erase(globalProgressEndErase)) { close(fd1); return false; } if(statusViewer) { if(globalProgressEndErase!=-1) statusViewer->showGlobalStatus(globalProgressEndErase); statusViewer->showLocalStatus(0); statusViewer->showStatusMessageUTF(g_Locale->getText(LOCALE_FLASHUPDATE_PROGRAMMINGFLASH)); // UTF-8 } #ifndef VFD_UPDATE CVFD::getInstance()->ShowText("Write Flash"); #endif if( (fd = open( mtdDevice.c_str(), O_WRONLY )) < 0 ) { ErrorMessage = g_Locale->getText(LOCALE_FLASHUPDATE_CANTOPENMTD); close(fd1); return false; } if(statusViewer) globalProgressBegin = statusViewer->getGlobalStatus(); unsigned char buf[meminfo.writesize]; unsigned mtdoffset = 0; unsigned fsize = filesize; printf("CFlashTool::program: file %s write size %d, erase size %d\n", flashfile.c_str(), meminfo.writesize, meminfo.erasesize); while(fsize > 0) { unsigned block = meminfo.writesize; if (block > fsize) block = fsize; unsigned res = read(fd1, buf, block); if (res != block) { printf("CFlashTool::program: read from %s failed: %d from %d\n", flashfile.c_str(), res, block); } if (isnand) { if (block < (unsigned) meminfo.writesize) { printf("CFlashTool::program: padding at %x\n", mtdoffset); memset(buf + res, 0, meminfo.writesize - res); } unsigned blockstart = mtdoffset & ~(meminfo.erasesize - 1); if (blockstart == mtdoffset) { while (mtdoffset < meminfo.size) { printf("CFlashTool::program: write block at %x\n", mtdoffset); loff_t offset = mtdoffset; int ret = ioctl(fd, MEMGETBADBLOCK, &offset); if (ret == 0) break; printf("CFlashTool::program: bad block at %x, skipping..\n", mtdoffset); mtdoffset += meminfo.erasesize; lseek(fd, mtdoffset, SEEK_SET); continue; } if (mtdoffset >= meminfo.size) { printf("CFlashTool::program: not enough space to write, left: %d\n", fsize); break; } } } write(fd, buf, meminfo.writesize); fsize -= block; mtdoffset += meminfo.writesize; int prog = int(100-(100./filesize*fsize)); if(statusViewer) { statusViewer->showLocalStatus(prog); if(globalProgressEndFlash!=-1) { int globalProg = globalProgressBegin + int((globalProgressEndFlash-globalProgressBegin) * prog/100. ); statusViewer->showGlobalStatus(globalProg); } } printf( "Writing %u Kbyte @ 0x%08X -- %2u %% complete.\n", block/1024, mtdoffset, prog); } if(statusViewer) statusViewer->showLocalStatus(100); close(fd1); close(fd); // FIXME error message if (fsize) return false; CVFD::getInstance()->ShowText("Flash OK."); return true; }