native extension Dart - postgresql

I'm trying to build a native extension in dart for postgresql. I have compiled the CC file in .o then in .so (shared object i guess). It's now named libpsql.so and I placed it in the the same directory as my .dart file. The first line of dart file is #import(dart-ext:libpsql); but it keeps telling me that the resources is unavailable.
My dart code
#library("psql");
#import("dart-ext:libpsql_dart");
class Database {
var mDb;
var mUser;
var mDbname;
var mPasswd;
var mHost;
var mPort;
var mTable;
//String toString() => "<PostgreSQL: $user#$_host:$_port/$_table>";
Database(host,user,passwd,dbname) : this.mUser = user, this.mHost = host, this.mPasswd = passwd, this.mDbname = dbname {
mDb = _connect(host,user,passwd,dbname);
}
}
_connect(host,user,passwd,dbname) native 'Connect';
And here is my C++ code.
#include <string.h>
#include <stdio.h>
#include <libpq-fe.h>
#include "dart_api.h"
Dart_NativeFunction ResolveName(Dart_Handle name, int argc);
DART_EXPORT Dart_Handle psql_dart_Init(Dart_Handle parent_library) {
if (Dart_IsError(parent_library)) return parent_library;
Dart_Handle result_code =
Dart_SetNativeResolver(parent_library, ResolveName);
if (Dart_IsError(result_code)) return result_code;
return Dart_Null();
}
Dart_Handle HandleError(Dart_Handle handle) {
if (Dart_IsError(handle)) Dart_PropagateError(handle);
return handle;
}
void Connect(Dart_NativeArguments args) {
Dart_EnterScope();
PGconn *conn;
const char *conninfo = "user=postgres;password=postgres;host=localhost;port=5432;dbname=reviewdb";
conn = PQconnectdb(conninfo);
/* Check to see that the backend connection was successfully made */
if (PQstatus(conn) != CONNECTION_OK)
{
fprintf(stderr, "Connection to database failed: %s",
PQerrorMessage(conn));
PQfinish(conn);
}
Dart_Handle result = HandleError(Dart_NewInteger((int64_t) conn));
Dart_SetReturnValue(args, result);
Dart_ExitScope();
}
Dart_NativeFunction ResolveName(Dart_Handle name, int argc) {
assert(Dart_IsString8(name));
const char* cname;
Dart_Handle check_error = Dart_StringToCString(name, &cname);
if (Dart_IsError(check_error)) Dart_PropagateError(check_error);
Dart_NativeFunction result = NULL;
if (strcmp("Connect", cname) == 0) result = Connect;
Dart_ExitScope();
return result;
}
Html script include
<script type="application/dart" src="web/lib/psql.dart"></script>
<script type="application/dart" src="web/test_dart.dart"></script>
And the last, my compile command line :
g++ -fPIC --verbose -I/home/{linux user}/Documents/dart/dart-sdk/include/ -lpq -I/usr/include/postgresql -c psql_dart.cc
gcc -shared -Wl,-soname,libpsql.so -o libpsql.so psql_dart.o
After testing new code i commented my function Connect like this :
void Connect(Dart_NativeArguments args) {
Dart_EnterScope();
// PGconn *conn;
// const char *conninfo = "user=postgres password=postgres host=localhost port=5432";
// conn = PQconnectdb(conninfo);
//
// /* Check to see that the backend connection was successfully made */
// if (PQstatus(conn) != CONNECTION_OK)
// {
// fprintf(stderr, "Connection to database failed: %s",
// PQerrorMessage(conn));
// PQfinish(conn);
// exit(1);
// }
// PQfinish(conn);
Dart_Handle result = HandleError(Dart_NewInteger( 0));
Dart_SetReturnValue(args, result);
Dart_ExitScope();
}
The output :
worked?
Segmentation fault (core dumped)
And I still get the SegFault any idea?
My gdb stacktrace :
Starting program: /home/<user>/Documents/dart/dart-sdk/bin/dart test_dart.dart
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
worked?
Program received signal SIGSEGV, Segmentation fault.
dart::Api::NewHandle (isolate=0x948a40, raw=0x7ffff7f80021) at runtime/vm/dart_api_impl.cc:114
114 runtime/vm/dart_api_impl.cc: No such file or directory.
(gdb) bt
#0 dart::Api::NewHandle (isolate=0x948a40, raw=0x7ffff7f80021) at runtime/vm/dart_api_impl.cc:114
#1 0x000000000042e121 in dart::Dart_Invoke (target=<optimized out>, name=0x959b90, number_of_arguments=<optimized out>, arguments=<optimized out>) at runtime/vm/dart_api_impl.cc:3543
#2 0x00000000004097ee in main (argc=<optimized out>, argv=<optimized out>) at runtime/bin/main.cc:724

