diff --git a/src/backend-sqlite3.c b/src/backend-sqlite3.c index c89b32b..51a22aa 100644 --- a/src/backend-sqlite3.c +++ b/src/backend-sqlite3.c @@ -101,12 +101,18 @@ int SQLite_print_contents_subtree(sqlite3 *db, "name STRING, firstchild INTEGER, next INTEGER, parent INTEGER, numproviders INTEGER" /* struct headerList **provider; */ -#define SQLITE_TABLE_packages_files_rel "id INTEGER PRIMARY KEY, id_package INTEGER, id_file INTEGER, name STRING, version STRING, release STRING" +#define SQLITE_TABLE_packages_files_rel "id INTEGER PRIMARY KEY, id_package INTEGER, id_file INTEGER, "\ + "id_user INTEGER, id_group INTEGER, flags INTEGER, "\ + "name STRING, version STRING, release STRING" +#define SQLITE_TABLE_fileusers "id INTEGER PRIMARY KEY, name STRING" +#define SQLITE_TABLE_filegroups "id INTEGER PRIMARY KEY, name STRING" int generateSQLite_files(struct configTag* ct, sqlite3 *db, int arch) { int i; struct headerList* currpackage; + struct fileUserList *fileUser = ct->fileuserlist[arch]; + struct fileGroupList *fileGroup = ct->filegrouplist[arch]; snprintf(sqlite3_query, PATH_MAX, "packages_files_rel"); SQLite_init_table(db, sqlite3_query, SQLITE_TABLE_packages_files_rel); @@ -114,22 +120,60 @@ int generateSQLite_files(struct configTag* ct, sqlite3 *db, int arch) { snprintf(sqlite3_query, PATH_MAX, "files"); SQLite_init_table(db, sqlite3_query, SQLITE_TABLE_files); + snprintf(sqlite3_query, PATH_MAX, "fileusers"); + SQLite_init_table(db, sqlite3_query, SQLITE_TABLE_fileusers); + + snprintf(sqlite3_query, PATH_MAX, "filegroups"); + SQLite_init_table(db, sqlite3_query, SQLITE_TABLE_filegroups); + + while (fileUser) { + snprintf(sqlite3_query, PATH_MAX, "INSERT INTO fileusers VALUES(%d,?);", + fileUser->id); + if (sqlite3_prepare_v2(db, sqlite3_query, -1, &stmt, NULL)) { + fprintf(stderr, "ERROR: sqlite3_prepare_v2: %s (%s)\n", sqlite3_errmsg(db), sqlite3_query); + return 1; + } + sqlite3_bind_text(stmt, 1, fileUser->name, -1, SQLITE_STATIC); + if (sqlite3_step(stmt) != SQLITE_DONE) { + fprintf(stderr, "ERROR: sqlite3_step: %s (%s)\n", sqlite3_query, sqlite3_errmsg(db)); + return 3; + } + sqlite3_finalize(stmt); + fileUser = fileUser->next; + } + + while (fileGroup) { + snprintf(sqlite3_query, PATH_MAX, "INSERT INTO filegroups VALUES(%d,?);", + fileGroup->id); + if (sqlite3_prepare_v2(db, sqlite3_query, -1, &stmt, NULL)) { + fprintf(stderr, "ERROR: sqlite3_prepare_v2: %s (%s)\n", sqlite3_errmsg(db), sqlite3_query); + return 1; + } + sqlite3_bind_text(stmt, 1, fileGroup->name, -1, SQLITE_STATIC); + if (sqlite3_step(stmt) != SQLITE_DONE) { + fprintf(stderr, "ERROR: sqlite3_step: %s (%s)\n", sqlite3_query, sqlite3_errmsg(db)); + return 3; + } + sqlite3_finalize(stmt); + fileGroup = fileGroup->next; + } + SQLite_begin_transaction(db); if (SQLite_print_contents_subtree(db, ct->filetree[arch], ct, arch)) return 1; -/* if (sqlite3_finalize(stmt)) { - fprintf(stderr, "ERROR: SQLite: (%s) %s", sqlite3_query, sqlite3_errmsg(db)); - }*/ - currpackage = ct->headerlist[arch]; while (currpackage) { /* packages <-> files relations */ for (i = 0; i < currpackage->filenamecount; i++) { - snprintf(sqlite3_query, PATH_MAX, "INSERT INTO packages_files_rel VALUES(NULL,%d,%d,?,?,?);", + snprintf(sqlite3_query, PATH_MAX, "INSERT INTO packages_files_rel VALUES(NULL,%d,%d,%d,%d,%d,?,?,?);", currpackage->id, - currpackage->file[i]->id); + currpackage->file[i]->id, + currpackage->fileuser[i]->id, + currpackage->filegroup[i]->id, + currpackage->fileflags[i]); if (sqlite3_prepare_v2(db, sqlite3_query, -1, &stmt, NULL)) { fprintf(stderr, "ERROR: sqlite3_prepare_v2: %s (%s)\n", sqlite3_errmsg(db), sqlite3_query); + return 1; } sqlite3_bind_text(stmt, 1, currpackage->name, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 2, currpackage->version, -1, SQLITE_STATIC); @@ -174,6 +218,7 @@ int generateSQLite_provided(struct configTag* ct, sqlite3 *db, int arch) { sqlite3_bind_text(stmt, 1, provided->name, -1, SQLITE_STATIC); if (sqlite3_step(stmt) != SQLITE_DONE) { fprintf(stderr, "ERROR: SQLite: (%s) %s\n", sqlite3_query, sqlite3_errmsg(db)); + return 1; } sqlite3_finalize(stmt); provided = provided->next; @@ -279,6 +324,7 @@ generateSQLite_packages(struct configTag *ct, sqlite3 *db, int arch) { currpackage->sourceheader->id); if (sqlite3_prepare_v2(db, sqlite3_query, -1, &stmt, NULL)) { fprintf(stderr, "ERROR: SQLite: (%s) %s\n", sqlite3_query, sqlite3_errmsg(db)); + return 1; } sqlite3_bind_text(stmt, 1, currpackage->name, -1, SQLITE_STATIC); @@ -543,8 +589,8 @@ generateSQLite(struct configTag *ct) return 1; } - generateSQLite_packages(ct, db, i); - generateSQLite_provided(ct, db, i); + if (generateSQLite_packages(ct, db, i)) return 1; + if (generateSQLite_provided(ct, db, i)) return 1; sqlite3_close(db); } diff --git a/src/distromatic.c b/src/distromatic.c index 4fba577..4904abb 100644 --- a/src/distromatic.c +++ b/src/distromatic.c @@ -1203,10 +1203,10 @@ main(int argc, char *argv[]) } // if (genheader_mode) if (mode & MODE_SQLITE3) { - if (!quietmode) printf("Generating sqlite3 databases...\n"); + if (!quietmode) printf("Generating SQLite databases...\n"); logmsg(LOG_DEBUG,"generateSQLite3 - start"); if (generateSQLite(configtag)) { - logmsg(LOG_ERROR, "could not generate sqlite3 databases; aborting."); + logmsg(LOG_ERROR, "could not generate SQLite databases; aborting."); exit(1); } logmsg(LOG_DEBUG,"generateSQLite3 - done"); diff --git a/src/distroquery.c b/src/distroquery.c index f2d342b..2c2fc0f 100644 --- a/src/distroquery.c +++ b/src/distroquery.c @@ -190,6 +190,26 @@ void printTagsLine(const char* arch, const char* tag, const char* group, const c tag, group, license); } +char* expandFileFlags(long flags, char *buffer) { + int special = flags >> 9 & 7; + int type = flags >> 12; + + sprintf(buffer,"----------"); + if (special & 1) buffer[9]='t'; else if (flags & 1<<6) buffer[9]='x'; + if (flags & 1<<1) buffer[8]='w'; + if (flags & 1<<2) buffer[7]='r'; + if (special & 2) buffer[6]='s'; else if (flags & 1<<6) buffer[6]='x'; + if (flags & 1<<4) buffer[5]='w'; + if (flags & 1<<5) buffer[4]='r'; + if (special & 4) buffer[3]='s'; else if (flags & 1<<6) buffer[3]='x'; + if (flags & 1<<7) buffer[2]='w'; + if (flags & 1<<8) buffer[1]='r'; + if (type & 4) buffer[0]='d'; + else if (type & 2) buffer[0]='l'; + else if (type != 8) buffer[0] = (flags >> 12) + '0'; + return buffer; +} + char* resolveFilePath(sqlite3 *db, long id, char *buffer) { long currid = id; @@ -732,15 +752,23 @@ void printPackageData() { /* files list */ snprintf(dbname, PATH_MAX, "%s%s-%s-files.db", ct->repository_dir, ct->tag, query_arch); if (!sqlite3_open_v2(dbname, &dbf, SQLITE_OPEN_READONLY, NULL)) { - printf("

%s:
", _("Files list")); - snprintf(sql, PATH_MAX, "SELECT * FROM packages_files_rel WHERE name='%s'", query_package); + printf("

%s:
", _("Files list")); + snprintf(sql, PATH_MAX, "SELECT * FROM packages_files_rel,fileusers,filegroups WHERE" + " packages_files_rel.name='%s' AND" + " packages_files_rel.id_user=fileusers.id AND " + " packages_files_rel.id_group=filegroups.id", query_package); if (sqlite3_prepare_v2(dbf, sql, strlen(sql), &stmt1, NULL) == SQLITE_OK) { while (sqlite3_step(stmt1) == SQLITE_ROW) { - printf(" %s
", resolveFilePath(dbf, sqlite3_column_int(stmt1,sqlite3_find_column_id(stmt1, NULL, "id_file")), buffer)); + printf("", + sqlite3_column_text(stmt1,sqlite3_find_column_id(stmt1, "fileusers", "name")), + sqlite3_column_text(stmt1,sqlite3_find_column_id(stmt1, "filegroups", "name")), + expandFileFlags(sqlite3_column_int(stmt1,sqlite3_find_column_id(stmt1, NULL, "flags")), sql), + resolveFilePath(dbf, sqlite3_column_int(stmt1,sqlite3_find_column_id(stmt1, NULL, "id_file")), buffer)); } sqlite3_finalize(stmt1); } sqlite3_close(dbf); + printf("
%s%s%s%s
"); } sqlite3_close(dbs); } diff --git a/src/functions.c b/src/functions.c index 6b3f3d6..3adff94 100644 --- a/src/functions.c +++ b/src/functions.c @@ -153,7 +153,7 @@ struct configTag* read_configuration(const char *confFile) } else { configsection = CONF_REP_SECTION; - newconfigtag = malloc(sizeof(struct configTag)); + newconfigtag = calloc(1, sizeof(struct configTag)); if (!newconfigtag) { fprintf(stderr, "The system is out of memory\n"); return NULL; @@ -161,23 +161,11 @@ struct configTag* read_configuration(const char *confFile) newconfigtag->tag = (char *) strndup(&vartok[1], strlen(vartok) - 2); - newconfigtag->repository_dir = NULL; - newconfigtag->repository_source_dir = NULL; curraltrep = 0; - for (i = 0; irepository[i] = NULL; - newconfigtag->html_dir = NULL; - newconfigtag->download_prefix = NULL; - newconfigtag->download_dir = NULL; - newconfigtag->showfile_prefix = NULL; for (i = 0; iarch[i] = configdefaults.arch[i]; - newconfigtag->headerlist[i] = NULL; - newconfigtag->filetree[i]=NULL; - for (j = 0; jprovidedlist_idx[i][j]=NULL; } newconfigtag->configdefaults = &configdefaults; - newconfigtag->headersourcelist = NULL; if (configdefaults.html_basedir) { strncpy(buf, configdefaults.html_basedir, PATH_MAX); diff --git a/src/headerlist.c b/src/headerlist.c index fc22c70..99fe191 100644 --- a/src/headerlist.c +++ b/src/headerlist.c @@ -502,6 +502,7 @@ findOrCreateFileTreeBrother(struct fileTree* *first,char* findname, int arch) return currdir; } + struct fileTree* findOrCreateFileTreeEntry(struct fileTree* *first,char* findname, int arch) { @@ -539,6 +540,48 @@ findOrCreateFileTreeEntry(struct fileTree* *first,char* findname, int arch) return currdir; } +struct fileUserList* +findOrCreateFileUserListEntry(struct fileUserList* *first,char* name, int arch) +{ + static long id[ARCHS_MAX] = { 0, 0, 0, 0, 0 }; + struct fileUserList *curr = *first, *prev = NULL, *newf = NULL; + int i; + + while (curr && (i=strcmp(curr->name,name)) < 0) { + prev = curr; + curr = curr->next; + } + if (curr && (i == 0)) return curr; + newf = malloc(sizeof(struct fileUserList)); + newf->name = strdup(name); + newf->id = ++id[arch]; + if (prev) prev->next = newf; else *first = newf; + if (curr) newf->next = curr; else newf->next = NULL; + if (!*first) *first = newf; + return newf; +} + +struct fileGroupList* +findOrCreateFileGroupListEntry(struct fileGroupList* *first,char* name, int arch) +{ + static long id[ARCHS_MAX] = { 0, 0, 0, 0, 0 }; + struct fileGroupList *curr = *first, *prev = NULL, *newf = NULL; + int i; + + while (curr && ((i=strcmp(curr->name,name)) < 0)) { + prev = curr; + curr = curr->next; + } + if (curr && (i == 0)) return curr; + newf = malloc(sizeof(struct fileGroupList)); + newf->name = strdup(name); + newf->id = ++id[arch]; + if (prev) prev->next = newf; else *first = newf; + if (curr) newf->next = curr; else newf->next = NULL; + if (!*first) *first = newf; + return newf; +} + static long sourceid = 0; int @@ -553,7 +596,8 @@ addToSourceHeaderList(struct headerSourceList **headersourcelist, struct configT Header h; char filepath[bufsize + 1]; int n, j, arch, *dirindexes, filenamescount, dirnamescount; - char **basenames, **dirnames; + int_16 *fileflags; + char **basenames, **dirnames, **usernames, **groupnames; const char* errstr; int requirecount; char **requireversion, **requirename; @@ -602,8 +646,9 @@ addToSourceHeaderList(struct headerSourceList **headersourcelist, struct configT "%s: unable to read header (%s); skipping.",namelist[cnt]->d_name, errstr); } else { - getPackageFilenames(h, &dirindexes, &dirnames, &dirnamescount, - &basenames, &filenamescount); + getPackageFiles(h, &dirindexes, &dirnames, &dirnamescount, + &basenames, &filenamescount, + &usernames, &groupnames, &fileflags); newheadersourcelist = malloc(sizeof(struct headerSourceList)); @@ -797,11 +842,14 @@ addToHeaderList(struct configTag *ct, char *filename=NULL; long i ,j , k, n, altn[ALT_REPS_MAX]; int altrepository=0, obsoletecount, providecount, requirecount, - filenamecount, dirnamecount, *dirindex; + filenamecount, dirnamecount, + *dirindex; + int_16 *fileflags; char **obsoletename, **obsoleteversion, **providename, **provideversion, **requirename, **requireversion, - **basename, **dirname, **newversion; + **basename, **dirname, **newversion, + **fileusername, **filegroupname; const char* errstr; uint_32 *requireflags, *obsoleteflags, *provideflags; #if RPM_VERSION >= 0x040100 @@ -915,8 +963,9 @@ addToHeaderList(struct configTag *ct, &provideversion, &providecount); getPackageRequires(h, &requirename, &requireflags, &requireversion, &requirecount); - getPackageFilenames(h, &dirindex, &dirname, &dirnamecount, - &basename, &filenamecount); + getPackageFiles(h, &dirindex, &dirname, &dirnamecount, + &basename, &filenamecount, + &fileusername, &filegroupname, &fileflags); newheaderlist = malloc(sizeof(struct headerList)); if (newheaderlist == NULL) { @@ -1052,9 +1101,20 @@ addToHeaderList(struct configTag *ct, newheaderlist->file = malloc(sizeof(struct fileTree*) * filenamecount); + newheaderlist->fileflags = + malloc(sizeof(int_16 *) * filenamecount); + newheaderlist->fileuser = + malloc(sizeof(struct fileUserList *) * filenamecount); + newheaderlist->filegroup = + malloc(sizeof(char *) * filenamecount); for (j=0; jfile[j] = findOrCreateFileTreeEntry(&ct->filetree[arch],filename,arch); + newheaderlist->file[j] = findOrCreateFileTreeEntry(&ct->filetree[arch], filename, arch); + newheaderlist->fileflags[j] = fileflags[j]; + newheaderlist->fileuser[j] = findOrCreateFileUserListEntry(&ct->fileuserlist[arch], fileusername[j], arch); + free(fileusername[j]); + newheaderlist->filegroup[j] = findOrCreateFileGroupListEntry(&ct->filegrouplist[arch], filegroupname[j], arch); + free(filegroupname[j]); if (newheaderlist->file[j]->numproviders == 0) { newheaderlist->file[j]->numproviders++; newheaderlist->file[j]->provider=malloc(sizeof(struct headerList*)); diff --git a/src/include/distromatic.h b/src/include/distromatic.h index 6856ce5..cc7c081 100644 --- a/src/include/distromatic.h +++ b/src/include/distromatic.h @@ -37,6 +37,8 @@ struct configTag { struct headerSourceList *headersourcelist; struct providedList *providedlist_idx[ARCHS_MAX][PROVIDEDLIST_IDX_SIZE]; struct fileTree *filetree[ARCHS_MAX]; + struct fileUserList *fileuserlist[ARCHS_MAX]; + struct fileGroupList *filegrouplist[ARCHS_MAX]; struct headerStats stats; struct configTag *next; void *db[ARCHS_MAX + 1]; diff --git a/src/include/headerlist.h b/src/include/headerlist.h index ad2c534..d50a71a 100644 --- a/src/include/headerlist.h +++ b/src/include/headerlist.h @@ -44,6 +44,18 @@ struct fileTree { long id; }; +struct fileUserList { + char *name; + struct fileUserList* next; + long id; +}; + +struct fileGroupList { + char *name; + struct fileGroupList* next; + long id; +}; + struct warningList { char* text; struct warningList *next; @@ -81,6 +93,9 @@ struct headerList { struct providedList **provided; int filenamecount; struct fileTree **file; + int_16 *fileflags; + struct fileUserList **fileuser; + struct fileGroupList **filegroup; int recursed; struct requireList *requirelist; struct headerList *next, *nextbrother; diff --git a/src/include/rpmfunctions.h b/src/include/rpmfunctions.h index 974bf35..11f004d 100644 --- a/src/include/rpmfunctions.h +++ b/src/include/rpmfunctions.h @@ -45,10 +45,12 @@ int getPackageObsoletes( Header h, char ***obsoletename, uint_32 **obsoleteflags, char ***obsoleteversion, int *obsoletecount); -int getPackageFilenames( - Header h, int **dirindexes, - char ***dirnames, int *dirnamescount, - char ***basenames, int *filenamescount); +int +getPackageFiles(Header h, int **dirindexes, + char ***dirnames, int *dirnamescount, + char ***basenames, int *filenamescount, + char ***usernames, char ***groupnames, + int_16 **fileflags); int rpmnamecmp(char *filename1, char *filename2, int checkver); diff --git a/src/rpmfunctions.c b/src/rpmfunctions.c index 99675ae..8da5849 100644 --- a/src/rpmfunctions.c +++ b/src/rpmfunctions.c @@ -201,7 +201,7 @@ long long headerGetUIntEntry(Header h, const int tag) { break; case RPM_UINT32_TYPE: ret = *he->p.ui32p; - break; + break; case RPM_UINT64_TYPE: ret = *he->p.ui64p; break; @@ -227,20 +227,20 @@ void *headerGetUIntArrayEntry(Header h, const int tag, int *count) { *count = he->c; switch (he->t) { case RPM_UINT8_TYPE: - ret = memndup(he->p.ui8p, he->c * sizeof(he->p.ui8p)); + ret = memndup(he->p.ui8p, *count); break; case RPM_UINT16_TYPE: - ret = memndup(he->p.ui16p, he->c * sizeof(he->p.ui16p)); + ret = memndup(he->p.ui16p, *count * 2); break; case RPM_UINT32_TYPE: - ret = memndup(he->p.ui32p, he->c * sizeof(he->p.ui32p)); + ret = memndup(he->p.ui32p, *count * 4); //int i; //for (i=0; ic; i++) { // printf("%d ",((int_32 *)ret)[i]); //} - break; + break; case RPM_UINT64_TYPE: - ret = memndup(he->p.ui64p, he->c * sizeof(he->p.ui64p)); + ret = memndup(he->p.ui64p, *count * 8); break; default: ret = NULL; @@ -248,10 +248,10 @@ void *headerGetUIntArrayEntry(Header h, const int tag, int *count) { } } -//unsigned int i; -//for (i=0; i < he->c; i++) { -//fprintf(stderr," headerGetUIntArrayEntry tag:%d value:%ld\n", he->tag, ((rpmuint32_t*)ret)[i]); -//} +/*unsigned int i; +for (i=0; i < he->c; i++) { +fprintf(stderr," headerGetUIntArrayEntry tag:%d value:%ld\n", he->tag, ((rpmuint32_t*)ret)[i]); +}*/ he->p.ptr = _free(he->p.ptr); return ret; } @@ -290,9 +290,11 @@ getPackageObsoletes(Header h, char ***obsoletename, uint_32 **obsoleteflags, } int -getPackageFilenames(Header h, int **dirindexes, +getPackageFiles(Header h, int **dirindexes, char ***dirnames, int *dirnamescount, - char ***basenames, int *filenamescount) + char ***basenames, int *filenamescount, + char ***usernames, char ***groupnames, + int_16 **fileflags) { int count; @@ -300,6 +302,9 @@ getPackageFilenames(Header h, int **dirindexes, *dirindexes = headerGetUIntArrayEntry(h, RPMTAG_DIRINDEXES, &count); *dirnames = headerGetStringArrayEntry(h, RPMTAG_DIRNAMES, dirnamescount); *basenames = headerGetStringArrayEntry(h, RPMTAG_BASENAMES, filenamescount); + *usernames = headerGetStringArrayEntry(h, RPMTAG_FILEUSERNAME, &count); + *groupnames = headerGetStringArrayEntry(h, RPMTAG_FILEGROUPNAME, &count); + *fileflags = headerGetUIntArrayEntry(h, RPMTAG_FILEMODES, &count); return 0; }