[pacman-dev] [PATCH 3/3] Only extract new db entries

Xavier shiningxc at gmail.com
Mon Oct 12 09:29:45 EDT 2009


On Mon, Oct 12, 2009 at 3:03 PM, Henning Garus
<henning.garus at googlemail.com> wrote:
> On Sun, Oct 11, 2009 at 03:42:50PM +0200, Xavier Chantry wrote:
>> +/* create list of directories in db */
>> +static alpm_list_t *dirlist_from_fs(const char *syncdbpath)
>> +{
>> +     DIR *dbdir;
>> +     struct dirent *ent = NULL;
>> +     alpm_list_t *dirlist = NULL;
>> +     struct stat sbuf;
>> +     char path[PATH_MAX];
>> +
>> +     dbdir = opendir(syncdbpath);
>> +     if (dbdir != NULL) {
>> +             while((ent = readdir(dbdir)) != NULL) {
>> +                     char *name = ent->d_name;
>> +                     if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
>> +                             continue;
>> +                     }
>> +
>> +                     /* stat the entry, make sure it's a directory */
>> +                     snprintf(path, PATH_MAX, "%s%s", syncdbpath, name);
>> +                     if(stat(path, &sbuf) != 0 || !S_ISDIR(sbuf.st_mode)) {
>> +                             continue;
>> +                     }
>> +
>> +                     int len = strlen(name);
>> +                     char *entry = malloc(len + 2);
>
> Isn't MALLOC more appropriate here?
>

Probably :)

>> +                     strcpy(entry, name);
>> +                     entry[len] = '/';
>> +                     entry[len+1] = '\0';
>> +                     dirlist = alpm_list_add(dirlist, entry);
>> +             }
>> +     }
>> +     closedir(dbdir);
>> +
>> +     dirlist = alpm_list_msort(dirlist, alpm_list_count(dirlist), _alpm_str_cmp);
>> +     return(dirlist);
>> +}
>> +
>> +/* remove old directories from dbdir */
>> +static int remove_olddir(const char *syncdbpath, alpm_list_t *dirlist)
>> +{
>> +     alpm_list_t *i;
>> +     for (i = dirlist; i; i = i->next) {
>> +             const char *name = i->data;
>> +             char *dbdir;
>> +             int len = strlen(syncdbpath) + strlen(name) + 2;
>> +             MALLOC(dbdir, len, RET_ERR(PM_ERR_MEMORY, -1));
>> +             snprintf(dbdir, len, "%s%s", syncdbpath, name);
>> +             _alpm_log(PM_LOG_DEBUG, "removing: %s\n", dbdir);
>> +             if(_alpm_rmrf(dbdir) != 0) {
>> +                     _alpm_log(PM_LOG_ERROR, _("could not remove database directory %s\n"), dbdir);
>> +                     free(dbdir);
>> +                     RET_ERR(PM_ERR_DB_REMOVE, -1);
>> +             }
>> +             free(dbdir);
>> +     }
>> +     return(0);
>> +}
>> +
>>  /** Update a package database
>>   *
>>   * An update of the package database \a db will be attempted. Unless
>> @@ -229,27 +329,54 @@ int SYMEXPORT alpm_db_update(int force, pmdb_t *db)
>>               return(-1);
>>       } else {
>>               const char *syncdbpath = _alpm_db_path(db);
>> -             /* remove the old dir */
>> -             if(_alpm_rmrf(syncdbpath) != 0) {
>> -                     _alpm_log(PM_LOG_ERROR, _("could not remove database %s\n"), db->treename);
>> -                     RET_ERR(PM_ERR_DB_REMOVE, -1);
>> -             }
>> -
>> -             /* Cache needs to be rebuilt */
>> -             _alpm_db_free_pkgcache(db);
>>
>>               /* form the path to the db location */
>>               len = strlen(dbpath) + strlen(db->treename) + strlen(DBEXT) + 1;
>>               MALLOC(dbfilepath, len, RET_ERR(PM_ERR_MEMORY, -1));
>>               sprintf(dbfilepath, "%s%s" DBEXT, dbpath, db->treename);
>>
>> -             /* uncompress the sync database */
>> -             checkdbdir(db);
>> -             ret = _alpm_unpack(dbfilepath, syncdbpath, NULL, 0);
>> -             if(ret) {
>> -                     free(dbfilepath);
>> -                     RET_ERR(PM_ERR_SYSTEM, -1);
>> +             /* remove the old dir if forcing update */
>> +             if(force) {
>> +                     if(_alpm_rmrf(syncdbpath) != 0) {
>> +                             _alpm_log(PM_LOG_ERROR, _("could not remove database %s\n"), db->treename);
>> +                             RET_ERR(PM_ERR_DB_REMOVE, -1);
>> +                     }
>> +
>> +                     checkdbdir(db);
>> +
>> +                     ret = _alpm_unpack(dbfilepath, syncdbpath, NULL, 0);
>> +                     if(ret) {
>> +                             free(dbfilepath);
>> +                             RET_ERR(PM_ERR_SYSTEM, -1);
>> +                     }
>> +             } else {
>> +                     alpm_list_t *onlyold = NULL;
>> +                     alpm_list_t *onlynew = NULL;
>> +                     alpm_list_t *olddirlist = NULL;
>> +                     alpm_list_t *newdirlist = NULL;
>> +
>> +                     newdirlist = dirlist_from_tar(dbfilepath);
>> +                     olddirlist = dirlist_from_fs(syncdbpath);
>
> dirlist_from_tar could return NULL. dirlist_from_fs could as well if you
> error out on failing malloc (see above).
> I assume just moving on after failing to read the archive isn't really
> intended, since onlyold will contain all entries from olddirlist and
> onlynew will be empty, this would lead to an empty db.
>

Hmm. I think that these two functions can return NULL also in a non-error case.
The sync database in the filesystem could be empty.
And the new sync database tarball could be empty too (actually we just
patched repo-add to support that).

But yeah I will probably change the signature of these functions to
distinguish error and empty case.

>> +
>> +                     alpm_list_diff_sorted(olddirlist, newdirlist, _alpm_str_cmp, &onlyold, &onlynew);
>> +
>> +                     ret = remove_olddir(syncdbpath, onlyold);
>> +                     if(ret == 0) {
>> +                             checkdbdir(db);
>> +                             ret = _alpm_unpack(dbfilepath, syncdbpath, onlynew, 0);
>> +                     }
>> +
>> +                     alpm_list_free(olddirlist);
>> +                     alpm_list_free(newdirlist);
>> +                     FREELIST(onlyold);
>> +                     FREELIST(onlynew);
>
> Shouldn't this be the other way round? onlyold and onlynew contain a
> subset of the entries in olddirlist and newdirlist.
>

Yeah, that seems right too :P

Thanks for your review ! I will send a new patch ... when I can :)


More information about the pacman-dev mailing list