> On Apr 2, 2018, at 5:35 AM, Aleksei Nikiforov <darktemp...@altlinux.org> 
> wrote:
> 
> Hi
> 
> 30.03.2018 18:35, Jeff Johnson пишет:
>>> On Mar 30, 2018, at 10:11 AM, Aleksei Nikiforov <darktemp...@altlinux.org> 
>>> wrote:
>>> 
>>> Hi
>>> 
>>> 29.03.2018 15:55, Aleksei Nikiforov пишет:
>>>> Hi
>>>> 29.03.2018 15:51, Jeff Johnson пишет:
>>>>> 
>>>>> 
>>>>>> On Mar 29, 2018, at 4:46 AM, Aleksei Nikiforov <darktemp...@altlinux.org>
>>>>> 
>>>>> ...
>>>>> 
>>>>>>>>> Adding AUTOINSTALLED through a transaction like this is far more 
>>>>>>>>> complex than necessary, particularly since rpm itself does not need 
>>>>>>>>> nor use that tag for any purpose
>>>>>>>> I've looked at librpm API documentation a few moments ago and found 
>>>>>>>> rpmdbSetIteratorRewrite + rpmdbSetIteratorModified. Did you mean these 
>>>>>>>> interfaces or something else I missed which could be used for changing 
>>>>>>>> headers in rpm db?
>>>>>>> Yes, those interfaces. Note that those interfaces are traversed only in 
>>>>>>> the case of a replaced file, which only rarely happens (multilib and 
>>>>>>> sloppy packaging are the two common cases that come to mind).
>>>>>> 
>>>>> 
>>>>> Apologies for not being precise.
>>>>> 
>>>>> Within rpm code, those interfaces are traversed only in the case of a 
>>>>> replaced file, and
>>>>> hence might be considered "lightly tested" or buggy.
>>>>> 
>>>>>> Patch 2 is used to provide interface which can be used for 
>>>>>> implementation of utilities like 'apt-mark auto' or 'apt-mark manual'. 
>>>>>> In that case no files are changed, no packages are actually reinstalled, 
>>>>>> only 1 header tag value is changed (or added, if tag AUTOINSTALLED was 
>>>>>> missing).
>>>>>> 
>>>>>>>> As for doing it within transaction, why not? As far as I can see 
>>>>>>>> almost every action on RPM db is done on open transaction, including 
>>>>>>>> rpmtsRebuildDB and rpmdbSetIteratorRewrite + rpmdbSetIteratorModified. 
>>>>>>>> Atomicity and consistency of transaction wouldn't hurt either.
>>>>>>> Here are the reasons not to implement as you have done:
>>>>>>> 0) rpm transactions are atomic/consistent only within very narrow 
>>>>>>> meanings that have little to do with traditional meanings of ACID 
>>>>>>> database transactions. E.g. The underlying Berkeley DB uses a CDB, not 
>>>>>>> a transactional model. There are no logs nor rollbacks nor 
>>>>>>> commit/discard events. Atomicity is only within an exclusive fcntl 
>>>>>>> write lock, and consistency is only de facto, as in there is exactly 
>>>>>>> one add/del operation per transaction element, with no well defined way 
>>>>>>> to hide, say, an add/del operation until the rpm transaction is 
>>>>>>> committed.
>>>>>>> 1) the rpmte interfaces aren't all that useful or compelling as an API. 
>>>>>>> I can't think of any application that has used/needed access to rpmte 
>>>>>>> transaction elements, because applications already have the headers 
>>>>>>> from which the transaction was composed.
>>>>>>> 2) There isn't any known usage case within rpm for AUTOINSTALL, nor is 
>>>>>>> there any means to compute the value within rpm which has no depsolver.
>>>>>>> Why should rpm start managing apt+rpm (my guess at what alt is doing) 
>>>>>>> data? If apt wishes AUTOINSTALL, then apt, not rpm, should manage that 
>>>>>>> data, and there are already sufficient API calls to perform that 
>>>>>>> management task.
>>>>>> 
>>>>>> Yes, depsolver is external, outside of librpm, but it is desired to keep 
>>>>>> all information in one database, including AUTOINSTALL tag, and this tag 
>>>>>> may be needed to be changed after package installation.
>>>>>> 
>>>>>> How can it be implemented other way? If rpmdbSetIteratorRewrite + 
>>>>>> rpmdbSetIteratorModified only works when files are changed, then this 
>>>>>> wouldn't work for this use-case.
>>>>>> 
>>>>> 
>>>>> Just do what markReplacedFile() does, but in apt-mark, outside of rpm 
>>>>> code.
>>>>> 
>>>> Thanks for clarification, I'll try doing it and see if it works for me.
>>> 
>>> I've tried using rpmdbSetIteratorRewrite + rpmdbSetIteratorModified and it 
>>> didn't work for me.
>>> I've tried calling headerDel + headerPutUint32, headerGet + headerGetUint32 
>>> + writing new value to the pointed memory, headerMod. Every time it fails 
>>> to write modified header, function headerExport hits following condition:
>>> 
>> Hmmm ... here's some context:
>> There are 3 cases for tags in a header, named akin to stalagmite formation 
>> in a cave.
>> 1) within the immutable region created when building a package (aka "rock")
>> 2) appended to the immutable region (aka "dribble")
>> 3) newly added tag data (aka "drip").
>> When a header is unloaded, a "drip" is appended, and thereby becomes a 
>> "dribble" when next loaded from an rpmdb.
>> Newly added "drips" can be freely added/deleted until a header is unloaded 
>> (I.e. saved in the rpmdb), "dribbles" can be modified through the pointer 
>> (if careful), and changes
>> to the immutable region "rock" can be done.
>> Similar to changing file states in markReplacedFile(), AUTOINSTALLED is a 
>> "dribble" when retrieved from an rpmdb, and you can modify by 
>> headerGet(MINMEM) and changing the value directly through the returned 
>> pointer.
>> The data type of AUTOINSTALL from int32 to int8, same as file states, to 
>> avoid alignment/padding issues with tag data. That's what usually breaks in 
>> headerExport()
> 
> I've used rpmtdGetChar instead of headerGetUint32 and it finally worked as 
> expected. Thanks!