After playing around some with your code and getting the postgresql-dev-9.1 package installed this is where I am. Currently it still does not run, however it is due to a linking error not due to the import itself.
Note a change to your C++ file: I renamed your initialization function from: psql_dart_Init to just psql_Init
// libpsql.cc
#include <string.h>
#include <stdio.h>
#include <libpq-fe.h>
#include "dart_api.h"
Dart_NativeFunction ResolveName(Dart_Handle name, int argc);
DART_EXPORT Dart_Handle psql_Init(Dart_Handle parent_library) {
if (Dart_IsError(parent_library)) return parent_library;
Dart_Handle result_code =
Dart_SetNativeResolver(parent_library, ResolveName);
if (Dart_IsError(result_code)) return result_code;
return Dart_Null();
}
Dart_Handle HandleError(Dart_Handle handle) {
if (Dart_IsError(handle)) Dart_PropagateError(handle);
return handle;
}
void Connect(Dart_NativeArguments args) {
Dart_EnterScope();
PGconn *conn;
const char *conninfo = "user=postgres;password=postgres;host=localhost;port=5432;dbname=reviewdb";
conn = PQconnectdb(conninfo);
/* Check to see that the backend connection was successfully made */
if (PQstatus(conn) != CONNECTION_OK)
{
fprintf(stderr, "Connection to database failed: %s",
PQerrorMessage(conn));
PQfinish(conn);
}
Dart_Handle result = HandleError(Dart_NewInteger((int64_t) conn));
Dart_SetReturnValue(args, result);
Dart_ExitScope();
}
Dart_NativeFunction ResolveName(Dart_Handle name, int argc) {
assert(Dart_IsString8(name));
const char* cname;
Dart_Handle check_error = Dart_StringToCString(name, &cname);
if (Dart_IsError(check_error)) Dart_PropagateError(check_error);
Dart_NativeFunction result = NULL;
if (strcmp("Connect", cname) == 0) result = Connect;
Dart_ExitScope();
return result;
}
And the following is my 1st dart file:
// psql.dart
#library("psql");
#import("dart-ext:psql");
class Database {
var mDb;
var mUser;
var mDbname;
var mPasswd;
var mHost;
var mPort;
var mTable;
//String toString() => "<PostgreSQL: $user#$_host:$_port/$_table>";
Database(host,user,passwd,dbname) : this.mUser = user, this.mHost = host, this.mPasswd = passwd, this.mDbname = dbname {
mDb = _connect(host,user,passwd,dbname);
}
}
_connect(host,user,passwd,dbname) native 'Connect';
And then the actual VERY minimal application (command line instead of dartium-based) to test it.
// test.dart
#import('psql.dart');
main() {
var database = new Database('localhost', 'mbutler', 'test', 'test');
if(database != null) {
print('worked?');
}
}
I used the following command to compile and link in one go and I it does work correctly. I segfault because I don't have a valid database to connect to but the following does load the native library properly:
g++ -O2 -DDART_SHARED_LIB -I/home/<user>/dart/dart-sdk/include -rdynamic -fPIC -shared libpsql.cc -lpq -I/usr/include/postgresql -o libpsql.so
(Thanks to dart-sqlite build script was able to piece together the linking I required)

Related

how to make HTTPS request in esp8266?

