Example #1
0
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;
}
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 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;
}