Good: that confirms that there is something screwy with "drip" alignment when 
unloading headers for re-writing through an iterator.

(aside)
I am not surprised: this was incredibly nasty code to implement way back when, 
and has never been used for anything but rewriting file states since. But is 
likely fixable with a little bit of work.

> I think patch 2 may be dropped since it's no longer required. But patch 1 
> looks still needed. Can patch 1 be merged?
> 
>>>    if (count != (rdlen + entry->info.count + drlen))
>>>        goto errxit;
>>>    }
>>> and returns NULL to function miFreeHeader.
>>> 
>> Can you get some values for those variables? My guess is that the problem is 
>> in darken computed across "dribbles" earlier in headerExport().
> 
> It's no longer relevant since it works now, but in case it might be needed 
> here are values I got before using rpmtdGetChar:
> 
> i = 0, count = 2408, rdlen = 3424, entry->info.count = 16, drlen = 156, sum = 
> 3596 (count != sum)
> 

Thanks!

>>> I was hitting similar issue when implementing current patches and worked 
>>> around it by making a copy of header and working with it:
>>> 
>>>    case TR_CHANGED:
>>>        tmp_h = rpmteDBHeader(te);
>>>        h = headerCopy(tmp_h);
>>>        headerFree(tmp_h);
>>>        break;
>>> But I can't find a way to modify header returned by rpmdbNextIterator() and 
>>> make rpmdbFreeIterator() successfully save changes, or a way to replace 
>>> whole header from rpmdbMatchIterator. Am I missing some way to modify or 
>>> replace header and successfully write changes to rpm db?
>>> 
>> An alternative approach is to retrieve the header, modify AUTOINSTALLED, and 
>> replace.
> 
> Is there an API to replace whole header? I didn't find any yet. I thought 
> about copying all tags to temporary header, changing values there as needed, 
> cleaning all tags from original header and copying modified tags back. I 
> didn't try doing it yet though.
> 

There is an API to retrieve the "immutable header region" which is exactly what 
was in the *.rpm package.

The immutable header region is the plaintext blob on which rpm 
digests/signatures are based. So changing the header (or changing a "rock" tag) 
isn't just deleting tags, the immutable header region is wired throughout rpm 
package security validation.

73 de Jeff
>> hth
>> 73 de Jeff
>>>>> 73
>>>>>>> 73 de Jeff
>>>>>>>> Best regards
>>>>>>>> Aleksei Nikifo
>>>> Best regards
>>>> Aleksei Nikiforov
>>>> _______________________________________________
>>>> Rpm-maint mailing list
>>>> Rpm-maint@lists.rpm.org
>>>> http://lists.rpm.org/mailman/listinfo/rpm-maint
>>> 
>>> Best regards
>>> Aleksei Nikiforov
> 
> Best regards
> Aleksei Nikiforov
_______________________________________________
Rpm-maint mailing list
Rpm-maint@lists.rpm.org
http://lists.rpm.org/mailman/listinfo/rpm-maint

Reply via email to