I once wanted to get THERMOCOUPLE DATA and by making HTTP request I put it on API
it worked flawlessly , here is the code for esp32:
// this example is public domain. enjoy! https://learn.adafruit.com/thermocouple/
#include "max6675.h"
#include <ArduinoJson.h>
#include <HTTPClient.h>
#include <WiFiMulti.h>
int thermoDO = 19;
int thermoCS = 23;
int thermoCLK = 5;
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
const char *AP_SSID = "ssid";
const char *AP_PWD = "pass";
WiFiMulti wifiMulti;
void setup() {
Serial.begin(9600);
delay(4000);
wifiMulti.addAP(AP_SSID, AP_PWD);
Serial.println("MAX6675 test");
// wait for MAX chip to stabilize
delay(500);
}
void loop() {
// basic readout test, just print the current temp
Serial.print("C = ");
Serial.println(thermocouple.readCelsius());
Serial.print("F = ");
Serial.println(thermocouple.readFahrenheit());
// For the MAX6675 to update, you must delay AT LEAST 250ms between reads!
delay(1000);
postDataToServer();
}
void postDataToServer() {
Serial.println("Posting JSON data to server...");
// Block until we are able to connect to the WiFi access point
if (wifiMulti.run() == WL_CONNECTED) {
HTTPClient http;
http.begin("https://retoolapi.dev/fyXalF/data/1");
http.addHeader("Content-Type", "application/json");
StaticJsonDocument<200> doc;
// Add values in the document
//
doc["temp1"] = thermocouple.readCelsius();
doc["temp2"] = thermocouple.readFahrenheit();
String requestBody;
serializeJson(doc, requestBody);
int httpResponseCode = http.PUT(requestBody);
if(httpResponseCode>0){
String response = http.getString();
Serial.println(httpResponseCode);
Serial.println(response);
}
else {
Serial.printf("Error occurred while sending HTTP POST");
}
}
}
now I'm trying to do it by esp8266.
so the code is basically the same , you have to put "ESP8266" before library names and for making http.begin() you have to pass a WiFiClient beside API address :
// this example is public domain. enjoy! https://learn.adafruit.com/thermocouple/
#include "max6675.h"
#include <ArduinoJson.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFiMulti.h>
#include <WiFiClientSecure.h>
int thermoDO = 19;
int thermoCS = 23;
int thermoCLK = 5;
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
const char *AP_SSID = "ssid";
const char *AP_PWD = "pass";
ESP8266WiFiMulti wifiMulti;
void setup() {
Serial.begin(9600);
delay(4000);
wifiMulti.addAP(AP_SSID, AP_PWD);
Serial.println("MAX6675 test");
// wait for MAX chip to stabilize
delay(500);
}
void loop() {
// basic readout test, just print the current temp
Serial.print("C = ");
Serial.println(thermocouple.readCelsius());
Serial.print("F = ");
Serial.println(thermocouple.readFahrenheit());
// For the MAX6675 to update, you must delay AT LEAST 250ms between reads!
delay(1000);
postDataToServer();
}
void postDataToServer() {
Serial.println("Posting JSON data to server...");
// Block until we are able to connect to the WiFi access point
if (wifiMulti.run() == WL_CONNECTED) {
WiFiClient client;
HTTPClient http;
http.begin(client,"https://retoolapi.dev/fyXalF/data/1");
http.addHeader("Content-Type", "application/json");
StaticJsonDocument<200> doc;
// Add values in the document
//
doc["temp1"] = thermocouple.readCelsius();
doc["temp2"] = thermocouple.readFahrenheit();
String requestBody;
serializeJson(doc, requestBody);
int httpResponseCode = http.PUT(requestBody);
if(httpResponseCode>0){
String response = http.getString();
Serial.println(httpResponseCode);
Serial.println(response);
}
else {
Serial.printf("Error occurred while sending HTTP POST");
}
}
}
it compiled but I got "bad request-400" and "The plain HTTP request was sent to HTTPS port" as a response .
I think the esp8266 library cant send https requests ...
any ideas how to solve this ?
PS : I also use #include <WiFiClientSecure.h>
WiFiClientSecure client;
HTTPClient http;
http.begin(client,"https://retoolapi.dev/0tvafA/data/1");
it's not working either : Error occurred while sending HTTP POSTC = 0.00
:(

MongoDB Atlas connection from mongoc (C) driver fails intermittently with 'No suitable servers found'

I'm using the MongoDB C driver (1.9.2) to connect to my Atlas Cluster (M5 using AWS).
My requests often succeeds, but I get this error about half the time. The longer I wait between requests, the more often the request succeeds.
I am always able to create a mongoc_client_t, but when the request fails, the drop, insert or read operation gets this error;
2019-12-30 23:10:50::dropCollection(): mongoc_collection_drop() failed code(13053)::
No suitable servers found: serverSelectionTimeoutMS expired: [Failed to receive length header from server. calling ismaster on 'xxxxx-shard-00-01-xxxxx.mongodb.net:27017'] [Failed to receive length header from server. calling ismaster on 'xxxxx-shard-00-00-xxxxx.mongodb.net:27017']
This is my (simplified) code;
I tried using a client pool, then switched to 'serverSelectionTryOnce=false' - they both get the error after timing out.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mongoc.h>
#include <bson.h>
#include <bcon.h>
#define ERROR -1
#define GOOD 0
typedef struct _MongoContext
{
mongoc_uri_t* uri;
mongoc_client_t* client;
mongoc_database_t* database;
mongoc_collection_t* collection;
bson_error_t error;
char* uriStr;
} MongoContext;
static const char* DEFAULT_URI = "mongodb+srv://<user>:<psswd>#<host>.mongodb.net/test?retryWrites=true&w=majority&serverSelectionTryOnce=false";
int getMongoContext(MongoContext* mctx, const char* dbname, const char* collname)
{
bson_error_t error;
mctx->uriStr = strdup(DEFAULT_URI);
mctx->uri = mongoc_uri_new_with_error(mctx->uriStr, &error);
if(!mctx->uri) {
fprintf(stderr, "getMongoContext(): Unable to parse URI(%s)\n(%s)", mctx->uriStr, error.message);
return ERROR;
}
// mongoc_client_pool_t *pool = mongoc_client_pool_new(mctx->uri);
// mongoc_client_pool_set_appname(pool, "my-mongo");
// mongoc_client_pool_set_error_api(pool, MONGOC_ERROR_API_VERSION_2);
// mctx->client = mongoc_client_pool_pop(pool);
mctx->client = mongoc_client_new_from_uri(mctx->uri);
if(!mctx->client) {
fprintf(stderr, "getMongoContext(): mongoc_client_new_from_uri() failed(%s)", error.message);
return ERROR;
}
mongoc_client_set_appname(mctx->client, "my-mongo");
mctx->database = mongoc_client_get_database(mctx->client, dbname);
if(mctx->database == NULL) {
fprintf(stderr, "getMongoContext(): invalid database(%s)", dbname);
return ERROR;
}
mctx->collection = mongoc_client_get_collection(mctx->client, dbname, collname);
if(mctx->collection == NULL) {
fprintf(stderr, "getMongoContext(): invalid collection(%s)", collname);
}
char* ptr = strchr(mctx->uriStr, '#');
fprintf(stderr, "getMongoContext(): connection made for host(%s), db(%s), collection(%s)\n", (ptr+1), dbname, collname);
return GOOD;
}
void closeMongoContext(MongoContext* mctx)
{
mongoc_collection_destroy(mctx->collection);
mongoc_database_destroy(mctx->database);
mongoc_uri_destroy(mctx->uri);
mongoc_client_destroy(mctx->client);
mongoc_cleanup();
free(mctx->uriStr);
}
/**
* read the collection in the given MongoContext
*/
int readCollection(MongoContext* mctx)
{
mongoc_cursor_t* cursor;
const bson_t* doc;
char* str;
bson_t* query = bson_new();
cursor = mongoc_collection_find_with_opts(mctx->collection, query, NULL, NULL);
if(cursor == NULL) {
fprintf(stderr, "readCollection(): Unable to retrieve a cursor for collection(%s)",
mongoc_collection_get_name(mctx->collection));
return ERROR;
}
while(mongoc_cursor_next(cursor, &doc)) {
str = bson_as_canonical_extended_json(doc, NULL);
printf("%s\n", str);
bson_free(str);
}
bson_destroy(query);
mongoc_cursor_destroy(cursor);
return GOOD;
}
int insertIntoCollection(MongoContext* mctx, const char* jsondata)
{
bson_t* doc;
bson_t reply;
bson_error_t error;
doc = bson_new_from_json((const uint8_t*)jsondata, -1, &error);
if(!doc) {
fprintf(stderr, "insertIntoCollection(): bson_new_from_json() failed (%s)\n", error.message);
return ERROR;
}
fprintf(stderr, "insertIntoCollection(): insert into collection(%s)\n", mongoc_collection_get_name(mctx->collection));
bool b = mongoc_collection_insert_one(mctx->collection, doc, NULL, &reply, &error);
if(!b) {
fprintf(stderr, "insertIntoCollection(): mongoc_collection_insert_one() failed (%s)\n", error.message);
}
bson_destroy(doc);
return GOOD;
}
int dropCollection(MongoContext* mctx)
{
bson_error_t error;
bool rval = mongoc_collection_drop(mctx->collection, &error);
if(!rval) {
fprintf(stderr, "dropCollection(): mongoc_collection_drop() failed code(%d)::%s", error.code, error.message);
fprintf(stderr, "dropCollection(): mongoc_collection_drop() failed on collection(%s) for(%s)",
mongoc_collection_get_name(mctx->collection), mctx->uriStr);
return (error.code == 26) ? GOOD : ERROR;
}
return GOOD;
}
int main(int argc, char* argv[])
{
mongoc_init();
MongoContext mctx = {0};
getMongoContext(&mctx, "my-db", "my-collection");
if(dropCollection(&mctx) == ERROR) {
exit(1);
}
printf("collection dropped...\n");
if(insertIntoCollection(&mctx, "{ \"hello\" : \"world\" }") == ERROR) {
exit(1);
}
printf("inserted into collection...\n");
if(readCollection(&mctx) == ERROR) {
exit(1);
}
closeMongoContext(&mctx);
}
In my case it was a version issue. I had to upgrade my C driver version to be compatible with the server.

Open file Error permission denied on macOS

hi I use bridging header include a hpp
but always output "Error permission denied"
My Derived Data is relative
I tried to key "chmod -R 777 ./" in Debug-iPhonesimulator
show the code:
bool CheckPath()
{
FILE *pfile = fopen("./__viewtest.txt","w");
if(pfile){
fclose(pfile);
return true;
}
printf("Error %s\n",strerror(errno));
return false;
}
it is always output "Error permission denied"
thanks a lot
I solved it
#include <unistd.h>
#include<iostream>
std::string GetCurrentWorkingDir( void ) {
char buff[FILENAME_MAX];
getcwd( buff, FILENAME_MAX );
std::string current_working_dir(buff);
return current_working_dir;
}
bool CheckPath()
{
std::string sPath = GetCurrentWorkingDir();
sPath += "Users/My/Desktop/WorkSpace/View/DerivedData/View/Build/Products/Debug-iphonesimulator/__viewtest.txt";
FILE *pfile = fopen(sPath.c_str(),"w");
if(pfile){
fclose(pfile);
return true;
}
printf(" %s, Path %s\n",strerror(errno), GetCurrentWorkingDir().c_str());
return false;
}

pci_disable_msi Oops Bug

I am trying to write a kernel module that will handle MSI interrupts for a PCIe device. I have written a simple skeleton outline for my driver currently and whenever I try to call 'pci_disable_msi(dev)' I get an unable to handle kernel NULL pointer dereference error. I am following along exactly as described from the /Documentation/PCI/MSI-HOWTO.txt and it seems to me that I should not be getting this error. Is this a bug or is my setup incorrect? Judging by the last print that occures, I am pretty sure that it is happening at the fpga_remove() when I call pci_disable_msi(). (Clearly this occures when I am removing the module)
static struct pci_driver fpga_driver = {
.name = "PCIe_test",
.id_table = fpga_dev_table,
.probe = fpga_probe,
.remove = fpga_remove,
.suspend = fpga_suspend,
.resume = fpga_resume,
};
static irqreturn_t fpga_isr(int irq, struct pci_dev *dev)
{
printk(KERN_NOTICE "THIS is the ISR\n");
return IRQ_HANDLED;
}
static int setup_MSI_interrupt(struct pci_dev *dev, int num_msi)
{
int result;
result = pci_enable_msi(dev);
if(result)
{
printk(KERN_WARNING "Could not enable MSI\n");
return result;
}
printk(KERN_NOTICE "MSI has been enabled\n");
printk(KERN_NOTICE "dev->irq line is %d", dev->irq);
result = request_irq(dev->irq, fpga_isr, IRQF_SHARED, fpga_driver.name, dev);
printk(KERN_NOTICE "Using IRQ num %d\n", dev->irq);
if (result) {
dev_err(&dev->dev, "Failed to allocate irq %d: %d\n", dev->irq, result);
goto exit1;
}
dev_info(&dev->dev, "FPGA using PCIe Interrupt\n");
return 0;
exit1:
return -1;
}
static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
printk(KERN_NOTICE "Probing driver\n");
switch(dev->vendor) {
case VENDOR://0x1708:
printk(KERN_NOTICE "Xilinx device found\n");
break;
default:
printk(KERN_NOTICE "Device found that does not match id: id = 0x%04X\n", dev->device);
};
int err = pci_enable_device(dev);
if (err) {
dev_err(&dev->dev, "Failed to enable FPGA PCI device (%d)\n", err);
goto exit;
}
err = setup_MSI_interrupt(dev, NUM_MSI);
if(err)
goto exit;
return 0;
exit:
return -1;
}
static void fpga_remove(struct pci_dev *dev)
{
printk(KERN_NOTICE "REMOVING IRQ # %d\n", dev->irq);
free_irq(dev->irq, dev);
printk(KERN_NOTICE "IRQ has been freed\n");
pci_disable_msi(dev); // This causes a NUll Pointer to be dereferenced but needs to be added
printk(KERN_NOTICE "MSI has been disabled\n");
}
static int __init fpga_init(void)
{
printk(KERN_NOTICE "Registering Driver\n");
return pci_register_driver(&fpga_driver);
return 0;
}
You should probably not use the struct pci_dev as void *dev_id parameter in the request_irq(...) and the free_irq(...) functions. Its important to call them with the right and the same unique dev_id parameter for the interrupt. Doing this not could cause the kernel panic at pci_disable_msi() on removing the module.
Read more here:
What is dev_id parameter in request_irq?

Add library into cascades

Hi I am developing an application to unzip files in blackberry10. For unzipping files I am using quazip library code I get from github. But I dont know how to add this library to my project can anybody please let me know how to add library to blackbery cascades.
To add a library to your BlackBerry 10 project in Momentics you just need to right click on the project and go to Configure->Add Library...
This will start the Add Library wizard where you can specify the path to your library. Just remember to update your .pro file. Instructions for doing this are in the wizard. If you're dynamically linking it you'll also need to update your bar-descriptor.xml so that the library is packaged in your BAR file as an asset.
I have successful experience in using quazip library in my project. Here are the steps you need to follow in order to get it working in your app:
1. Download a copy of zip archive from QuaZip home page
2. Copy the following files across into your project source folder:
qioapi.cpp
quazip.cpp
quazipfile.cpp
quazipnewinfo.cpp
unzip.c
zip.c
crypt.h
ioapi.h
quazipdir.h
quazipfile.h
quazipfileinfo.h
quazip_global.h
quazip.h
quazipnewinfo.h
unzip.h
zip.h
3. Create an utility class for handling archives:
Header file:
#ifndef ZIPPER_H_
#define ZIPPER_H_
#include <QObject>
#include <QDir>
#include "quazip.h"
#include "quazipfile.h"
class Zipper : public QObject {
Q_OBJECT
public:
Zipper() {}
virtual ~Zipper() {}
static bool extract(const QString & filePath, const QString & extDirPath, const QString & singleFileName = QString(""));
static bool archive(const QString & filePath, const QDir & dir, const QString & comment = QString(""));
Q_DISABLE_COPY(Zipper)
};
Source file:
#include <QFile>
#include <QDir>
#include "Zipper.h"
bool Zipper::extract(const QString & filePath, const QString & extDirPath, const QString & singleFileName) {
QuaZip zip(filePath);
if (!zip.open(QuaZip::mdUnzip)) {
qWarning("testRead(): zip.open(): %d", zip.getZipError());
return false;
}
zip.setFileNameCodec("IBM866");
qWarning("%d entries\n", zip.getEntriesCount());
qWarning("Global comment: %s\n", zip.getComment().toLocal8Bit().constData());
QuaZipFileInfo info;
QuaZipFile file(&zip);
QFile out;
QString name;
char c;
for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile()) {
if (!zip.getCurrentFileInfo(&info)) {
qWarning("testRead(): getCurrentFileInfo(): %d\n", zip.getZipError());
return false;
}
if (!singleFileName.isEmpty())
if (!info.name.contains(singleFileName))
continue;
if (!file.open(QIODevice::ReadOnly)) {
qWarning("testRead(): file.open(): %d", file.getZipError());
return false;
}
name = QString("%1/%2").arg(extDirPath).arg(file.getActualFileName());
if (file.getZipError() != UNZ_OK) {
qWarning("testRead(): file.getFileName(): %d", file.getZipError());
return false;
}
//out.setFileName("out/" + name);
qWarning ("using %s for output fileName", qPrintable(name));
out.setFileName(name);
// this will fail if "name" contains subdirectories, but we don't mind that
out.open(QIODevice::WriteOnly);
// Slow like hell (on GNU/Linux at least), but it is not my fault.
// Not ZIP/UNZIP package's fault either.
// The slowest thing here is out.putChar(c).
while (file.getChar(&c)) out.putChar(c);
out.close();
if (file.getZipError() != UNZ_OK) {
qWarning("testRead(): file.getFileName(): %d", file.getZipError());
return false;
}
if (!file.atEnd()) {
qWarning("testRead(): read all but not EOF");
return false;
}
file.close();
if (file.getZipError() != UNZ_OK) {
qWarning("testRead(): file.close(): %d", file.getZipError());
return false;
}
}
zip.close();
if (zip.getZipError() != UNZ_OK) {
qWarning("testRead(): zip.close(): %d", zip.getZipError());
return false;
}
return true;
}
bool Zipper::archive(const QString & filePath, const QDir & dir, const QString & comment) {
QuaZip zip(filePath);
zip.setFileNameCodec("IBM866");
if (!zip.open(QuaZip::mdCreate)) {
qDebug("testCreate(): zip.open(): %d", zip.getZipError());
return false;
}
if (!dir.exists()) {
qDebug("dir.exists(%s)=FALSE", qPrintable(dir.absolutePath()));
return false;
}
QFile inFile;
QStringList sl;
// what's this ??
// recurseAddDir(dir, sl);
QFileInfoList files;
foreach (QString fn, sl) files << QFileInfo(fn);
QuaZipFile outFile(&zip);
char c;
foreach(QFileInfo fileInfo, files) {
if (!fileInfo.isFile())
continue;
QString fileNameWithRelativePath = fileInfo.filePath().remove(0, dir.absolutePath().length() + 1);
inFile.setFileName(fileInfo.filePath());
if (!inFile.open(QIODevice::ReadOnly)) {
qDebug("testCreate(): inFile.open(): %s", qPrintable(inFile.errorString()));
return false;
}
if (!outFile.open(QIODevice::WriteOnly, QuaZipNewInfo(fileNameWithRelativePath, fileInfo.filePath()))) {
qDebug("testCreate(): outFile.open(): %s", qPrintable(outFile.getZipError()));
return false;
}
while (inFile.getChar(&c) && outFile.putChar(c));
if (outFile.getZipError() != UNZ_OK) {
qDebug("testCreate(): outFile.putChar(): %d", outFile.getZipError());
return false;
}
outFile.close();
if (outFile.getZipError() != UNZ_OK) {
qDebug("testCreate(): outFile.close(): %d", outFile.getZipError());
return false;
}
inFile.close();
}
if (!comment.isEmpty())
zip.setComment(comment);
zip.close();
if (zip.getZipError() != 0) {
qDebug("testCreate(): zip.close(): %d", zip.getZipError());
return false;
}
return true;
}
4. Then use it in your project like that:
bool rc = Zipper::extract(filePath, pathToUnpack);
qDebug("extracting %s", rc ? "success" : "failure");