Please see the attached patches. I tried to split the patches logically into manageable sets. Unfortunately I made a minor mistake and I am afraid I will do something wrong to fix it. I merged two wrong patches. Fortunately it was three liner with 1 liner so it is not a big of the deal but I am really scared that I will do something wrong and loose the work I have done. So I hope it is Ok to send it as is.
0001--INI-Making-Coverity-happy.patch <- this is the patch I submitted earlier that I merged by mistake. I was supposed to merge it with patch 25 but picked the wrong one instead. Patch 25 addresses the real issue found by Coverity as mentioned in Stephen's review mail but it did not apply cleanly since it relies on some code from the patches in the middle.
0002--INI-Adding-missing-function-declararion.patch <- this is the patch that was rejected from the second set sent earlier. Fixed according to review comment.
0003--BUILD-Allow-trace-per-component.patch <- This patch allows tracing per component
The following set of patches introduces the merging of sections during the reading of the file: 0004--INI-New-error-codes-and-messages.patch 0005--INI-New-merge-flags.patch 0006--INI-Add-new-vars-to-parse-structure.patch 0007--INI-Add-save_error-function.patch 0008--INI-Change-parse_error-to-use-save_error.patch 0009--INI-Preparing-for-merging-sections.patch 0010--INI-Enhance-value-processing.patch 0011--INI-Use-section-line-number.patch 0012--INI-Refactor-section-processing.patch 0013--INI-Return-error-in-DETECT-mode.patch 0014--INI-New-test-files-for-section-merge.patch 0015--INI-Test-DETECT-mode-and-use-new-file.patch 0016--INI-Test-for-all-section-merge-modes.patch
Patches related porting of the meta data from old way of doing things to the new way of doing things: 0017--INI-Separate-close-and-destroy.patch 0018--INI-Function-to-reopen-file.patch 0019--INI-Metadata-collection-is-gone.patch 0020--INI-Check-access-function.patch 0021--INI-Avoid-double-free.patch <- patch related to 17 (missed check) 0022--INI-Function-to-check-for-changes.patch 0023--INI-Tests-for-access-and-changes.patch
0024--INI-Rename-error-print-function.patch <- rename error printing function for consistency with new interface
0025--INI-Initialize-variables-in-loops.patch <- Coverity issue addressed. Related to patch 0001.
0026--INI-Exposing-functions.patch <- Make some internal functions reusable
There is also patch 27. It is a piece of new functionality. It is a preview. Please see the comment before reviewing it. Do I need to split it into multiple patches or it is Ok as is? It is pretty big but all changes are in one file and logically related. The UNIT test is missing so I am not claiming it actually works as expected.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 01/03/2011 06:12 PM, Dmitri Pal wrote:
Please see the attached patches. I tried to split the patches logically into manageable sets. Unfortunately I made a minor mistake and I am afraid I will do something wrong to fix it. I merged two wrong patches. Fortunately it was three liner with 1 liner so it is not a big of the deal but I am really scared that I will do something wrong and loose the work I have done. So I hope it is Ok to send it as is.
0001--INI-Making-Coverity-happy.patch <- this is the patch I submitted earlier that I merged by mistake. I was supposed to merge it with patch 25 but picked the wrong one instead. Patch 25 addresses the real issue found by Coverity as mentioned in Stephen's review mail but it did not apply cleanly since it relies on some code from the patches in the middle.
I split this patch. I'm attaching the missing initializer patch. That gets an ack.
However, the 100078/79 fix is not correct. I did some digging and found the real problem. If you look at line 264 and 279 of ini_valueobj_ut.c, it's possible for other_create_test() to return EOK without having modified the vo variable. As a result, you will be passing the uninitialized value to modify_test(). So Coverity is right that there's a possibility of it passing a freed variable here.
So the Coverity fix gets a nack.
0002--INI-Adding-missing-function-declararion.patch <- this is the patch that was rejected from the second set sent earlier. Fixed according to review comment.
Ack.
0003--BUILD-Allow-trace-per-component.patch <- This patch allows tracing per component
Nack. Requiring a file doesn't make sense. Just add --enable-trace-ini, - --enable-trace-collection etc. flags.
The following set of patches introduces the merging of sections during the reading of the file: 0004--INI-New-error-codes-and-messages.patch
It would be better to use an enum here instead of #defines, then your last entry for ERR_MAXPARSE will always be one higher than your previous error message.
See sdap_basic_opt in src/providers/ldap/sdap.h in the SSSD source code for an example.
That said, there's nothing WRONG with this patch, so ack.
0005--INI-New-merge-flags.patch
I don't much like the idea of having flags that have overlapping bits without an obvious reason (0x0020 and 0x0030, for example), but since those are pre-existing, I'll leave them alone. Ack.
0006--INI-Add-new-vars-to-parse-structure.patch
Ack, though it seems to me that a memset to zero would be simpler than manually setting every struct member to zero manually.
0007--INI-Add-save_error-function.patch
Nack. It doesn't make sense to pass in an index value to an array local only to the function. That's not clean. It would be better to either pass in the const char * for the message, or at worst pass in an enum type that you would use to look up the matching error message.
0008--INI-Change-parse_error-to-use-save_error.patch
Nack. This will need to be updated to correspond to the changes for patch 0007.
0009--INI-Preparing-for-merging-sections.patch
Ack.
0010--INI-Enhance-value-processing.patch
Ack.
0011--INI-Use-section-line-number.patch
Ack.
0012--INI-Refactor-section-processing.patch
Nack. Please fix the formatting of the switch statement. There should be only one level of indent following the case tag.
0013--INI-Return-error-in-DETECT-mode.patch
Ack
0014--INI-New-test-files-for-section-merge.patch
Ack
0015--INI-Test-DETECT-mode-and-use-new-file.patch
Ack
0016--INI-Test-for-all-section-merge-modes.patch
Nack. Please fix random tabs in the indentation. Otherwise it looks fine.
I'll review the porting patches in a separate email. This should be enough to get you started in the meantime.
Patches related porting of the meta data from old way of doing things to the new way of doing things: 0017--INI-Separate-close-and-destroy.patch 0018--INI-Function-to-reopen-file.patch 0019--INI-Metadata-collection-is-gone.patch 0020--INI-Check-access-function.patch 0021--INI-Avoid-double-free.patch <- patch related to 17 (missed check) 0022--INI-Function-to-check-for-changes.patch 0023--INI-Tests-for-access-and-changes.patch
0024--INI-Rename-error-print-function.patch <- rename error printing function for consistency with new interface
0025--INI-Initialize-variables-in-loops.patch <- Coverity issue addressed. Related to patch 0001.
0026--INI-Exposing-functions.patch <- Make some internal functions reusable
There is also patch 27. It is a piece of new functionality. It is a preview. Please see the comment before reviewing it. Do I need to split it into multiple patches or it is Ok as is? It is pretty big but all changes are in one file and logically related. The UNIT test is missing so I am not claiming it actually works as expected.
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
- -- Stephen Gallagher RHCE 804006346421761
Delivering value year after year. Red Hat ranks #1 in value among software vendors. http://www.redhat.com/promo/vendor/
Thank you for the review. Questions/comments inline.
Stephen Gallagher wrote:
On 01/03/2011 06:12 PM, Dmitri Pal wrote:
Please see the attached patches. I tried to split the patches logically into manageable sets. Unfortunately I made a minor mistake and I am afraid I will do something wrong to fix it. I merged two wrong patches. Fortunately it was three liner with 1 liner so it is not a big of the deal but I am really scared that I will do something wrong and loose the work I have done. So I hope it is Ok to send it as is.
0001--INI-Making-Coverity-happy.patch <- this is the patch I submitted earlier that I merged by mistake. I was supposed to merge it with patch 25 but picked the wrong one instead. Patch 25 addresses the real issue found by Coverity as mentioned in Stephen's review mail but it did not apply cleanly since it relies on some code from the patches in the middle.
I split this patch. I'm attaching the missing initializer patch. That gets an ack.
However, the 100078/79 fix is not correct. I did some digging and found the real problem. If you look at line 264 and 279 of ini_valueobj_ut.c, it's possible for other_create_test() to return EOK without having modified the vo variable. As a result, you will be passing the uninitialized value to modify_test(). So Coverity is right that there's a possibility of it passing a freed variable here.
So the Coverity fix gets a nack.
As I understand the changes I made are still valid. They are just not enough. So the fix will be incremental. Right?
0003--BUILD-Allow-trace-per-component.patch <- This patch allows tracing per component
Nack. Requiring a file doesn't make sense. Just add --enable-trace-ini, --enable-trace-collection etc. flags.
This is exactly what I did not like to do and tried to avoid. It is more code on the configure script, more checks and less convenient to turn on and off becuase you can run the same configure command with one switch enabled from history and do "touch trace" & "rm trace" as needed in the directory you need. Saves a lot of typing for me :-) If you do not like the patch I will have to keep it as private patch as it is more convenient for me during development than the flags.
The following set of patches introduces the merging of sections during the reading of the file: 0004--INI-New-error-codes-and-messages.patch
It would be better to use an enum here instead of #defines, then your last entry for ERR_MAXPARSE will always be one higher than your previous error message.
See sdap_basic_opt in src/providers/ldap/sdap.h in the SSSD source code for an example.
That said, there's nothing WRONG with this patch, so ack.
Yes I know that enum would be stylistically better. May be you are right and I should switch to ENUM. I will open a ticket for that. https://fedorahosted.org/sssd/ticket/766
0005--INI-New-merge-flags.patch
I don't much like the idea of having flags that have overlapping bits without an obvious reason (0x0020 and 0x0030, for example), but since those are pre-existing, I'll leave them alone. Ack.
Can you please elaborate becuase I designed the whole set of flags to be overlapping on purpose. There are three ranges that address three use cases: 1) Flags that define how to merge values that are encountered within the same section [section] a=1 a=2 2) Flags that define how to merge values that are in a section that is segmented [section] a=1 ... [section] a=2 3) Flags that define how to merge sections But all three are related (especially case 2 & 3) so it makes sense to pass them in one variable
But if there are some concerns or I am missing something please explain.
0006--INI-Add-new-vars-to-parse-structure.patch
Ack, though it seems to me that a memset to zero would be simpler than manually setting every struct member to zero manually.
I dislike calloc. May be I am blowing on water. It is just matter of style. Tried to change this attitude and use calloc or memset - does not fit well with me. It is a little bit more code but sometimes more initialization is needed and habit of initializing each individual member pays off. This is the case when actually I missed it. Thanks to Coverity that found the issue.
0007--INI-Add-save_error-function.patch
Nack. It doesn't make sense to pass in an index value to an array local only to the function. That's not clean. It would be better to either pass in the const char * for the message, or at worst pass in an enum type that you would use to look up the matching error message.
Hm. Ok. I see how it violates the "defensive programming" paradigm. Old habits hard to get rid of. ;-)
0008--INI-Change-parse_error-to-use-save_error.patch
Nack. This will need to be updated to correspond to the changes for patch 0007.
0009--INI-Preparing-for-merging-sections.patch
Ack.
0010--INI-Enhance-value-processing.patch
Ack.
0011--INI-Use-section-line-number.patch
Ack.
0012--INI-Refactor-section-processing.patch
Nack. Please fix the formatting of the switch statement. There should be only one level of indent following the case tag.
0013--INI-Return-error-in-DETECT-mode.patch
Ack
0014--INI-New-test-files-for-section-merge.patch
Ack
0015--INI-Test-DETECT-mode-and-use-new-file.patch
Ack
0016--INI-Test-for-all-section-merge-modes.patch
Nack. Please fix random tabs in the indentation. Otherwise it looks fine.
I'll review the porting patches in a separate email. This should be enough to get you started in the meantime.
Patches related porting of the meta data from old way of doing things to the new way of doing things: 0017--INI-Separate-close-and-destroy.patch 0018--INI-Function-to-reopen-file.patch 0019--INI-Metadata-collection-is-gone.patch 0020--INI-Check-access-function.patch 0021--INI-Avoid-double-free.patch <- patch related to 17 (missed check) 0022--INI-Function-to-check-for-changes.patch 0023--INI-Tests-for-access-and-changes.patch
0024--INI-Rename-error-print-function.patch <- rename error printing function for consistency with new interface
0025--INI-Initialize-variables-in-loops.patch <- Coverity issue addressed. Related to patch 0001.
0026--INI-Exposing-functions.patch <- Make some internal functions
reusable
There is also patch 27. It is a piece of new functionality. It is a preview. Please see the comment before reviewing it. Do I need to split it into multiple patches or it is Ok as is? It is pretty big but all changes are in one file and logically related. The UNIT test is missing so I am not claiming it actually works as expected.
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
-------------------------
_______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 01/05/2011 02:13 PM, Dmitri Pal wrote:
Thank you for the review. Questions/comments inline.
Stephen Gallagher wrote:
On 01/03/2011 06:12 PM, Dmitri Pal wrote:
Please see the attached patches. I tried to split the patches logically into manageable sets. Unfortunately I made a minor mistake and I am afraid I will do something wrong to fix it. I merged two wrong patches. Fortunately it was three liner with 1 liner so it is not a big of the deal but I am really scared that I will do something wrong and loose the work I have done. So I hope it is Ok to send it as is.
0001--INI-Making-Coverity-happy.patch <- this is the patch I submitted earlier that I merged by mistake. I was supposed to merge it with patch 25 but picked the wrong one instead. Patch 25 addresses the real issue found by Coverity as mentioned in Stephen's review mail but it did not apply cleanly since it relies on some code from the patches in the middle.
I split this patch. I'm attaching the missing initializer patch. That gets an ack.
However, the 100078/79 fix is not correct. I did some digging and found the real problem. If you look at line 264 and 279 of ini_valueobj_ut.c, it's possible for other_create_test() to return EOK without having modified the vo variable. As a result, you will be passing the uninitialized value to modify_test(). So Coverity is right that there's a possibility of it passing a freed variable here.
So the Coverity fix gets a nack.
As I understand the changes I made are still valid. They are just not enough. So the fix will be incremental. Right?
Well, they're "valid", but they're not accomplishing anything at all. In general, I nack no-op patches :)
0003--BUILD-Allow-trace-per-component.patch <- This patch allows tracing per component
Nack. Requiring a file doesn't make sense. Just add --enable-trace-ini, --enable-trace-collection etc. flags.
This is exactly what I did not like to do and tried to avoid. It is more code on the configure script, more checks and less convenient to turn on and off becuase you can run the same configure command with one switch enabled from history and do "touch trace" & "rm trace" as needed in the directory you need. Saves a lot of typing for me :-) If you do not like the patch I will have to keep it as private patch as it is more convenient for me during development than the flags.
I still vote nack, as I don't like the approach.
The following set of patches introduces the merging of sections during the reading of the file: 0004--INI-New-error-codes-and-messages.patch
It would be better to use an enum here instead of #defines, then your last entry for ERR_MAXPARSE will always be one higher than your previous error message.
See sdap_basic_opt in src/providers/ldap/sdap.h in the SSSD source code for an example.
That said, there's nothing WRONG with this patch, so ack.
Yes I know that enum would be stylistically better. May be you are right and I should switch to ENUM. I will open a ticket for that. https://fedorahosted.org/sssd/ticket/766
Thanks.
0005--INI-New-merge-flags.patch
I don't much like the idea of having flags that have overlapping bits without an obvious reason (0x0020 and 0x0030, for example), but since those are pre-existing, I'll leave them alone. Ack.
Can you please elaborate becuase I designed the whole set of flags to be overlapping on purpose. There are three ranges that address three use cases:
- Flags that define how to merge values that are encountered within the
same section [section] a=1 a=2 2) Flags that define how to merge values that are in a section that is segmented [section] a=1 ... [section] a=2 3) Flags that define how to merge sections But all three are related (especially case 2 & 3) so it makes sense to pass them in one variable
But if there are some concerns or I am missing something please explain.
#define INI_MV1S_OVERWRITE 0x0000 #define INI_MV1S_ERROR 0x0001 #define INI_MV1S_PRESERVE 0x0002 #define INI_MV1S_ALLOW 0x0003 #define INI_MV1S_DETECT 0x0004
I don't like that on a bitwise compare, if you do: var = INI_MV1S_ALLOW;
then
if (var & INI_MV1S_ERROR) { } would be true. This isn't how flags are supposed to work. You're using these more like an enum. It would be better to define them as such (and not call them "flags" if that's what you're trying to do.
Calling them flags implies that you would expect to be able to do:
var = INI_MV1S_OVERWRITE | INI_MV1S_OVERWRITE;
And have both of those be active.
0006--INI-Add-new-vars-to-parse-structure.patch
Ack, though it seems to me that a memset to zero would be simpler than manually setting every struct member to zero manually.
I dislike calloc. May be I am blowing on water. It is just matter of style. Tried to change this attitude and use calloc or memset - does not fit well with me. It is a little bit more code but sometimes more initialization is needed and habit of initializing each individual member pays off. This is the case when actually I missed it. Thanks to Coverity that found the issue.
Right, but memsetting to zero guarantees that everything is intialized. Like I said, the patch is acked, but it's not my favorite style :)
- -- Stephen Gallagher RHCE 804006346421761
Delivering value year after year. Red Hat ranks #1 in value among software vendors. http://www.redhat.com/promo/vendor/
0003--BUILD-Allow-trace-per-component.patch <- This patch allows
tracing
per component
Nack. Requiring a file doesn't make sense. Just add --enable-trace-ini, --enable-trace-collection etc. flags.
This is exactly what I did not like to do and tried to avoid. It is more code on the configure script, more checks and less convenient to turn on and off becuase you can run the same configure command with one switch enabled from history and do "touch trace" & "rm trace" as needed in the directory you need. Saves a lot of typing for me :-) If you do not like the patch I will have to keep it as private patch as it is more convenient for me during development than the flags.
I still vote nack, as I don't like the approach.
So this is the dead lock becuase I like the approach and do not like yours. How we are going to resolve it?
0005--INI-New-merge-flags.patch
I don't much like the idea of having flags that have overlapping bits without an obvious reason (0x0020 and 0x0030, for example), but since those are pre-existing, I'll leave them alone. Ack.
Can you please elaborate becuase I designed the whole set of flags to be overlapping on purpose. There are three ranges that address three use cases:
- Flags that define how to merge values that are encountered within the
same section [section] a=1 a=2 2) Flags that define how to merge values that are in a section that is segmented [section] a=1 ... [section] a=2 3) Flags that define how to merge sections But all three are related (especially case 2 & 3) so it makes sense to pass them in one variable
But if there are some concerns or I am missing something please explain.
#define INI_MV1S_OVERWRITE 0x0000 #define INI_MV1S_ERROR 0x0001 #define INI_MV1S_PRESERVE 0x0002 #define INI_MV1S_ALLOW 0x0003 #define INI_MV1S_DETECT 0x0004
I don't like that on a bitwise compare, if you do: var = INI_MV1S_ALLOW;
then
if (var & INI_MV1S_ERROR) { } would be true. This isn't how flags are supposed to work. You're using these more like an enum. It would be better to define them as such (and not call them "flags" if that's what you're trying to do.
Calling them flags implies that you would expect to be able to do:
var = INI_MV1S_OVERWRITE | INI_MV1S_OVERWRITE;
And have both of those be active.
I view it differently. Within the range they are mutually exclusive but they are flags since I expect it to be used in a following way:
var = INI_MS_MERGE | INI_MV1S_OVERWRITE | INI_MV2S_OVERWRITE;
Do you have a better way of accomplishing what I am trying to do?
_______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 01/05/2011 03:40 PM, Dmitri Pal wrote:
0003--BUILD-Allow-trace-per-component.patch <- This patch allows
tracing
per component
Nack. Requiring a file doesn't make sense. Just add --enable-trace-ini, --enable-trace-collection etc. flags.
This is exactly what I did not like to do and tried to avoid. It is more code on the configure script, more checks and less convenient to turn on and off becuase you can run the same configure command with one switch enabled from history and do "touch trace" & "rm trace" as needed in the directory you need. Saves a lot of typing for me :-) If you do not like the patch I will have to keep it as private patch as it is more convenient for me during development than the flags.
I still vote nack, as I don't like the approach.
So this is the dead lock becuase I like the approach and do not like yours. How we are going to resolve it?
Ultimately, it's your project, not mine. You have commit privilege and full discretion on when to use it. You asked for my review comments. You don't have to listen to them :)
0005--INI-New-merge-flags.patch
I don't much like the idea of having flags that have overlapping bits without an obvious reason (0x0020 and 0x0030, for example), but since those are pre-existing, I'll leave them alone. Ack.
Can you please elaborate becuase I designed the whole set of flags to be overlapping on purpose. There are three ranges that address three use cases:
- Flags that define how to merge values that are encountered within the
same section [section] a=1 a=2 2) Flags that define how to merge values that are in a section that is segmented [section] a=1 ... [section] a=2 3) Flags that define how to merge sections But all three are related (especially case 2 & 3) so it makes sense to pass them in one variable
But if there are some concerns or I am missing something please explain.
#define INI_MV1S_OVERWRITE 0x0000 #define INI_MV1S_ERROR 0x0001 #define INI_MV1S_PRESERVE 0x0002 #define INI_MV1S_ALLOW 0x0003 #define INI_MV1S_DETECT 0x0004
I don't like that on a bitwise compare, if you do: var = INI_MV1S_ALLOW;
then
if (var & INI_MV1S_ERROR) { } would be true. This isn't how flags are supposed to work. You're using these more like an enum. It would be better to define them as such (and not call them "flags" if that's what you're trying to do.
Calling them flags implies that you would expect to be able to do:
var = INI_MV1S_OVERWRITE | INI_MV1S_OVERWRITE;
And have both of those be active.
I view it differently. Within the range they are mutually exclusive but they are flags since I expect it to be used in a following way:
var = INI_MS_MERGE | INI_MV1S_OVERWRITE | INI_MV2S_OVERWRITE;
Do you have a better way of accomplishing what I am trying to do?
I think this would be better served if var was:
struct ini_struct { enum ms_cmd ms; enum mv1s_cmd mv1s; enum mv2s_cmd mv2s; }
This would guarantee the mutual exclusivity.
- -- Stephen Gallagher RHCE 804006346421761
Delivering value year after year. Red Hat ranks #1 in value among software vendors. http://www.redhat.com/promo/vendor/
Stephen Gallagher wrote:
On 01/05/2011 03:40 PM, Dmitri Pal wrote:
0003--BUILD-Allow-trace-per-component.patch <- This patch allows
tracing
per component
Nack. Requiring a file doesn't make sense. Just add
--enable-trace-ini,
--enable-trace-collection etc. flags.
This is exactly what I did not like to do and tried to avoid. It
is more
code on the configure script, more checks and less convenient to
turn on
and off becuase you can run the same configure command with one switch enabled from history and do "touch trace" & "rm trace" as needed
in the
directory you need. Saves a lot of typing for me :-) If you do not like the patch I will have to keep it as private
patch as
it is more convenient for me during development than the flags.
I still vote nack, as I don't like the approach.
So this is the dead lock becuase I like the approach and do not like yours. How we are going to resolve it?
Ultimately, it's your project, not mine. You have commit privilege and full discretion on when to use it. You asked for my review comments. You don't have to listen to them :)
Nack. I think we need to come to some terms and find consensus. I will definitely not push it over your head using my privilege. I agree that what you suggest is logical and consistent with how things are done. The problem is that it does not help me much. I will keep patch in my tree for now.
0005--INI-New-merge-flags.patch
I don't much like the idea of having flags that have overlapping bits without an obvious reason (0x0020 and 0x0030, for example), but since those are pre-existing, I'll leave them alone. Ack.
Can you please elaborate becuase I designed the whole set of flags
to be
overlapping on purpose. There are three ranges that address three use cases:
- Flags that define how to merge values that are encountered
within the
same section [section] a=1 a=2 2) Flags that define how to merge values that are in a section that is segmented [section] a=1 ... [section] a=2 3) Flags that define how to merge sections But all three are related (especially case 2 & 3) so it makes sense to pass them in one variable But if there are some concerns or I am missing something please
explain.
#define INI_MV1S_OVERWRITE 0x0000 #define INI_MV1S_ERROR 0x0001 #define INI_MV1S_PRESERVE 0x0002 #define INI_MV1S_ALLOW 0x0003 #define INI_MV1S_DETECT 0x0004
I don't like that on a bitwise compare, if you do: var = INI_MV1S_ALLOW;
then
if (var & INI_MV1S_ERROR) { } would be true. This isn't how flags are supposed to work. You're using these more like an enum. It would be better to define them as such (and not call them "flags" if that's what you're trying to do.
Calling them flags implies that you would expect to be able to do:
var = INI_MV1S_OVERWRITE | INI_MV1S_OVERWRITE;
And have both of those be active.
I view it differently. Within the range they are mutually exclusive but they are flags since I expect it to be used in a following way:
var = INI_MS_MERGE | INI_MV1S_OVERWRITE | INI_MV2S_OVERWRITE;
Do you have a better way of accomplishing what I am trying to do?
I think this would be better served if var was:
struct ini_struct { enum ms_cmd ms; enum mv1s_cmd mv1s; enum mv2s_cmd mv2s; }
This would guarantee the mutual exclusivity.
I really do not like this approach. It is too heavy weighted. I will think more about this though. May be I will use union and package it all into 32 bit integer. https://fedorahosted.org/sssd/ticket/767
_______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
On Wed, Jan 05, 2011 at 04:03:38PM -0500, Dmitri Pal wrote:
Stephen Gallagher wrote:
On 01/05/2011 03:40 PM, Dmitri Pal wrote:
> 0003--BUILD-Allow-trace-per-component.patch <- This patch allows
tracing
> per component Nack. Requiring a file doesn't make sense. Just add
--enable-trace-ini,
--enable-trace-collection etc. flags.
This is exactly what I did not like to do and tried to avoid. It
is more
code on the configure script, more checks and less convenient to
turn on
and off becuase you can run the same configure command with one switch enabled from history and do "touch trace" & "rm trace" as needed
in the
directory you need. Saves a lot of typing for me :-) If you do not like the patch I will have to keep it as private
patch as
it is more convenient for me during development than the flags.
I still vote nack, as I don't like the approach.
So this is the dead lock becuase I like the approach and do not like yours. How we are going to resolve it?
Ultimately, it's your project, not mine. You have commit privilege and full discretion on when to use it. You asked for my review comments. You don't have to listen to them :)
Nack. I think we need to come to some terms and find consensus. I will definitely not push it over your head using my privilege. I agree that what you suggest is logical and consistent with how things are done. The problem is that it does not help me much. I will keep patch in my tree for now.
To enlarge the quorum I throw in my opinion here. In general I agree with Stephen because the file approach is quite unusual and needs to be well documented so that other developers can use it. You might also want to use $builddir instead of $srcdir to allow a separate build directory.
But I would like to suggest another approach which might be even easier to use. You can introduce a make target like 'trace' or 'devel' which will build everything with tracing enabled. This way you do not even have to rerun configure to enable tracing.
bye, Sumit
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 01/06/2011 03:02 AM, Sumit Bose wrote:
On Wed, Jan 05, 2011 at 04:03:38PM -0500, Dmitri Pal wrote:
Stephen Gallagher wrote:
On 01/05/2011 03:40 PM, Dmitri Pal wrote:
>> 0003--BUILD-Allow-trace-per-component.patch <- This patch allows
tracing
>> per component > Nack. Requiring a file doesn't make sense. Just add
--enable-trace-ini,
> --enable-trace-collection etc. flags. This is exactly what I did not like to do and tried to avoid. It
is more
code on the configure script, more checks and less convenient to
turn on
and off becuase you can run the same configure command with one switch enabled from history and do "touch trace" & "rm trace" as needed
in the
directory you need. Saves a lot of typing for me :-) If you do not like the patch I will have to keep it as private
patch as
it is more convenient for me during development than the flags.
I still vote nack, as I don't like the approach.
So this is the dead lock becuase I like the approach and do not like yours. How we are going to resolve it?
Ultimately, it's your project, not mine. You have commit privilege and full discretion on when to use it. You asked for my review comments. You don't have to listen to them :)
Nack. I think we need to come to some terms and find consensus. I will definitely not push it over your head using my privilege. I agree that what you suggest is logical and consistent with how things are done. The problem is that it does not help me much. I will keep patch in my tree for now.
To enlarge the quorum I throw in my opinion here. In general I agree with Stephen because the file approach is quite unusual and needs to be well documented so that other developers can use it. You might also want to use $builddir instead of $srcdir to allow a separate build directory.
But I would like to suggest another approach which might be even easier to use. You can introduce a make target like 'trace' or 'devel' which will build everything with tracing enabled. This way you do not even have to rerun configure to enable tracing.
That's a good idea. The trace level could then be set by environment variable as well.
e.g. ./configure COL_TRACE=3 make devel
And this would tell it to pass -DTRACE_LEVEL=3 to the COLLECTION_CFLAGS
- -- Stephen Gallagher RHCE 804006346421761
Delivering value year after year. Red Hat ranks #1 in value among software vendors. http://www.redhat.com/promo/vendor/
Stephen Gallagher wrote:
On 01/06/2011 03:02 AM, Sumit Bose wrote:
On Wed, Jan 05, 2011 at 04:03:38PM -0500, Dmitri Pal wrote:
Stephen Gallagher wrote:
On 01/05/2011 03:40 PM, Dmitri Pal wrote:
>>> 0003--BUILD-Allow-trace-per-component.patch <- This patch allows tracing >>> per component >> Nack. Requiring a file doesn't make sense. Just add
--enable-trace-ini,
>> --enable-trace-collection etc. flags. > This is exactly what I did not like to do and tried to avoid. It
is more
> code on the configure script, more checks and less convenient to
turn on
> and off becuase you can run the same configure command with one
switch
> enabled from history and do "touch trace" & "rm trace" as needed
in the
> directory you need. > Saves a lot of typing for me :-) > If you do not like the patch I will have to keep it as private
patch as
> it is more convenient for me during development than the flags. I still vote nack, as I don't like the approach.
So this is the dead lock becuase I like the approach and do not like yours. How we are going to resolve it?
Ultimately, it's your project, not mine. You have commit privilege and full discretion on when to use it. You asked for my review
comments. You
don't have to listen to them :)
Nack. I think we need to come to some terms and find consensus. I will definitely not push it over your head using my privilege. I agree that what you suggest is logical and consistent with how things are done. The problem is that it does not help me much. I will keep patch in my tree for now.
To enlarge the quorum I throw in my opinion here. In general I agree with Stephen because the file approach is quite unusual and needs to be well documented so that other developers can use it. You might also want to use $builddir instead of $srcdir to allow a separate build directory.
But I would like to suggest another approach which might be even easier to use. You can introduce a make target like 'trace' or 'devel' which will build everything with tracing enabled. This way you do not even have to rerun configure to enable tracing.
That's a good idea. The trace level could then be set by environment variable as well.
e.g. ./configure COL_TRACE=3 make devel
And this would tell it to pass -DTRACE_LEVEL=3 to the COLLECTION_CFLAGS
I will look into this later.
_______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
0001--INI-Making-Coverity-happy.patch <- this is the patch I submitted earlier that I merged by mistake. I was supposed to merge it with patch 25 but picked the wrong one instead. Patch 25 addresses the real issue found by Coverity as mentioned in Stephen's review mail but it did not apply cleanly since it relies on some code from the patches in the middle.
I split this patch. I'm attaching the missing initializer patch. That gets an ack.
I am missing something. If you split the patch should there have been two patches? You sent just one.
Thanks Dmitri
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 01/06/2011 08:36 AM, Dmitri Pal wrote:
0001--INI-Making-Coverity-happy.patch <- this is the patch I submitted earlier that I merged by mistake. I was supposed to merge it with patch 25 but picked the wrong one instead. Patch 25 addresses the real issue found by Coverity as mentioned in Stephen's review mail but it did not apply cleanly since it relies on some code from the patches in the middle.
I split this patch. I'm attaching the missing initializer patch. That gets an ack.
I am missing something. If you split the patch should there have been two patches? You sent just one.
I didn't send the other one because I had nacked it.
- -- Stephen Gallagher RHCE 804006346421761
Delivering value year after year. Red Hat ranks #1 in value among software vendors. http://www.redhat.com/promo/vendor/
On 01/05/2011 01:19 PM, Stephen Gallagher wrote:
On 01/03/2011 06:12 PM, Dmitri Pal wrote:
Please see the attached patches. I tried to split the patches logically into manageable sets. Unfortunately I made a minor mistake and I am afraid I will do something wrong to fix it. I merged two wrong patches. Fortunately it was three liner with 1 liner so it is not a big of the deal but I am really scared that I will do something wrong and loose the work I have done. So I hope it is Ok to send it as is.
0001--INI-Making-Coverity-happy.patch <- this is the patch I submitted earlier that I merged by mistake. I was supposed to merge it with patch 25 but picked the wrong one instead. Patch 25 addresses the real issue found by Coverity as mentioned in Stephen's review mail but it did not apply cleanly since it relies on some code from the patches in the middle.
I split this patch. I'm attaching the missing initializer patch. That gets an ack.
However, the 100078/79 fix is not correct. I did some digging and found the real problem. If you look at line 264 and 279 of ini_valueobj_ut.c, it's possible for other_create_test() to return EOK without having modified the vo variable. As a result, you will be passing the uninitialized value to modify_test(). So Coverity is right that there's a possibility of it passing a freed variable here.
So the Coverity fix gets a nack.
I realized what the problem is. See the first patch.
0002--INI-Adding-missing-function-declararion.patch <- this is the patch that was rejected from the second set sent earlier. Fixed according to review comment.
Dropped. I think Jakub fixed it.
Ack.
0003--BUILD-Allow-trace-per-component.patch <- This patch allows tracing per component
Nack. Requiring a file doesn't make sense. Just add --enable-trace-ini, --enable-trace-collection etc. flags.
Dropped for now
The following set of patches introduces the merging of sections during the reading of the file: 0004--INI-New-error-codes-and-messages.patch
It would be better to use an enum here instead of #defines, then your last entry for ERR_MAXPARSE will always be one higher than your previous error message.
See sdap_basic_opt in src/providers/ldap/sdap.h in the SSSD source code for an example.
That said, there's nothing WRONG with this patch, so ack.
Attached as is. The ticket is open.
0005--INI-New-merge-flags.patch
I don't much like the idea of having flags that have overlapping bits without an obvious reason (0x0020 and 0x0030, for example), but since those are pre-existing, I'll leave them alone. Ack.
As I mentioned earlier I will reconsider however for now it is unchanged.
0006--INI-Add-new-vars-to-parse-structure.patch
Ack, though it seems to me that a memset to zero would be simpler than manually setting every struct member to zero manually.
Unchanged
0007--INI-Add-save_error-function.patch
Nack. It doesn't make sense to pass in an index value to an array local only to the function. That's not clean. It would be better to either pass in the const char * for the message, or at worst pass in an enum type that you would use to look up the matching error message.
Modified. Const char * is passed in.
0008--INI-Change-parse_error-to-use-save_error.patch
Nack. This will need to be updated to correspond to the changes for patch 0007.
Updated to reflect the above patch.
0009--INI-Preparing-for-merging-sections.patch
Ack.
Unchanged
0010--INI-Enhance-value-processing.patch
Ack.
Unchanged
0011--INI-Use-section-line-number.patch
Ack.
Unchanged
0012--INI-Refactor-section-processing.patch
Nack. Please fix the formatting of the switch statement. There should be only one level of indent following the case tag.
Done
0013--INI-Return-error-in-DETECT-mode.patch
Ack
Unchanged
0014--INI-New-test-files-for-section-merge.patch
Ack
Unchanged
0015--INI-Test-DETECT-mode-and-use-new-file.patch
Ack
Unchanged
0016--INI-Test-for-all-section-merge-modes.patch
Nack. Please fix random tabs in the indentation. Otherwise it looks fine.
Fixed.
Added another patch, in the new numeration it is patch 15. It is a cosmetic change to meet the coding standard.
The rest are deferred in this round.
------------------------------
I also have a question. I use a struct that is not aligned by 8 byte boundary on a 64 bit machine.
pointer = 8 unsigned = 4 unsigned = 4 unsigned = 4
total length is 20 which is padded to 24
I allocate memory for it using sizeof of the structure. Everything is fine - no leak. I then set the values of the structure one by one. Also in some cases for debugging purposes I print the contents of the allocated memory as binary memory byte by byte. When I do this with the memory used by this structure valgrind complains that I am printing uninitialized memory. And indeed the padding is not initialized by me. So I can: 1) memset memory after allocating it (which I do not like to do especially if I can set all the elements to the non zero values anyways except for padding) 2) Add artificial padding to the structure or a dummy unsigned member (seems a bit ugly) 3) Ignore the warning (seems wrong) 4) Ask your advice (...?)
Patch 0001: Ack
Patch 0002: Ack
Patch 0003: Ack
Patch 0004: Ack, but it would be more efficient (maintenance-wise) to just memset() the struct instead of setting the individual elements to zero.
Patch 0005: Ack
Patch 0006: Ack
Patch 0007: Ack
Patch 0008: Ack
Patch 0009: Ack
Patch 0010: Ack
Patch 0011: Ack
Patch 0012: Ack
Patch 0013: Ack
Patch 0014: Ack
Patch 0015: Nack (minor). I can fix this when I push, but please don't include trailing spaces after the case directives.
On Fri, 2012-03-16 at 01:22 -0400, Dmitri Pal wrote:
On 01/05/2011 01:19 PM, Stephen Gallagher wrote:
On 01/03/2011 06:12 PM, Dmitri Pal wrote:
Please see the attached patches. I tried to split the patches logically into manageable sets. Unfortunately I made a minor mistake and I am afraid I will do something wrong to fix it. I merged two wrong patches. Fortunately it was three liner with 1 liner so it is not a big of the deal but I am really scared that I will do something wrong and loose the work I have done. So I hope it is Ok to send it as is.
0001--INI-Making-Coverity-happy.patch <- this is the patch I submitted earlier that I merged by mistake. I was supposed to merge it with patch 25 but picked the wrong one instead. Patch 25 addresses the real issue found by Coverity as mentioned in Stephen's review mail but it did not apply cleanly since it relies on some code from the patches in the middle.
I split this patch. I'm attaching the missing initializer patch. That gets an ack.
However, the 100078/79 fix is not correct. I did some digging and found the real problem. If you look at line 264 and 279 of ini_valueobj_ut.c, it's possible for other_create_test() to return EOK without having modified the vo variable. As a result, you will be passing the uninitialized value to modify_test(). So Coverity is right that there's a possibility of it passing a freed variable here.
So the Coverity fix gets a nack.
I realized what the problem is. See the first patch.
0002--INI-Adding-missing-function-declararion.patch <- this is the patch that was rejected from the second set sent earlier. Fixed according to review comment.
Dropped. I think Jakub fixed it.
Ack.
0003--BUILD-Allow-trace-per-component.patch <- This patch allows tracing per component
Nack. Requiring a file doesn't make sense. Just add --enable-trace-ini, --enable-trace-collection etc. flags.
Dropped for now
The following set of patches introduces the merging of sections during the reading of the file: 0004--INI-New-error-codes-and-messages.patch
It would be better to use an enum here instead of #defines, then your last entry for ERR_MAXPARSE will always be one higher than your previous error message.
See sdap_basic_opt in src/providers/ldap/sdap.h in the SSSD source code for an example.
That said, there's nothing WRONG with this patch, so ack.
Attached as is. The ticket is open.
0005--INI-New-merge-flags.patch
I don't much like the idea of having flags that have overlapping bits without an obvious reason (0x0020 and 0x0030, for example), but since those are pre-existing, I'll leave them alone. Ack.
As I mentioned earlier I will reconsider however for now it is unchanged.
0006--INI-Add-new-vars-to-parse-structure.patch
Ack, though it seems to me that a memset to zero would be simpler than manually setting every struct member to zero manually.
Unchanged
0007--INI-Add-save_error-function.patch
Nack. It doesn't make sense to pass in an index value to an array local only to the function. That's not clean. It would be better to either pass in the const char * for the message, or at worst pass in an enum type that you would use to look up the matching error message.
Modified. Const char * is passed in.
0008--INI-Change-parse_error-to-use-save_error.patch
Nack. This will need to be updated to correspond to the changes for patch 0007.
Updated to reflect the above patch.
0009--INI-Preparing-for-merging-sections.patch
Ack.
Unchanged
0010--INI-Enhance-value-processing.patch
Ack.
Unchanged
0011--INI-Use-section-line-number.patch
Ack.
Unchanged
0012--INI-Refactor-section-processing.patch
Nack. Please fix the formatting of the switch statement. There should be only one level of indent following the case tag.
Done
0013--INI-Return-error-in-DETECT-mode.patch
Ack
Unchanged
0014--INI-New-test-files-for-section-merge.patch
Ack
Unchanged
0015--INI-Test-DETECT-mode-and-use-new-file.patch
Ack
Unchanged
0016--INI-Test-for-all-section-merge-modes.patch
Nack. Please fix random tabs in the indentation. Otherwise it looks fine.
Fixed.
Added another patch, in the new numeration it is patch 15. It is a cosmetic change to meet the coding standard.
The rest are deferred in this round.
I also have a question. I use a struct that is not aligned by 8 byte boundary on a 64 bit machine.
pointer = 8 unsigned = 4 unsigned = 4 unsigned = 4
total length is 20 which is padded to 24
I allocate memory for it using sizeof of the structure. Everything is fine - no leak. I then set the values of the structure one by one. Also in some cases for debugging purposes I print the contents of the allocated memory as binary memory byte by byte. When I do this with the memory used by this structure valgrind complains that I am printing uninitialized memory. And indeed the padding is not initialized by me. So I can:
- memset memory after allocating it (which I do not like to do
especially if I can set all the elements to the non zero values anyways except for padding) 2) Add artificial padding to the structure or a dummy unsigned member (seems a bit ugly) 3) Ignore the warning (seems wrong) 4) Ask your advice (...?)
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
On 03/19/2012 04:39 PM, Stephen Gallagher wrote:
Patch 0001: Ack
Patch 0002: Ack
Patch 0003: Ack
Patch 0004: Ack, but it would be more efficient (maintenance-wise) to just memset() the struct instead of setting the individual elements to zero.
Patch 0005: Ack
Patch 0006: Ack
Patch 0007: Ack
Patch 0008: Ack
Patch 0009: Ack
Patch 0010: Ack
Patch 0011: Ack
Patch 0012: Ack
Patch 0013: Ack
Patch 0014: Ack
Patch 0015: Nack (minor). I can fix this when I push, but please don't include trailing spaces after the case directives.
Thanks for review. I do not like memset(). It just hides things. If it is not initialized coverity and valgrind would not complain and we will see the issue. The plugin for gedit that I use does not show the spaces the way the old plugin did. I need to find a good plugin again. I will take a note to find a better plugin.
Please push and I will just rebase.
On Fri, 2012-03-16 at 01:22 -0400, Dmitri Pal wrote:
On 01/05/2011 01:19 PM, Stephen Gallagher wrote:
On 01/03/2011 06:12 PM, Dmitri Pal wrote:
Please see the attached patches. I tried to split the patches logically into manageable sets. Unfortunately I made a minor mistake and I am afraid I will do something wrong to fix it. I merged two wrong patches. Fortunately it was three liner with 1 liner so it is not a big of the deal but I am really scared that I will do something wrong and loose the work I have done. So I hope it is Ok to send it as is. 0001--INI-Making-Coverity-happy.patch <- this is the patch I submitted earlier that I merged by mistake. I was supposed to merge it with patch 25 but picked the wrong one instead. Patch 25 addresses the real issue found by Coverity as mentioned in Stephen's review mail but it did not apply cleanly since it relies on some code from the patches in the middle.
I split this patch. I'm attaching the missing initializer patch. That gets an ack.
However, the 100078/79 fix is not correct. I did some digging and found the real problem. If you look at line 264 and 279 of ini_valueobj_ut.c, it's possible for other_create_test() to return EOK without having modified the vo variable. As a result, you will be passing the uninitialized value to modify_test(). So Coverity is right that there's a possibility of it passing a freed variable here.
So the Coverity fix gets a nack.
I realized what the problem is. See the first patch.
0002--INI-Adding-missing-function-declararion.patch <- this is the patch that was rejected from the second set sent earlier. Fixed according to review comment.
Dropped. I think Jakub fixed it.
Ack.
0003--BUILD-Allow-trace-per-component.patch <- This patch allows tracing per component
Nack. Requiring a file doesn't make sense. Just add --enable-trace-ini, --enable-trace-collection etc. flags.
Dropped for now
The following set of patches introduces the merging of sections during the reading of the file: 0004--INI-New-error-codes-and-messages.patch
It would be better to use an enum here instead of #defines, then your last entry for ERR_MAXPARSE will always be one higher than your previous error message.
See sdap_basic_opt in src/providers/ldap/sdap.h in the SSSD source code for an example.
That said, there's nothing WRONG with this patch, so ack.
Attached as is. The ticket is open.
0005--INI-New-merge-flags.patch
I don't much like the idea of having flags that have overlapping bits without an obvious reason (0x0020 and 0x0030, for example), but since those are pre-existing, I'll leave them alone. Ack.
As I mentioned earlier I will reconsider however for now it is unchanged.
0006--INI-Add-new-vars-to-parse-structure.patch
Ack, though it seems to me that a memset to zero would be simpler than manually setting every struct member to zero manually.
Unchanged
0007--INI-Add-save_error-function.patch
Nack. It doesn't make sense to pass in an index value to an array local only to the function. That's not clean. It would be better to either pass in the const char * for the message, or at worst pass in an enum type that you would use to look up the matching error message.
Modified. Const char * is passed in.
0008--INI-Change-parse_error-to-use-save_error.patch
Nack. This will need to be updated to correspond to the changes for patch 0007.
Updated to reflect the above patch.
0009--INI-Preparing-for-merging-sections.patch
Ack.
Unchanged
0010--INI-Enhance-value-processing.patch
Ack.
Unchanged
0011--INI-Use-section-line-number.patch
Ack.
Unchanged
0012--INI-Refactor-section-processing.patch
Nack. Please fix the formatting of the switch statement. There should be only one level of indent following the case tag.
Done
0013--INI-Return-error-in-DETECT-mode.patch
Ack
Unchanged
0014--INI-New-test-files-for-section-merge.patch
Ack
Unchanged
0015--INI-Test-DETECT-mode-and-use-new-file.patch
Ack
Unchanged
0016--INI-Test-for-all-section-merge-modes.patch
Nack. Please fix random tabs in the indentation. Otherwise it looks fine.
Fixed.
Added another patch, in the new numeration it is patch 15. It is a cosmetic change to meet the coding standard.
The rest are deferred in this round.
I also have a question. I use a struct that is not aligned by 8 byte boundary on a 64 bit machine.
pointer = 8 unsigned = 4 unsigned = 4 unsigned = 4
total length is 20 which is padded to 24
I allocate memory for it using sizeof of the structure. Everything is fine - no leak. I then set the values of the structure one by one. Also in some cases for debugging purposes I print the contents of the allocated memory as binary memory byte by byte. When I do this with the memory used by this structure valgrind complains that I am printing uninitialized memory. And indeed the padding is not initialized by me. So I can:
- memset memory after allocating it (which I do not like to do
especially if I can set all the elements to the non zero values anyways except for padding) 2) Add artificial padding to the structure or a dummy unsigned member (seems a bit ugly) 3) Ignore the warning (seems wrong) 4) Ask your advice (...?)
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
On Mon, 2012-03-19 at 19:01 -0400, Dmitri Pal wrote:
Thanks for review. I do not like memset(). It just hides things. If it is not initialized coverity and valgrind would not complain and we will see the issue.
As I said, I don't care sufficiently about it for me to nack it. However, I strongly disagree that memset() hides things. It's defensive coding, as it guarantees that even if someone working in another area of the code adds a new option to the struct, they won't need to remember to initialize the variable. It's not safe to rely on static analysis tools to let us know if a variable isn't initialized. Some of them cannot follow memory through its entire lifecycle.
In the SSSD code, we have a convention that requires us to allocate memory for structures using talloc_zero(), which internally is a malloc() plus a memset() to protect against this.
I'd like to know what you think it "hides", though.
The plugin for gedit that I use does not show the spaces the way the old plugin did. I need to find a good plugin again. I will take a note to find a better plugin.
Please push and I will just rebase.
I'm going to hold off on pushing until I finish the review of the remaining nine patches and then test them all together carefully.
I'm aiming to complete this review today.
On 03/20/2012 08:41 AM, Stephen Gallagher wrote:
I'd like to know what you think it "hides", though.
There are two reasons that I have in mind. 1) When you add a new structure member you add it for purpose so it should be initialized to a proper value. In many cases it is 0 but is some cases it is not. Then you usually add code to do something with this member (otherwise why you added it in the first place). If you memset() the whole struct the value is already initialized and if you forgot to set it to something you would have to spend long time to figure out what is going on in testing. If you do not memset valgrind will immediately find that you are using uninitialized value and point you to the right place helping you to set the proper initial value. This implies that valgrind is routinely executed which is the case in my dev practice. 2) Structure can not be aligned so it will be padded. If then you try to do some operations with the whole blob of data like print it with debug() function you will access the uninitialized memory. This is not good and generally you can't assume that the padding will be done in a same way on different platforms so accessing uninitialized data will be caught. If you memset you will be able to dump this data but it might be meaningless as the layout might change from platform to platform.
These are weak arguments but they force the developer to be honest and thorough so I think it is the "defensive programming" technique. But I do not force anyone to agree with me.
On Mon, Jan 03, 2011 at 06:12:38PM -0500, Dmitri Pal wrote:
Please see the attached patches. I tried to split the patches logically into manageable sets. Unfortunately I made a minor mistake and I am afraid I will do something wrong to fix it. I merged two wrong patches. Fortunately it was three liner with 1 liner so it is not a big of the deal but I am really scared that I will do something wrong and loose the work I have done. So I hope it is Ok to send it as is.
0001--INI-Making-Coverity-happy.patch <- this is the patch I submitted earlier that I merged by mistake. I was supposed to merge it with patch 25 but picked the wrong one instead. Patch 25 addresses the real issue found by Coverity as mentioned in Stephen's review mail but it did not apply cleanly since it relies on some code from the patches in the middle.
0002--INI-Adding-missing-function-declararion.patch <- this is the patch that was rejected from the second set sent earlier. Fixed according to review comment.
0003--BUILD-Allow-trace-per-component.patch <- This patch allows tracing per component
The following set of patches introduces the merging of sections during the reading of the file: 0004--INI-New-error-codes-and-messages.patch 0005--INI-New-merge-flags.patch 0006--INI-Add-new-vars-to-parse-structure.patch 0007--INI-Add-save_error-function.patch 0008--INI-Change-parse_error-to-use-save_error.patch 0009--INI-Preparing-for-merging-sections.patch 0010--INI-Enhance-value-processing.patch 0011--INI-Use-section-line-number.patch 0012--INI-Refactor-section-processing.patch 0013--INI-Return-error-in-DETECT-mode.patch 0014--INI-New-test-files-for-section-merge.patch 0015--INI-Test-DETECT-mode-and-use-new-file.patch 0016--INI-Test-for-all-section-merge-modes.patch
Patches related porting of the meta data from old way of doing things to the new way of doing things: 0017--INI-Separate-close-and-destroy.patch
You should set file_ctx->file to NULL after fclose(file_ctx->file) to make the if(file_ctx->file) checks work in ini_config_file_close() and ini_config_file_destroy().
There are tab indents in merge_values_test() and merge_section_test().
0018--INI-Function-to-reopen-file.patch 0019--INI-Metadata-collection-is-gone.patch
You remove metadata from struct ini_cfgfile without removing all references to metadata in the same patch. You should make clear that more patches are needed to create a buildable version of libini or remove all references in this patch.
I wonder is the following is a change of defaults. With the patch the new file_ctx->file_stats are only set if INI_META_STATS is set while previously file-ctx>metadata was set unconditionally.
0020--INI-Check-access-function.patch
I wonder if it is necessary to return EINVAL if flags == 0. I would say in this case no checks are requested and EOK could be returned?
I would prefer to copy file_ctx->file_stats.st_mode instead of modifying it, e.g. you might want to know the file type later on.
0021--INI-Avoid-double-free.patch <- patch related to 17 (missed check)
oops, so you can ignore my comment to 00017, let's see if there is also a patch for ini_config_file_destroy(). "I might squash this patch into one of the previous ones." Yes, please.
0022--INI-Function-to-check-for-changes.patch 0023--INI-Tests-for-access-and-changes.patch
Why do you need sleep(1) ? The man page of system() does not mention that system() sets errno, please check the return code instead.
0024--INI-Rename-error-print-function.patch <- rename error printing function for consistency with new interface
Maybe ini_print_errors() should print a deprecated warning to make migrations easier.
0025--INI-Initialize-variables-in-loops.patch <- Coverity issue addressed. Related to patch 0001.
0026--INI-Exposing-functions.patch <- Make some internal functions reusable
There is also patch 27. It is a piece of new functionality. It is a preview. Please see the comment before reviewing it. Do I need to split it into multiple patches or it is Ok as is? It is pretty big but all changes are in one file and logically related. The UNIT test is missing so I am not claiming it actually works as expected.
I didn't had a look at 0027 so far.
bye, Sumit
-- Thank you, Dmitri Pal
Sr. Engineering Manager IPA project, Red Hat Inc.
Looking to carve out IT costs? www.redhat.com/carveoutcosts/
From 2cb4d6ad0bfad2170e09152379f29de2b9c29196 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Fri, 24 Dec 2010 00:38:48 -0500 Subject: [PATCH] [INI] Making Coverity happy
Coverity found issues 10078 & 10079. This patch should make it happy, however I think that Coverity is wrong unless I am missing something. If I am I hope that this patch would be able to reveal the real issue if any. For now just renaming a variable.
[INI] Added missing initialization
One liner to initialize a variable.
ini/ini_configobj.c | 2 +- ini/ini_valueobj_ut.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/ini/ini_configobj.c b/ini/ini_configobj.c index 3e5dec4733a49d03e44185637592f0efdbe7db3c..5e5e40b566abdf3ce2cbc225babe4b1e20c2dd47 100644 --- a/ini/ini_configobj.c +++ b/ini/ini_configobj.c @@ -215,7 +215,7 @@ int ini_config_copy(struct ini_cfgobj *ini_config, struct ini_cfgobj **ini_new) { int error = EOK;
- struct ini_cfgobj *new_co;
struct ini_cfgobj *new_co = NULL;
TRACE_FLOW_ENTRY();
diff --git a/ini/ini_valueobj_ut.c b/ini/ini_valueobj_ut.c index 767a64cc2fe624800bed7e9dc4b53a90fa2d59c2..af62c140d215f9298dd5671d8aa544a84ef254b1 100644 --- a/ini/ini_valueobj_ut.c +++ b/ini/ini_valueobj_ut.c @@ -378,6 +378,7 @@ int vo_basic_test(void) */
struct value_obj *vo = NULL;
- struct value_obj *other_vo = NULL; uint32_t wrap = 0; struct ini_comment *ic = NULL; FILE *ff = NULL;
@@ -429,7 +430,7 @@ int vo_basic_test(void) }
/* Run other create test here */
- error = other_create_test(ff, &vo);
- error = other_create_test(ff, &other_vo); if (error) { printf("Create test failed %d.\n", error); fclose(ff);
@@ -437,15 +438,15 @@ int vo_basic_test(void) }
/* Run modify test here */
- error = modify_test(ff, vo);
- error = modify_test(ff, other_vo); if (error) { printf("Modify test failed %d.\n", error); fclose(ff);
value_destroy(vo);
}value_destroy(other_vo); return error;
- value_destroy(vo);
value_destroy(other_vo);
ic = NULL;
-- 1.5.5.6
From 68ecd60fac51706c743a5c4a4cfe87ec6ca9d304 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Fri, 24 Dec 2010 21:27:24 -0500 Subject: [PATCH] [INI] Adding missing function declararion.
One-liner that eliminates compilation warning.
[INI] Include proper header
Value object needs its own header file.
ini/ini_valueobj.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/ini/ini_valueobj.c b/ini/ini_valueobj.c index a90fa451468aecc6c04f4411675ab67613a59cbe..f196c1ab3195db7cbe616e6e1275c656919fe156 100644 --- a/ini/ini_valueobj.c +++ b/ini/ini_valueobj.c @@ -29,6 +29,7 @@ #include "ini_comment.h" #include "ini_defines.h" #include "trace.h" +#include "ini_valueobj.h"
struct value_obj { struct ref_array *raw_lines; -- 1.5.5.6
From 574be6d8c0896c8bee0c16224f52c2dbea48a44e Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Fri, 24 Dec 2010 22:38:42 -0500 Subject: [PATCH] [BUILD] Allow trace per component
This patch add ability to build tracing for each component independently.
Makefile.am | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- configure.ac | 15 ++++++++++++++- 2 files changed, 60 insertions(+), 5 deletions(-)
diff --git a/Makefile.am b/Makefile.am index 0946169308bab6585c93cca36d45b360b565f6b5..1780e9b234e68006af910413b3e8312c9db72c7b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,7 @@ -TRACE_LEVEL=@TRACE_VAR@ +TRACE_INI=@TRACE_INI@ +TRACE_COLLECTION=@TRACE_COLLECTION@ +TRACE_REFARRAY=@TRACE_REFARRAY@ +TRACE_BASICOBJECTS=@TRACE_BASICOBJECTS@
RPMBUILD ?= $(PWD)/rpmbuild
@@ -28,8 +31,7 @@ AM_CPPFLAGS = \ -I$(srcdir)/ini \ -I$(srcdir)/basicobjects \ -I$(srcdir) \
- -I$(srcdir)/trace \
- $(TRACE_LEVEL)
- -I$(srcdir)/trace
ACLOCAL_AMFLAGS = -I m4
@@ -132,6 +134,10 @@ libcollection_la_SOURCES = \ libcollection_la_LDFLAGS = \ -version-info 3:0:0
+libcollection_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
check_PROGRAMS += \ collection_ut \ collection_stack_ut \ @@ -142,11 +148,21 @@ TESTS += \ collection_queue_ut
collection_ut_SOURCES = collection/collection_ut.c +collection_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
collection_ut_LDADD = libcollection.la collection_stack_ut_SOURCES = collection/collection_stack_ut.c collection_stack_ut_LDADD = libcollection.la +collection_stack_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
collection_queue_ut_SOURCES = collection/collection_queue_ut.c collection_queue_ut_LDADD = libcollection.la +collection_queue_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
collection-docs: if HAVE_DOXYGEN @@ -167,10 +183,15 @@ libref_array_la_SOURCES = \ trace/trace.h libref_array_la_LDFLAGS = \ -version-info 1:0:0
+libref_array_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_REFARRAY)
check_PROGRAMS += ref_array_ut TESTS += ref_array_ut ref_array_ut_SOURCES = refarray/ref_array_ut.c +ref_array_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_REFARRAY)
ref_array_ut_LDADD = libref_array.la
dist_doc_DATA += refarray/README.ref_array @@ -194,11 +215,17 @@ libbasicobjects_la_SOURCES = \ trace/trace.h libbasicobjects_la_LDFLAGS = \ -version-info 1:0:0 +libbasicobjects_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_BASICOBJECTS)
check_PROGRAMS += simplebuffer_ut TESTS += simplebuffer_ut simplebuffer_ut_SOURCES = basicobjects/simplebuffer_ut.c simplebuffer_ut_LDADD = libbasicobjects.la +simplebuffer_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_BASICOBJECTS)
basicobjects-docs: if HAVE_DOXYGEN @@ -243,6 +270,9 @@ libini_config_la_LIBADD = \ libbasicobjects.la libini_config_la_LDFLAGS = \ -version-info 3:0:0 +libini_config_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
dist_noinst_DATA += \ ini/ini.conf \ @@ -268,15 +298,27 @@ ini_config_ut_SOURCES = ini/ini_config_ut.c ini_config_ut_LDADD = \ libini_config.la \ libcollection.la +ini_config_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_comment_ut_SOURCES = ini/ini_comment_ut.c ini_comment_ut_LDADD = libini_config.la +ini_comment_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_valueobj_ut_SOURCES = ini/ini_valueobj_ut.c ini_valueobj_ut_LDADD = libini_config.la +ini_valueobj_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_parse_ut_SOURCES = ini/ini_parse_ut.c ini_parse_ut_LDADD = libini_config.la +ini_parse_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_config-docs: if HAVE_DOXYGEN diff --git a/configure.ac b/configure.ac index 2e22e8a6aaac271dfa4841c17f98411967e09fd9..d1b68f5fd76654e899738f6c8a29b516a23592c5 100644 --- a/configure.ac +++ b/configure.ac @@ -39,11 +39,24 @@ AC_PATH_PROG([DOXYGEN], [doxygen], [false]) AM_CONDITIONAL([HAVE_DOXYGEN], [test x$DOXYGEN != xfalse ])
# Enable trace build +# To turn on the tracing of one of the componenets one has not only +# to enable it with --enable-trace but to drop a file named "trace" +# into a corresponding directory. +# Tracing can be built for collection, ini, refarray or basicobjects. +# The approach allows building different libraries with trace +# independent of each other. AC_ARG_ENABLE([trace], [AS_HELP_STRING([--enable-trace[=LEVEL]],[build with low level tracing enabled])], [trace_level="$enableval"], [trace_level="0"]) -AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] ],[AC_SUBST([TRACE_VAR],["-DTRACE_LEVEL=$trace_level"])]) +AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/ini/trace] ],
[AC_SUBST([TRACE_INI],["-DTRACE_LEVEL=$trace_level"])])
+AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/collection/trace] ],
[AC_SUBST([TRACE_COLLECTION],["-DTRACE_LEVEL=$trace_level"])])
+AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/refarray/trace] ],
[AC_SUBST([TRACE_REFARRAY],["-DTRACE_LEVEL=$trace_level"])])
+AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/basicobjects/trace] ],
[AC_SUBST([TRACE_BASICOBJECTS],["-DTRACE_LEVEL=$trace_level"])])
AC_CHECK_SIZEOF([long]) AC_CHECK_SIZEOF([long long]) -- 1.5.5.6
From 6a66a986e962554b161ddb46f8b1e85a7c791e27 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:24:35 -0500 Subject: [PATCH] [INI] New error codes and messages
Patch consists of two parts:
- Adding new constants for error messages to ini_configobj.h file
- Making ini_print.c use this header file instead of the old one.
ini/ini_configobj.h | 12 ++++++---- ini/ini_print.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 9 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 88a8704277facb0f8883b2df28a709b26ae311f7..36558a701a86f6f656f2d0e3b155b9d901177fa7 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -72,13 +72,15 @@ #define ERR_READ 8 /** @brief Line starts with space when it should not (Error). */ #define ERR_SPACE 9 +/** @brief Duplicate key is not allowed (Error). */ +#define ERR_DUPKEY 10 +/** @brief Duplicate key is detected while merging sections (Error). */ +#define ERR_DUPKEYSEC 11 +/** @brief Duplicate section is not allowed (Error). */ +#define ERR_DUPSECTION 12
/** @brief Size of the error array. */ -#define ERR_MAXPARSE ERR_SPACE
-/**
- @}
- */
+#define ERR_MAXPARSE ERR_DUPSECTION
/** diff --git a/ini/ini_print.c b/ini/ini_print.c index 0430976cd56e89313cb386b99ad387263498c639..1dcfa54bfd72daf2c790d04c37ff2b3107eb7295 100644 --- a/ini/ini_print.c +++ b/ini/ini_print.c @@ -31,7 +31,8 @@ #include "collection.h" #include "collection_tools.h" #include "ini_defines.h" -#include "ini_config.h" +#include "ini_config_priv.h" +#include "ini_configobj.h"
/*============================================================*/ @@ -42,6 +43,16 @@
- check that the class IDs did not get reused over time by
- other classes.
*/ +/**
- @brief Collection of error collections.
- When multiple files are read during one call
- each file has its own set of parsing errors
- and warnings. This is the collection
- of such sets.
- */
+#define COL_CLASS_INI_PESET COL_CLASS_INI_BASE + 3
/** @brief Collection of grammar errors.
- Reserved for future use.
@@ -53,6 +64,37 @@ */ #define COL_CLASS_INI_VERROR COL_CLASS_INI_BASE + 6
+/**
- @}
- */
+/**
- @defgroup gramerr Grammar errors and warnings
- Placeholder for now. Reserved for future use.
- @{
- */
+#define ERR_MAXGRAMMAR 0 +/**
- @}
- */
+/**
- @defgroup valerr Validation errors and warnings
- Placeholder for now. Reserved for future use.
- @{
- */
+#define ERR_MAXVALID 0
+/**
- @}
- */
#ifdef HAVE_VALIDATION
/** @brief Collection of lines from the INI file. @@ -78,7 +120,11 @@ static const char *parsing_error_str(int parsing_error) _("Property name is too long."), _("Failed to read line."), _("Invalid space character at the "
"beginning of the line.")
"beginning of the line."),
_("Duplicate key is not allowed."),
_("Duplicate key is detected while "
"merging sections."),
_("Duplicate section is not allowed.")
};
/* Check the range */
@@ -208,7 +254,7 @@ static void print_error_list(FILE *file, struct collection_iterator *iterator; int error; struct collection_item *item = NULL;
- struct parse_error *pe;
struct ini_parse_error *pe; unsigned int count;
TRACE_FLOW_STRING("print_error_list", "Entry");
@@ -256,7 +302,7 @@ static void print_error_list(FILE *file, } else { /* Put error into provided format */
pe = (struct parse_error *)(col_get_item_data(item));
pe = (struct ini_parse_error *)(col_get_item_data(item)); fprintf(file, line_format, col_get_item_property(item, NULL), /* Error or warning */ pe->error, /* Error */
-- 1.5.5.6
From 2323da5507a13b5267152482a212442685cfcf05 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:29:05 -0500 Subject: [PATCH] [INI] New merge flags
Adding "DETECT" merge modes. These modes would be useable for dry run cases to detect if there are any potential merge conflicts. Patch just defines new constans and adds input checks.
ini/ini_configobj.h | 6 ++++++ ini/ini_fileobj.c | 9 ++++++--- 2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 36558a701a86f6f656f2d0e3b155b9d901177fa7..f0c6882dbb1e066972f98309bf78a99670b985c5 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -108,6 +108,8 @@ #define INI_MV1S_PRESERVE 0x0002 /** @brief Duplicates are allowed */ #define INI_MV1S_ALLOW 0x0003 +/** @brief Duplicates are allowed but errors are logged */ +#define INI_MV1S_DETECT 0x0004
/**
- @}
@@ -133,6 +135,8 @@ #define INI_MV2S_PRESERVE 0x0020 /** @brief Duplicates are allowed */ #define INI_MV2S_ALLOW 0x0030 +/** @brief Duplicates are allowed but errors are logged */ +#define INI_MV2S_DETECT 0x0040
/**
- @}
@@ -159,6 +163,8 @@ #define INI_MS_PRESERVE 0x0300 /** @brief Duplicates are allowed */ #define INI_MS_ALLOW 0x0400 +/** @brief Duplicates are allowed but errors are logged */ +#define INI_MS_DETECT 0x0500
/**
- @}
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 94494f78a41b6af5e44686134ab1e48290b9ab38..7bc599b948563964830f9ade75966cf4f9aa3018 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -44,7 +44,8 @@ static int valid_collision_flags(uint32_t collision_flags) if ((flag != INI_MV1S_OVERWRITE) && (flag != INI_MV1S_ERROR) && (flag != INI_MV1S_PRESERVE) &&
(flag != INI_MV1S_ALLOW)) {
(flag != INI_MV1S_ALLOW) &&
}(flag != INI_MV1S_DETECT)) { TRACE_ERROR_STRING("Invalid value collision flag",""); return 0;
@@ -53,7 +54,8 @@ static int valid_collision_flags(uint32_t collision_flags) if ((flag != INI_MV2S_OVERWRITE) && (flag != INI_MV2S_ERROR) && (flag != INI_MV2S_PRESERVE) &&
(flag != INI_MV2S_ALLOW)) {
(flag != INI_MV2S_ALLOW) &&
}(flag != INI_MV2S_DETECT)) { TRACE_ERROR_STRING("Invalid value cross-section collision flag",""); return 0;
@@ -63,7 +65,8 @@ static int valid_collision_flags(uint32_t collision_flags) (flag != INI_MS_OVERWRITE) && (flag != INI_MS_ERROR) && (flag != INI_MS_PRESERVE) &&
(flag != INI_MS_ALLOW)) {
(flag != INI_MS_ALLOW) &&
}(flag != INI_MS_DETECT)) { TRACE_ERROR_STRING("Invalid section collision flag",""); return 0;
-- 1.5.5.6
From 45efaa8dc8de649d4714066ccd3b8441dd55b0e6 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:36:06 -0500 Subject: [PATCH] [INI] Add new vars to parse structure
Adding new varibles to the internal parsing structure and initializing them.
ini/ini_parse.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 18edc629e90fe47597357b7953f06990ab5a48f0..9667a02926ef7d984886896b206997a841f04619 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -69,8 +69,11 @@ struct parser_obj { uint32_t linenum; /* Line number of the last found key */ uint32_t keylinenum;
- /* Line number of the last found section */
- uint32_t seclinenum; /* Internal variables */ struct collection_item *sec;
- struct collection_item *merge_sec; struct ini_comment *ic; char *last_read; uint32_t last_read_len;
@@ -78,12 +81,15 @@ struct parser_obj { uint32_t key_len; struct ref_array *raw_lines; struct ref_array *raw_lengths;
- char *merge_key;
- struct value_obj *merge_vo;
- /* Merge error */
- uint32_t merge_error; int ret;
};
typedef int (*action_fn)(struct parser_obj *);
#define PARSE_ACTION "action"
/* Actions */ @@ -181,9 +187,12 @@ static int parser_create(FILE *file,
/* Initialize internal varibles */ new_po->sec = NULL;
- new_po->merge_sec = NULL; new_po->ic = NULL; new_po->last_error = 0; new_po->linenum = 0;
- new_po->keylinenum = 0;
- new_po->seclinenum = 0; new_po->last_read = NULL; new_po->last_read_len = 0; new_po->key = NULL;
@@ -191,6 +200,9 @@ static int parser_create(FILE *file, new_po->raw_lines = NULL; new_po->raw_lengths = NULL; new_po->ret = EOK;
new_po->merge_key = NULL;
new_po->merge_vo = NULL;
new_po->merge_error = 0;
/* Create a queue */ new_po->queue = NULL;
-- 1.5.5.6
From 27cf7bc5c1089380cc7bc893deee8eb88db2d3d4 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:44:52 -0500 Subject: [PATCH] [INI] Add save_error function
Create a function to add error into error list.
ini/ini_parse.c | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 9667a02926ef7d984886896b206997a841f04619..a2e05f9311d38ff5904b016c5c8335d56b26a170 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -99,6 +99,13 @@ typedef int (*action_fn)(struct parser_obj *); #define PARSE_ERROR 3 /* Handle error */ #define PARSE_DONE 4 /* We are done */
+/* Declarations of the reusble functions: */ +static int complete_value_processing(struct parser_obj *po); +static int save_error(struct collection_item *el,
unsigned line,
int error,
int idx);
int is_just_spaces(const char *str, uint32_t len) { @@ -946,6 +953,28 @@ static int parser_post(struct parser_obj *po) return EOK; }
+static int save_error(struct collection_item *el,
unsigned line,
int inerr,
int idx)
+{
- int error = EOK;
- const char *errtxt[] = { ERROR_TXT, WARNING_TXT };
- struct ini_parse_error pe;
- TRACE_FLOW_ENTRY();
- /* Clear the warning bit */
- pe.error = inerr;
- pe.line = line;
- error = col_add_binary_property(el, NULL,
errtxt[idx], &pe, sizeof(pe));
- TRACE_FLOW_RETURN(error);
- return error;
+}
/* Error and warning processing */ static int parser_error(struct parser_obj *po) { -- 1.5.5.6
From e5a6bb7e8fab4b7e23f31ee1ab5ce10bf7dd33d5 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:48:35 -0500 Subject: [PATCH] [INI] Change parse_error to use save_error
- Changed parse_error to use save_error function created in previous commit.
- Fixed comment to be more clear.
ini/ini_parse.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index a2e05f9311d38ff5904b016c5c8335d56b26a170..e7eab28211655f7a225202552fd96b68c1e09450 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -981,19 +981,17 @@ static int parser_error(struct parser_obj *po) int error = EOK; uint32_t action; int idx = 0;
const char *errtxt[] = { ERROR_TXT, WARNING_TXT };
struct ini_parse_error pe;
TRACE_FLOW_ENTRY();
pe.line = po->linenum;
/* Clear the warning bit */
pe.error = po->last_error & ~INI_WARNING; if (po->last_error & INI_WARNING) idx = 1;
error = col_add_binary_property(po->el, NULL,
errtxt[idx], &pe, sizeof(pe));
- error = save_error(po->el,
po->linenum,
po->last_error & ~INI_WARNING,
if (error) {idx);
TRACE_ERROR_NUMBER("Failed to add error to collection",
}TRACE_ERROR_NUMBER("Failed to add error to error list", error); return error;
@@ -1043,7 +1041,9 @@ static int parser_error(struct parser_obj *po) /* If merging sections should produce error and we got error * or if we merge sections but dup values produce error and * we got error then it is not a fatal error so we need to handle
* it nicely. We check for reverse condition and return error,
* it nicely and suppress it here. We already in the procees
* of handling another error and merge error does not matter here.
* We check for reverse condition and return error, * otherwise fall through. */ if (!((((po->collision_flags & INI_MS_MASK) == INI_MS_ERROR) &&
-- 1.5.5.6
From 10610699c6db3d181011c85447073f5ee4a04153 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:56:51 -0500 Subject: [PATCH] [INI] Preparing for merging sections
Patch implements three functions:
- Function to detect a collision between two section names.
- Function to empty section from all its keys
- Function to add values one by one from one section to another.
ini/ini_parse.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 177 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index e7eab28211655f7a225202552fd96b68c1e09450..fc43cb06daca64309e47f43047263c5f066fc43e 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -318,6 +318,183 @@ static int parser_read(struct parser_obj *po) return EOK; }
+/* Find if there is a collistion */ +static int check_section_collision(struct parser_obj *po) +{
- int error = EOK;
- struct collection_item *item = NULL;
- TRACE_FLOW_ENTRY();
- TRACE_INFO_STRING("Searching for:", col_get_item_property(po->sec, NULL));
- error = col_get_item(po->top,
col_get_item_property(po->sec, NULL),
COL_TYPE_ANY,
COL_TRAVERSE_DEFAULT,
&item);
- if (error) {
TRACE_ERROR_NUMBER("Failed searching for dup", error);
return error;
- }
- /* Check if there is a dup */
- if (item) {
TRACE_INFO_STRING("Collision found:",
col_get_item_property(item, NULL));
/* Get the actual section collection instead of reference */
po->merge_sec = *((struct collection_item **)
(col_get_item_data(item)));
- }
- else {
TRACE_INFO_STRING("Collision not found.", "");
po->merge_sec = NULL;
- }
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Clean all items in the section */ +static int empty_section(struct collection_item *sec) +{
- int error = EOK;
- struct collection_item *item = NULL;
- struct collection_item *save_item = NULL;
- struct value_obj *vo = NULL;
- int work_to_do = 1;
- TRACE_FLOW_ENTRY();
- do {
item = NULL;
error = col_extract_item_from_current(sec,
COL_DSP_FRONT,
NULL,
0,
COL_TYPE_ANY,
&item);
if ((error) && (error != ENOENT)) {
TRACE_ERROR_NUMBER("Failed to extract item.", error);
return error;
}
if (item) {
TRACE_INFO_STRING("Item found:",
col_get_item_property(item, NULL));
if (strncmp(col_get_item_property(item, NULL),
INI_SECTION_KEY, 1) == 0) {
/* Just ignore the first item */
save_item = item;
continue;
}
vo = *((struct value_obj **)(col_get_item_data(item)));
value_destroy(vo);
col_delete_item(item);
}
else {
TRACE_INFO_STRING("No more items:", "");
/* Restore saved item */
error = col_insert_item(sec,
NULL,
save_item,
COL_DSP_END,
NULL,
0,
COL_INSERT_NOCHECK);
if (error) {
TRACE_ERROR_NUMBER("Failed to restore item.", error);
return error;
}
work_to_do = 0;
}
- }
- while (work_to_do);
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Merge contents of the section */ +static int merge_section(struct parser_obj *po) +{
- int error = EOK;
- struct collection_item *item = NULL;
- struct value_obj *vo = NULL;
- int work_to_do = 1;
- const char *key;
- TRACE_FLOW_ENTRY();
- do {
TRACE_INFO_STRING("Top of the merge loop", "");
item = NULL;
error = col_extract_item_from_current(po->sec,
COL_DSP_FRONT,
NULL,
0,
COL_TYPE_ANY,
&item);
if ((error) && (error != ENOENT)) {
TRACE_ERROR_NUMBER("Failed to extract item.", error);
return error;
}
if (item) {
TRACE_INFO_STRING("Item found:", col_get_item_property(item, NULL));
if (strncmp(col_get_item_property(item, NULL),
INI_SECTION_KEY, 1) == 0) {
/* Just ignore the first item */
vo = *((struct value_obj **)(col_get_item_data(item)));
value_destroy(vo);
col_delete_item(item);
continue;
}
po->merge_vo = *((struct value_obj **)(col_get_item_data(item)));
key = col_get_item_property(item, NULL);
/* To be able to use po->merge_key in the loop
* we have to overcome constraints imposed by
* the "const" declaration.
*/
memcpy(&(po->merge_key), &key, sizeof(char *));
/* Use the value processing function to inser the value */
error = complete_value_processing(po);
/* In case of error value is already cleaned */
po->merge_vo = NULL;
po->merge_key = NULL;
col_delete_item(item);
/* Now we can check the error */
if (error) {
TRACE_ERROR_NUMBER("Failed to merge item.", error);
return error;
}
}
else {
TRACE_INFO_STRING("No more items:", "");
work_to_do = 0;
}
- }
- while (work_to_do);
- /* If we reached this place the incoming section is empty.
* but just to be safe clean with callback. */
- col_destroy_collection_with_cb(po->sec, ini_cleanup_cb, NULL);
- po->sec = NULL;
- TRACE_FLOW_EXIT();
- return EOK;
+}
/* Function to read next line from the file */ static int parser_save_section(struct parser_obj *po) { -- 1.5.5.6
From aa35a75674482febe3f5f67b3e7c7c7faf507f05 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:03:33 -0500 Subject: [PATCH] [INI] Enhance value processing
This patch refactores the value processing function so that it can be used both in normal mode when velues need to be constrcuted and saved into the current section (po->sec) and in the merge mode when values are already constructed and need to be saved into a po->merge_sec.
ini/ini_parse.c | 165 ++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 116 insertions(+), 49 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index fc43cb06daca64309e47f43047263c5f066fc43e..5dd873a339e5fce36bc13ea8bde65dbefc5d617f 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -529,6 +529,7 @@ static int parser_save_section(struct parser_obj *po) static int complete_value_processing(struct parser_obj *po) { int error = EOK;
- int error2 = EOK; struct value_obj *vo = NULL; struct value_obj *vo_old = NULL; unsigned insertmode;
@@ -536,12 +537,19 @@ static int complete_value_processing(struct parser_obj *po) int suppress = 0; int doinsert = 0; struct collection_item *item = NULL;
struct collection_item *section = NULL;
int merging = 0;
TRACE_FLOW_ENTRY();
- /* If there is not open section create a default one */
- if(!(po->sec)) {
/* Create a new section */
- if (po->merge_sec) {
TRACE_INFO_STRING("Processing value in merge mode", "");
section = po->merge_sec;
merging = 1;
- }
- else if(!(po->sec)) {
TRACE_INFO_STRING("Creating default section", "");
/* If there is not open section create a default one */ error = col_create_collection(&po->sec, INI_DEFAULT_SECTION, COL_CLASS_INI_SECTION);
@@ -549,29 +557,44 @@ static int complete_value_processing(struct parser_obj *po) TRACE_ERROR_NUMBER("Failed to create default section", error); return error; }
}section = po->sec;
- /* Construct value object from what we have */
- error = value_create_from_refarray(po->raw_lines,
po->raw_lengths,
po->keylinenum,
INI_VALUE_READ,
po->key_len,
po->boundary,
po->ic,
&vo);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create value object", error);
return error;
- else {
TRACE_INFO_STRING("Processing value in normal mode", "");
}section = po->sec;
- /* Forget about the arrays. They are now owned by the value object */
- po->ic = NULL;
- po->raw_lines = NULL;
- po->raw_lengths = NULL;
- if (merging) {
TRACE_INFO_STRING("Using merge key:", po->merge_key);
vo = po->merge_vo;
/* We are adding to the merge section so use MV2S flags.
* But flags are done in such a way that deviding MV2S by MV1S mask
* will translate MV2S flags into MV1S so we can use
* MV1S constants. */
TRACE_INFO_NUMBER("Collisions flags:", po->collision_flags);
mergemode = (po->collision_flags & INI_MV2S_MASK) / INI_MV1S_MASK;
- }
- else {
/* Construct value object from what we have */
error = value_create_from_refarray(po->raw_lines,
po->raw_lengths,
po->keylinenum,
INI_VALUE_READ,
po->key_len,
po->boundary,
po->ic,
&vo);
- mergemode = po->collision_flags & INI_MV1S_MASK;
if (error) {
TRACE_ERROR_NUMBER("Failed to create value object", error);
return error;
}
/* Forget about the arrays. They are now owned by the value object */
po->ic = NULL;
po->raw_lines = NULL;
po->raw_lengths = NULL;
mergemode = po->collision_flags & INI_MV1S_MASK;
}
switch (mergemode) { case INI_MV1S_ERROR: insertmode = COL_INSERT_DUPERROR;
@@ -585,16 +608,18 @@ static int complete_value_processing(struct parser_obj *po) doinsert = 1; break; case INI_MV1S_OVERWRITE: /* Special handling */
case INI_MV1S_DETECT: default: break; }
/* Do not insert but search for dups first */ if (!doinsert) {
TRACE_INFO_STRING("Ovewrite mode. Lokking for:", po->key);
TRACE_INFO_STRING("Overwrite mode. Looking for:",
(char *)(merging ? po->merge_key : po->key));
error = col_get_item(po->sec,
po->key,
error = col_get_item(section,
merging ? po->merge_key : po->key, COL_TYPE_BINARY, COL_TRAVERSE_DEFAULT, &item);
@@ -607,21 +632,42 @@ static int complete_value_processing(struct parser_obj *po)
/* Check if there is a dup */ if (item) {
/* Dup exists - update it */
vo_old = *((struct value_obj **)(col_get_item_data(item)));
error = col_modify_binary_item(item,
NULL,
&vo,
sizeof(struct value_obj *));
if (error) {
TRACE_ERROR_NUMBER("Failed updating the value", error);
value_destroy(vo);
return error;
/* Check if we are in the detect mode */
if (mergemode == INI_MV1S_DETECT) {
po->merge_error = EEXIST;
/* There is a dup - inform user about it and continue */
error = save_error(po->el,
merging ? po->seclinenum : po->keylinenum,
merging ? ERR_DUPKEYSEC : ERR_DUPKEY,
0);
if (error) {
TRACE_ERROR_NUMBER("Failed to save error", error);
value_destroy(vo);
return error;
}
doinsert = 1;
insertmode = COL_INSERT_NOCHECK;
}
else {
/* Dup exists - update it */
vo_old = *((struct value_obj **)(col_get_item_data(item)));
error = col_modify_binary_item(item,
NULL,
&vo,
sizeof(struct value_obj *));
if (error) {
TRACE_ERROR_NUMBER("Failed updating the value", error);
value_destroy(vo);
return error;
}
/* If we failed to update it is better to leak then crash,
* so destroy original value only on the successful update.
*/
value_destroy(vo_old); }
/* If we failed to update it is better to leak then crash,
* so desctroy original value only on the successful update.
*/
value_destroy(vo_old); } else { /* No dup found so we can insert with no check */
@@ -632,31 +678,52 @@ static int complete_value_processing(struct parser_obj *po)
if (doinsert) { /* Add value to collection */
error = col_insert_binary_property(po->sec,
error = col_insert_binary_property(section, NULL, COL_DSP_END, NULL, 0, insertmode,
po->key,
merging ? po->merge_key : po->key, &vo, sizeof(struct value_obj *)); if (error) {
value_destroy(vo);
if ((suppress) && (error == EEXIST)) {
TRACE_INFO_STRING("Preseved exisitng value", po->key);
value_destroy(vo);
TRACE_INFO_STRING("Preseved exisitng value",
(char *)(merging ? po->merge_key : po->key)); } else {
TRACE_ERROR_NUMBER("Failed to add value object to the section", error);
value_destroy(vo);
return error;
/* Check if this is a critical error or not */
if ((mergemode == INI_MV1S_ERROR) && (error == EEXIST)) {
TRACE_ERROR_NUMBER("Failed to add value object "
"to the section", error);
error2 = save_error(po->el,
merging ? po->seclinenum : po->keylinenum,
merging ? ERR_DUPKEYSEC : ERR_DUPKEY,
0);
if (error2) {
TRACE_ERROR_NUMBER("Failed to save error", error2);
return error2;
}
return error;
}
else {
TRACE_ERROR_NUMBER("Failed to add value object"
" to the section", error);
return error;
}} } }
- free(po->key);
- po->key = NULL;
- po->key_len = 0;
- if (!merging) {
free(po->key);
po->key = NULL;
po->key_len = 0;
- }
- TRACE_FLOW_EXIT(); return EOK;
}
1.5.5.6
From f5e1f6494f6350d41fce3e063a8aebf72aa7c4ea Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:05:28 -0500 Subject: [PATCH] [INI] Use section line number
Use section line number for error reporting about the section collisions.
ini/ini_parse.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 5dd873a339e5fce36bc13ea8bde65dbefc5d617f..a1c3a26f0f88c80616bad5336be1126a1f9b99bf 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -1069,9 +1069,12 @@ static int handle_section(struct parser_obj *po, uint32_t *action) }
/* Save the line number of the last found key */
- po->keylinenum = po->linenum;
- po->seclinenum = po->linenum;
- /* Complete processing of this value */
- /* Complete processing of this value.
* A new section will be created inside and a special
* value will be added.
error = complete_value_processing(po); if (error) { TRACE_ERROR_NUMBER("Failed to complete value processing", error);*/
-- 1.5.5.6
From 6d4b2785106cd6614eedb62069da76ecc2e90457 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:08:19 -0500 Subject: [PATCH] [INI] Refactor section processing
This patch adds functionality to respect merge section flags and to process section collisions differently dpending on these flags.
ini/ini_parse.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 105 insertions(+), 9 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index a1c3a26f0f88c80616bad5336be1126a1f9b99bf..d9c6d0a9bc71f197eb4bf752fd56958ba6f64df2 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -499,25 +499,121 @@ static int merge_section(struct parser_obj *po) static int parser_save_section(struct parser_obj *po) { int error = EOK;
uint32_t mergemode;
int add = 0;
int merge = 0;
TRACE_FLOW_ENTRY();
if (po->sec) {
/* For now just add as we did.
* Add merge code here !!!!
*/
error = col_add_collection_to_collection(po->top,
NULL, NULL,
po->sec,
COL_ADD_MODE_EMBED);
TRACE_INFO_STRING("Section exists.", "");
/* First detect if we have collision */
error = check_section_collision(po); if (error) {
TRACE_ERROR_NUMBER("Failed to embed section", error);
TRACE_ERROR_NUMBER("Failed to check for collision", error); return error; }
po->sec = NULL;
if (po->merge_sec) {
TRACE_INFO_STRING("Merge collision detected", "");
mergemode = po->collision_flags & INI_MS_MASK;
switch (mergemode) {
case INI_MS_ERROR: /* Report error and return */
TRACE_INFO_STRING("Reporting error",
"duplicate section");
error = save_error(po->el,
po->seclinenum,
ERR_DUPSECTION,
0);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"save error",
error);
return error;
}
/* Return error */
TRACE_FLOW_RETURN(EEXIST);
return EEXIST;
case INI_MS_PRESERVE: /* Delete new section */
TRACE_INFO_STRING("Preserve mode", "");
col_destroy_collection_with_cb(
po->sec,
ini_cleanup_cb,
NULL);
po->sec = NULL;
break;
case INI_MS_ALLOW: TRACE_INFO_STRING("Allow mode", "");
add = 1;
break;
case INI_MS_OVERWRITE: /* Empty existing section */
TRACE_INFO_STRING("Ovewrite mode", "");
error = empty_section(po->merge_sec);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"empty section",
error);
return error;
}
merge = 1;
break;
case INI_MS_DETECT: /* Detect mode */
TRACE_INFO_STRING("Detect mode", "");
po->merge_error = EEXIST;
error = save_error(po->el,
po->seclinenum,
ERR_DUPSECTION,
0);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"save error",
error);
return error;
}
merge = 1;
break;
case INI_MS_MERGE: /* Merge */
default: TRACE_INFO_STRING("Merge mode", "");
merge = 1;
break;
}
if (merge) {
error = merge_section(po);
if (error) {
TRACE_ERROR_NUMBER("Failed to merge section", error);
return error;
}
}
po->merge_sec = NULL;
}
else add = 1;
if (add) {
/* Add section to configuration */
TRACE_INFO_STRING("Now adding collection", "");
error = col_add_collection_to_collection(po->top,
NULL, NULL,
po->sec,
COL_ADD_MODE_EMBED);
if (error) {
TRACE_ERROR_NUMBER("Failed to embed section", error);
return error;
}
po->sec = NULL;
}
}
TRACE_FLOW_EXIT();
-- 1.5.5.6
From 8fb3799dc674770bb622b630267a7a436449069e Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:10:23 -0500 Subject: [PATCH] [INI] Return error in DETECT mode
If in merge DETECT mode and there were no parsing errors return error if there were merge collisions.
ini/ini_parse.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index d9c6d0a9bc71f197eb4bf752fd56958ba6f64df2..3f45ac71ae46dff3413a6d4db5dd59a0838d078b 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -1441,7 +1441,18 @@ int parser_run(struct parser_obj *po) col_delete_item(item);
if (action == PARSE_DONE) {
TRACE_INFO_NUMBER("We are done", error);
/* Report merge error in detect mode
* if no other error was detected. */
if ((po->ret == 0) &&
(po->merge_error != 0) &&
((po->collision_flags & INI_MV1S_DETECT) ||
(po->collision_flags & INI_MV2S_DETECT) ||
(po->collision_flags & INI_MS_DETECT)))
po->ret = po->merge_error;
error = po->ret; break; }
-- 1.5.5.6
From 235393228925b4aee6138820276450c233853464 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:15:12 -0500 Subject: [PATCH] [INI] New test files for section merge
smerge.conf - test file sexpect.conf - file contains output of the smerge.conf processed in different merge modes for sections and values
Makefile.am | 4 +- ini/ini.d/sexpect.conf | 644 ++++++++++++++++++++++++++++++++++++++++++++++++ ini/ini.d/smerge.conf | 33 +++ 3 files changed, 680 insertions(+), 1 deletions(-) create mode 100644 ini/ini.d/sexpect.conf create mode 100644 ini/ini.d/smerge.conf
diff --git a/Makefile.am b/Makefile.am index 1780e9b234e68006af910413b3e8312c9db72c7b..4f9ab3427bb309b19ddec0da5e2125046d03babc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -280,7 +280,9 @@ dist_noinst_DATA += \ ini/ini.d/test.conf \ ini/ini.d/ipa.conf \ ini/ini.d/foo.conf \
- ini/ini.d/mysssd.conf
- ini/ini.d/mysssd.conf \
- ini/ini.d/smerge.conf \
- ini/ini.d/sexpect.conf
check_PROGRAMS += \ ini_config_ut \ diff --git a/ini/ini.d/sexpect.conf b/ini/ini.d/sexpect.conf new file mode 100644 index 0000000000000000000000000000000000000000..6a9222b0a9003ed1a6e9c10401573832980a3706 --- /dev/null +++ b/ini/ini.d/sexpect.conf @@ -0,0 +1,644 @@ +# Section mode: MERGE, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: MERGE, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: MERGE, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+#End of file +# Section mode: MERGE, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: MERGE, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ERROR, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: OVERWRITE, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: ERROR +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: ALLOW +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: DETECT +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: PRESERVE, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ALLOW, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: DETECT, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: DETECT, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: DETECT, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+#End of file +# Section mode: DETECT, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: DETECT, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file diff --git a/ini/ini.d/smerge.conf b/ini/ini.d/smerge.conf new file mode 100644 index 0000000000000000000000000000000000000000..bdec46d86fb6ecd0d39f4b50aca01a53dabd9ebf --- /dev/null +++ b/ini/ini.d/smerge.conf @@ -0,0 +1,33 @@ +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file
1.5.5.6
From a2b8565c919f3b39e9d7eeef9baa29081bb80f43 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:18:48 -0500 Subject: [PATCH] [INI] Test DETECT mode and use new file
Patch adds smerge.conf file to the list of files to test and adds test for the DETECT mode for inidividual values.
ini/ini_parse_ut.c | 30 +++++++++++++++++++++++------- 1 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 9327ebaab2dc529b593e0b550011bbac6b949b94..40c64bb15c0535dd2e8f5e62129a31ae53c3f35f 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -173,6 +173,7 @@ int read_save_test(void) "mysssd", "ipa", "test",
"smerge", NULL };
@@ -203,6 +204,7 @@ int read_again_test(void) "mysssd", "ipa", "test",
"smerge", NULL };
@@ -279,14 +281,25 @@ int create_expect(const char *checkname) fprintf(ff,"#Second value\n"); fprintf(ff,"bar = second value\n"); fprintf(ff,"#End of section\n");
/* Detect */
fprintf(ff,"#Hoho section\n");
fprintf(ff,"[hoho]\n");
fprintf(ff,"#Hoho value\n");
fprintf(ff,"val = hoho\n");
fprintf(ff,"#End of hoho\n");
fprintf(ff,"#Start of section\n");
fprintf(ff,"[foo]\n");
fprintf(ff,"#First value\n");
fprintf(ff,"bar = first value\n");
fprintf(ff,"#Second value\n");
fprintf(ff,"bar = second value\n");
fprintf(ff,"#End of section\n");
fclose(ff);
return EOK;
}
/* Check merge modes */ int merge_values_test(void) { @@ -301,12 +314,14 @@ int merge_values_test(void) uint32_t mflags[] = { INI_MV1S_OVERWRITE, INI_MV1S_ERROR, INI_MV1S_PRESERVE,
INI_MV1S_ALLOW };
INI_MV1S_ALLOW,
INI_MV1S_DETECT };
const char *mstr[] = { "OVERWRITE", "ERROR", "PRESERVE",
"ALLOW" };
"ALLOW",
"DETECT" };
char filename[PATH_MAX]; const char *resname = "./merge.conf.out";
@@ -323,7 +338,7 @@ int merge_values_test(void) return error; }
- for (i = 0; i < 4; i++) {
for (i = 0; i < 5; i++) {
INIOUT(printf("<==== Testing mode %s ====>\n", mstr[i]));
@@ -360,8 +375,9 @@ int merge_values_test(void) ini_config_free_errors(error_list); }
if ((mflags[i] != INI_MV1S_ERROR) ||
((mflags[i] = INI_MV1S_ERROR) && (error != EEXIST))) {
if (((mflags[i] != INI_MV1S_ERROR) && (mflags[i]!= INI_MV1S_DETECT)) ||
((mflags[i] = INI_MV1S_ERROR) && (error != EEXIST)) ||
((mflags[i] = INI_MV1S_DETECT) && (error != EEXIST))) { printf("This is unexpected error %d in mode %d\n", error, mflags[i]); ini_config_destroy(ini_config); simplebuffer_free(sbobj);
-- 1.5.5.6
From 24241d6fa2aa0b7e1595f0600d28238945f647d3 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:20:54 -0500 Subject: [PATCH] [INI] Test for all section merge modes
New test reads smerge.conf in all possible modes and compares the combined result with the sexpect.conf function.
ini/ini_parse_ut.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 188 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 40c64bb15c0535dd2e8f5e62129a31ae53c3f35f..95793dc39cfa73966192802a12d9bdc54c5ec545 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -438,6 +438,193 @@ int merge_values_test(void) resname, checkname, error));
return error;
+}
+/* Check merge modes */ +int merge_section_test(void) +{
- int error = EOK;
- int i, j;
- struct ini_cfgfile *file_ctx = NULL;
- FILE *ff = NULL;
- struct ini_cfgobj *ini_config = NULL;
- char **error_list = NULL;
- struct simplebuffer *sbobj = NULL;
- uint32_t left = 0;
- uint32_t msecflags[] = { INI_MS_MERGE,
INI_MS_ERROR,
INI_MS_OVERWRITE,
INI_MS_PRESERVE,
INI_MS_ALLOW,
INI_MS_DETECT };
- uint32_t mflags[] = { INI_MV2S_OVERWRITE,
INI_MV2S_ERROR,
INI_MV2S_PRESERVE,
INI_MV2S_ALLOW,
INI_MV2S_DETECT };
- const char *secmstr[] = { "MERGE",
"ERROR",
"OVERWRITE",
"PRESERVE",
"ALLOW",
"DETECT" };
- const char *mstr[] = { "OVERWRITE",
"ERROR",
"PRESERVE",
"ALLOW",
"DETECT" };
- char filename[PATH_MAX];
- char checkname[PATH_MAX];
- const char *resname = "./smerge.conf.out";
- char command[PATH_MAX * 3];
- char mode[100];
- char *srcdir;
- srcdir = getenv("srcdir");
- sprintf(filename, "%s/ini/ini.d/smerge.conf",
(srcdir == NULL) ? "." : srcdir);
- sprintf(checkname, "%s/ini/ini.d/sexpect.conf",
(srcdir == NULL) ? "." : srcdir);
- error = simplebuffer_alloc(&sbobj);
- if (error) {
TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error);
return error;
- }
- for (i = 0; i < 6; i++) {
for (j = 0; j < 5; j++) {
INIOUT(printf("<==== Testing mode %s + %s ====>\n",
secmstr[i], mstr[j]));
sprintf(mode, "# Section mode: %s, value mode: %s\n",
secmstr[i], mstr[j]);
error = simplebuffer_add_str(sbobj,
mode,
strlen(mode),
100);
if (error) {
TRACE_ERROR_NUMBER("Failed to add string.",
error);
simplebuffer_free(sbobj);
return error;
}
/* Create config collection */
error = ini_config_create(&ini_config);
if (error) {
printf("Failed to create collection. "
"Error %d.\n", error);
simplebuffer_free(sbobj);
return error;
}
error = ini_config_file_open(filename,
INI_STOP_ON_ANY,
msecflags[i] | mflags[j],
0, /* TBD */
&file_ctx);
if (error) {
printf("Failed to open file for reading. "
"Error %d.\n", error);
ini_config_destroy(ini_config);
simplebuffer_free(sbobj);
return error;
}
error = ini_config_parse(file_ctx,
ini_config);
if (error) {
INIOUT(printf("Failed to parse configuration. "
"Error %d.\n", error));
if (ini_config_error_count(file_ctx)) {
INIOUT(printf("Errors detected while parsing: %s\n",
ini_config_get_filename(file_ctx)));
ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
ini_config_free_errors(error_list);
}
if (((msecflags[i] == INI_MS_ERROR) &&
(error == EEXIST)) ||
((msecflags[i] == INI_MS_DETECT) &&
(error == EEXIST)) ||
((msecflags[i] == INI_MS_MERGE) &&
((mflags[j] == INI_MV2S_ERROR) ||
(mflags[j] == INI_MV2S_DETECT)) &&
(error == EEXIST))) {
INIOUT(printf("This is an expected error "
"%d in mode %d + %d\n",
error,
msecflags[i],
mflags[j]));
/* We do not return here intentionally */
}
else {
printf("This is unexpected error %d in mode %d + %d\n",
error, msecflags[i], mflags[j]);
ini_config_destroy(ini_config);
simplebuffer_free(sbobj);
ini_config_file_close(file_ctx);
return error;
}
}
ini_config_file_close(file_ctx);
INIOUT(col_debug_collection(ini_config->cfg,
COL_TRAVERSE_DEFAULT));
error = ini_config_serialize(ini_config, sbobj);
if (error != EOK) {
printf("Failed to serialize configuration. "
"Error %d.\n", error);
ini_config_destroy(ini_config);
simplebuffer_free(sbobj);
return error;
}
ini_config_destroy(ini_config);
}
- }
- errno = 0;
- ff = fopen(resname, "w");
- if(!ff) {
error = errno;
printf("Failed to open file for writing. Error %d.\n", error);
simplebuffer_free(sbobj);
return error;
- }
- /* Save */
- left = simplebuffer_get_len(sbobj);
- while (left > 0) {
error = simplebuffer_write(fileno(ff), sbobj, &left);
if (error) {
printf("Failed to write back the configuration %d.\n", error);
simplebuffer_free(sbobj);
fclose(ff);
return error;
}
- }
- simplebuffer_free(sbobj);
- fclose(ff);
- sprintf(command,"diff -q %s %s", resname, checkname);
- error = system(command);
- INIOUT(printf("Comparison of %s %s returned: %d\n",
resname, checkname, error));
- return error;
} @@ -449,6 +636,7 @@ int main(int argc, char *argv[]) test_fn tests[] = { read_save_test, read_again_test, merge_values_test,
test_fn t; int i = 0;merge_section_test, NULL };
-- 1.5.5.6
From 8176dad24b0124a634450741f00b2d03c48ce437 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 18:08:27 -0500 Subject: [PATCH] [INI] Separate close and destroy
Allow closing file without destroying the context.
ini/ini_configobj.h | 5 ++++- ini/ini_fileobj.c | 25 +++++++++++++++++++------ ini/ini_parse_ut.c | 10 +++++----- 3 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index f0c6882dbb1e066972f98309bf78a99670b985c5..e728c2e3cbc787586a542a184a07593ad1e03331 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -213,9 +213,12 @@ int ini_config_file_open(const char *filename, uint32_t metadata_flags, struct ini_cfgfile **file_ctx);
-/* Close file context and destroy the object */ +/* Close file context */ void ini_config_file_close(struct ini_cfgfile *file_ctx);
+/* Close file context and destroy the object */ +void ini_config_file_destroy(struct ini_cfgfile *file_ctx);
/* How many errors do we have in the list ? */ unsigned ini_config_error_count(struct ini_cfgfile *file_ctx);
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 7bc599b948563964830f9ade75966cf4f9aa3018..f998eb09d1b5c271be9a316196a510bac39455c2 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -75,12 +75,25 @@ static int valid_collision_flags(uint32_t collision_flags) return 1; }
-/* Close file context and destroy the object */
+/* Close file but not destroy the object */ void ini_config_file_close(struct ini_cfgfile *file_ctx) { TRACE_FLOW_ENTRY();
if(file_ctx) {
if(file_ctx->file) fclose(file_ctx->file);
- }
- TRACE_FLOW_EXIT();
+}
+/* Close file context and destroy the object */ +void ini_config_file_destroy(struct ini_cfgfile *file_ctx) +{
- TRACE_FLOW_ENTRY();
- if(file_ctx) { free(file_ctx->filename); col_destroy_collection(file_ctx->error_list); col_destroy_collection(file_ctx->metadata);
@@ -144,7 +157,7 @@ int ini_config_file_open(const char *filename, new_ctx->filename = malloc(PATH_MAX + 1); if (!(new_ctx->filename)) { error = errno;
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); TRACE_ERROR_NUMBER("Failed to allocate memory for file path.", error); return error;
@@ -155,7 +168,7 @@ int ini_config_file_open(const char *filename, filename); if(error) { TRACE_ERROR_NUMBER("Failed to resolve path", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
@@ -166,7 +179,7 @@ int ini_config_file_open(const char *filename, if (!(new_ctx->file)) { error = errno; TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
@@ -176,7 +189,7 @@ int ini_config_file_open(const char *filename, COL_CLASS_INI_PERROR); if (error) { TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
@@ -185,7 +198,7 @@ int ini_config_file_open(const char *filename, COL_CLASS_INI_META); if (error) { TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 95793dc39cfa73966192802a12d9bdc54c5ec545..f0a95527aa315b559e5c6fa42740fe4a3ba4e4b3 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -91,7 +91,7 @@ int test_one_file(const char *in_filename, /* We do not return here intentionally */ }
- ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx);
INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
@@ -381,13 +381,13 @@ int merge_values_test(void) printf("This is unexpected error %d in mode %d\n", error, mflags[i]); ini_config_destroy(ini_config); simplebuffer_free(sbobj);
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); return error; } /* We do not return here intentionally */ }
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
@@ -572,12 +572,12 @@ int merge_section_test(void) error, msecflags[i], mflags[j]); ini_config_destroy(ini_config); simplebuffer_free(sbobj);
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); return error; } }
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
-- 1.5.5.6
From 29e4a0a028b802eaa3bb1dfbc7a9080fc7f21f4b Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 18:34:02 -0500 Subject: [PATCH] [INI] Function to reopen file
This patch would allow to reopen file and create a new context based on the old one.
ini/ini_configobj.h | 4 ++ ini/ini_fileobj.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 0 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index e728c2e3cbc787586a542a184a07593ad1e03331..3321bd3ea8985b9b12f04ab792fbcac307bbbe2e 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -213,6 +213,10 @@ int ini_config_file_open(const char *filename, uint32_t metadata_flags, struct ini_cfgfile **file_ctx);
+/* Create a file object from existing one */ +int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in,
struct ini_cfgfile **file_ctx_out);
/* Close file context */ void ini_config_file_close(struct ini_cfgfile *file_ctx);
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index f998eb09d1b5c271be9a316196a510bac39455c2..200c7af9de896c1abd26a57a508f9f540475b19d 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -210,6 +210,92 @@ int ini_config_file_open(const char *filename, return error; }
+/* Create a file object from existing one */ +int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in,
struct ini_cfgfile **file_ctx_out)
+{
- int error = EOK;
- struct ini_cfgfile *new_ctx = NULL;
- TRACE_FLOW_ENTRY();
- if ((!file_ctx_in) || (!file_ctx_out)) {
TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
return EINVAL;
- }
- /* Allocate structure */
- errno = 0;
- new_ctx = malloc(sizeof(struct ini_cfgfile));
- if (!new_ctx) {
error = errno;
TRACE_ERROR_NUMBER("Failed to allocate file ctx.", error);
return error;
- }
- new_ctx->filename = NULL;
- new_ctx->file = NULL;
- new_ctx->error_list = NULL;
- new_ctx->metadata = NULL;
- /* TBD - decide whether we actually need an FD.
It will be done when we move the metadata
processing into this function. */
- new_ctx->fd = -1;
- /* Store flags */
- new_ctx->error_level = file_ctx_in->error_level;
- new_ctx->collision_flags = file_ctx_in->collision_flags;
- new_ctx->metadata_flags = file_ctx_in->metadata_flags;
- new_ctx->count = 0;
- /* Copy full file path */
- errno = 0;
- new_ctx->filename = strndup(file_ctx_in->filename, PATH_MAX);
- if (!(new_ctx->filename)) {
error = errno;
ini_config_file_destroy(new_ctx);
TRACE_ERROR_NUMBER("Failed to allocate memory for file path.", error);
return error;
- }
- /* Open file */
- TRACE_INFO_STRING("File", new_ctx->filename);
- errno = 0;
- new_ctx->file = fopen(new_ctx->filename, "r");
- if (!(new_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(new_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_close(new_ctx);
return error;
- }
- error = col_create_collection(&(new_ctx->metadata),
INI_METADATA,
COL_CLASS_INI_META);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* TBD - Add metadata processing here */
- *file_ctx_out = new_ctx;
- TRACE_FLOW_EXIT();
- return error;
+}
/* How many errors do we have in the list ? */ unsigned ini_config_error_count(struct ini_cfgfile *file_ctx) -- 1.5.5.6
From 7030e51bb22e62e6f5d63b0faa923d2151336818 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 19:21:32 -0500 Subject: [PATCH] [INI] Metadata collection is gone
After some more thinking I decided not to use metadata collection. It seems to be an overhead. Patch does following:
- Replaces metadata collection in file context structure with standard file stats
- Removes all operations against old metadata collection
- Defines new flags for data to collect
- Creates a function that consolidates common operations between open and reopen functions.
ini/ini_config_priv.h | 11 +++-- ini/ini_configobj.h | 20 ++++++++ ini/ini_fileobj.c | 121 ++++++++++++++++++++----------------------------- 3 files changed, 75 insertions(+), 77 deletions(-)
diff --git a/ini/ini_config_priv.h b/ini/ini_config_priv.h index 1880c3ff4caa91e7ed3a37e445a20294e76d8037..84742c70ceeb5b493b935c635e81c57d5ef487ce 100644 --- a/ini/ini_config_priv.h +++ b/ini/ini_config_priv.h @@ -22,6 +22,9 @@ #ifndef INI_CONFIG_PRIV_H #define INI_CONFIG_PRIV_H
+#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include "collection.h"
/* Configuration object */ @@ -45,21 +48,19 @@ struct ini_cfgfile { char *filename; /* File stream */ FILE *file;
- /* File descriptor that is passed in */
- int fd; /* Error level */ int error_level; /* Collision flags - define how to merge things */ uint32_t collision_flags;
- /* Collision flags - define how to merge things */
- /* What meta data to collect */ uint32_t metadata_flags; /**********************/ /* Internal variables */ /**********************/ /* Collection of errors detected during parsing */ struct collection_item *error_list;
- /* Metadata about the file */
- struct collection_item *metadata;
- /* File stats */
- struct stat file_stats; /* Count of error lines */ unsigned count;
}; diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 3321bd3ea8985b9b12f04ab792fbcac307bbbe2e..898440252ef3a547566fe2b5e80753d7971a8e47 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -82,6 +82,26 @@ /** @brief Size of the error array. */ #define ERR_MAXPARSE ERR_DUPSECTION
+/**
- @}
- */
+/**
- @defgroup metacollect Constants that define what meta data to collect
- Constants in this section define what meta data to collect
- @{
- */
+/** @brief Do not collect any data. */ +#define INI_META_NONE 0 +/** @brief Collect file stats. */ +#define INI_META_STATS 1
+/**
- @}
- */
/**
- @defgroup collisionflags Flags that define collision resolution logic.
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 200c7af9de896c1abd26a57a508f9f540475b19d..c10b4bf954366ddae90f1d06c53acd0332968599 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -96,7 +96,6 @@ void ini_config_file_destroy(struct ini_cfgfile *file_ctx) if(file_ctx) { free(file_ctx->filename); col_destroy_collection(file_ctx->error_list);
}col_destroy_collection(file_ctx->metadata); if(file_ctx->file) fclose(file_ctx->file); free(file_ctx);
@@ -104,6 +103,47 @@ void ini_config_file_destroy(struct ini_cfgfile *file_ctx) TRACE_FLOW_EXIT(); }
+/* Internal common initialization part */ +static int common_file_init(struct ini_cfgfile *file_ctx) +{
- int error = EOK;
- TRACE_FLOW_ENTRY();
- /* Open file */
- TRACE_INFO_STRING("File", file_ctx->filename);
- errno = 0;
- file_ctx->file = fopen(file_ctx->filename, "r");
- if (!(file_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(file_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
return error;
- }
- /* Collect stats */
- if (file_ctx->metadata_flags & INI_META_STATS) {
errno = 0;
if (fstat(fileno(file_ctx->file),
&(file_ctx->file_stats)) < 0) {
error = errno;
TRACE_ERROR_NUMBER("Failed to get file stats.", error);
return error;
}
- }
- TRACE_FLOW_EXIT();
- return EOK;
+}
/* Create a file object for parsing a config file */ int ini_config_file_open(const char *filename, int error_level, @@ -135,16 +175,9 @@ int ini_config_file_open(const char *filename, return error; }
new_ctx->filename = NULL; new_ctx->file = NULL; new_ctx->error_list = NULL;
new_ctx->metadata = NULL;
/* TBD - decide whether we actually need an FD.
It will be done when we move the metadata
processing into this function. */
new_ctx->fd = -1;
/* Store flags */ new_ctx->error_level = error_level;
@@ -172,39 +205,14 @@ int ini_config_file_open(const char *filename, return error; }
- /* Open file */
- TRACE_INFO_STRING("File", new_ctx->filename);
- errno = 0;
- new_ctx->file = fopen(new_ctx->filename, "r");
- if (!(new_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(new_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- error = col_create_collection(&(new_ctx->metadata),
INI_METADATA,
COL_CLASS_INI_META);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
- /* Do common init */
- error = common_file_init(new_ctx);
- if(error) {
}TRACE_ERROR_NUMBER("Failed to do common init", error); ini_config_file_destroy(new_ctx); return error;
- /* TBD - Add metadata processing here */
- *file_ctx = new_ctx; TRACE_FLOW_EXIT(); return error;
@@ -236,12 +244,6 @@ int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in, new_ctx->filename = NULL; new_ctx->file = NULL; new_ctx->error_list = NULL;
new_ctx->metadata = NULL;
/* TBD - decide whether we actually need an FD.
It will be done when we move the metadata
processing into this function. */
new_ctx->fd = -1;
/* Store flags */ new_ctx->error_level = file_ctx_in->error_level;
@@ -259,39 +261,14 @@ int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in, return error; }
- /* Open file */
- TRACE_INFO_STRING("File", new_ctx->filename);
- errno = 0;
- new_ctx->file = fopen(new_ctx->filename, "r");
- if (!(new_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(new_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_close(new_ctx);
return error;
- }
- error = col_create_collection(&(new_ctx->metadata),
INI_METADATA,
COL_CLASS_INI_META);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
- /* Do common init */
- error = common_file_init(new_ctx);
- if(error) {
}TRACE_ERROR_NUMBER("Failed to do common init", error); ini_config_file_destroy(new_ctx); return error;
- /* TBD - Add metadata processing here */
- *file_ctx_out = new_ctx; TRACE_FLOW_EXIT(); return error;
-- 1.5.5.6
From 87be7cfc4b8cc143a582a38a0d024e166d91df35 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 19:46:15 -0500 Subject: [PATCH] [INI] Check access function
Added check access constants and the check access function. The function is effectively copied from ini_metadata.c The flags are copied from ini_config.h
ini/ini_configobj.h | 35 +++++++++++++++++++++++ ini/ini_fileobj.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 898440252ef3a547566fe2b5e80753d7971a8e47..eccad71c7245f1d035c5133c13b6078fc3e3dc5b 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -104,6 +104,41 @@ */
/**
- @defgroup accesscheck Access control check flags
- @{
- */
+/**
- @brief Validate access mode
- If this flag is specified the mode parameter
- will be matched against the permissions set on the file
- using the provided mask.
- */
+#define INI_ACCESS_CHECK_MODE 0x00000001
+/**
- @brief Validate uid
- Provided uid will be checked against uid
- of the file.
- */
+#define INI_ACCESS_CHECK_UID 0x00000002
+/**
- @brief Validate gid
- Provided gid will be checked against gid
- of the file.
- */
+#define INI_ACCESS_CHECK_GID 0x00000004
+/**
- @}
- */
+/**
- @defgroup collisionflags Flags that define collision resolution logic.
- @{
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index c10b4bf954366ddae90f1d06c53acd0332968599..93a9372f3e37489862a33f1676ca68a532c62441 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -406,3 +406,78 @@ const char *ini_config_get_filename(struct ini_cfgfile *file_ctx) TRACE_FLOW_EXIT(); return ret; }
+/* Check access */ +int ini_config_access_check(struct ini_cfgfile *file_ctx,
uint32_t flags,
uid_t uid,
gid_t gid,
mode_t mode,
mode_t mask)
+{
- int error = EOK;
- TRACE_FLOW_ENTRY();
- flags &= INI_ACCESS_CHECK_MODE |
INI_ACCESS_CHECK_GID |
INI_ACCESS_CHECK_UID;
- if ((file_ctx == NULL) || (flags == 0)) {
TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
return EINVAL;
- }
- /* Check mode */
- if (flags & INI_ACCESS_CHECK_MODE) {
TRACE_INFO_NUMBER("File mode as saved.",
file_ctx->file_stats.st_mode);
file_ctx->file_stats.st_mode &= S_IRWXU | S_IRWXG | S_IRWXO;
TRACE_INFO_NUMBER("File mode adjusted.",
file_ctx->file_stats.st_mode);
TRACE_INFO_NUMBER("Mode as provided.", mode);
mode &= S_IRWXU | S_IRWXG | S_IRWXO;
TRACE_INFO_NUMBER("Mode adjusted.", mode);
/* Adjust mask */
if (mask == 0) mask = S_IRWXU | S_IRWXG | S_IRWXO;
else mask &= S_IRWXU | S_IRWXG | S_IRWXO;
if ((mode & mask) != (file_ctx->file_stats.st_mode & mask)) {
TRACE_INFO_NUMBER("File mode:", (mode & mask));
TRACE_INFO_NUMBER("Mode adjusted.",
(file_ctx->file_stats.st_mode & mask));
TRACE_ERROR_NUMBER("Access denied.", EACCES);
return EACCES;
}
- }
- /* Check uid */
- if (flags & INI_ACCESS_CHECK_UID) {
if (file_ctx->file_stats.st_uid != uid) {
TRACE_ERROR_NUMBER("GID:", file_ctx->file_stats.st_uid);
TRACE_ERROR_NUMBER("GID passed in.", uid);
TRACE_ERROR_NUMBER("Access denied.", EACCES);
return EACCES;
}
- }
- /* Check gid */
- if (flags & INI_ACCESS_CHECK_GID) {
if (file_ctx->file_stats.st_gid != gid) {
TRACE_ERROR_NUMBER("GID:", file_ctx->file_stats.st_gid);
TRACE_ERROR_NUMBER("GID passed in.", gid);
TRACE_ERROR_NUMBER("Access denied.", EACCES);
return EACCES;
}
- }
- TRACE_FLOW_EXIT();
- return error;
+}
1.5.5.6
From c4d2383282b898f4c5914bf720301cdcabf5eb51 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:24:08 -0500 Subject: [PATCH] [INI] Avoid double free
I might squash this patch into one of the previous ones.
ini/ini_fileobj.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 93a9372f3e37489862a33f1676ca68a532c62441..2d47c8ff1d1a613dfc5baa8efd00b05c368f8447 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -82,7 +82,10 @@ void ini_config_file_close(struct ini_cfgfile *file_ctx) TRACE_FLOW_ENTRY();
if(file_ctx) {
if(file_ctx->file) fclose(file_ctx->file);
if(file_ctx->file) {
fclose(file_ctx->file);
file_ctx->file = NULL;
}
}
TRACE_FLOW_EXIT();
-- 1.5.5.6
From 81e90b377b432ef874fda11b6e82f6f0eb894807 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:28:59 -0500 Subject: [PATCH] [INI] Function to check for changes
Added function to detect changes to the configuration file.
ini/ini_configobj.h | 4 ++-- ini/ini_fileobj.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index eccad71c7245f1d035c5133c13b6078fc3e3dc5b..913b91e6abed18d30ba256edc280a1d0aa9d76ef 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -335,8 +335,8 @@ int ini_config_access_check(struct ini_cfgfile *file_ctx,
- device ID
- i-node
*/ -int ini_config_changed(struct ini_cfgfile *file_ctx,
struct ini_cfgfile *file_ctx_saved,
+int ini_config_changed(struct ini_cfgfile *file_ctx1,
struct ini_cfgfile *file_ctx2, int *changed);
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 2d47c8ff1d1a613dfc5baa8efd00b05c368f8447..6de963971a0e9501fb86c23ee5faf6bfb5824bf0 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -484,3 +484,40 @@ int ini_config_access_check(struct ini_cfgfile *file_ctx, return error;
}
+/* Determins if two file context different by comparing
- time stamp
- device ID
- i-node
- */
+int ini_config_changed(struct ini_cfgfile *file_ctx1,
struct ini_cfgfile *file_ctx2,
int *changed)
+{
- int error = EOK;
- TRACE_FLOW_ENTRY();
- if ((file_ctx1 == NULL) ||
(file_ctx2 == NULL) ||
(changed == NULL)) {
TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
return EINVAL;
- }
- *changed = 0;
- if((file_ctx1->file_stats.st_mtime !=
file_ctx2->file_stats.st_mtime) ||
(file_ctx1->file_stats.st_dev !=
file_ctx2->file_stats.st_dev) ||
(file_ctx1->file_stats.st_ino !=
file_ctx2->file_stats.st_ino)) {
TRACE_INFO_STRING("File changed!", "");
*changed = 1;
- }
- TRACE_FLOW_EXIT();
- return error;
+}
1.5.5.6
From 2ec4163bcbbcfa6c025b32cdbdbd3adf8c7a84f2 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:31:33 -0500 Subject: [PATCH] [INI] Tests for access and changes
Patch adds two functions. One tests permissions, another validates if the file has changed or not.
ini/ini_parse_ut.c | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 248 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index f0a95527aa315b559e5c6fa42740fe4a3ba4e4b3..f5b1c2c5b4e82de2baf29955901da28afc082cbb 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -625,10 +625,256 @@ int merge_section_test(void) resname, checkname, error));
return error;
+}
+int startup_test(void) +{
- int error = EOK;
- struct ini_cfgfile *file_ctx = NULL;
- struct ini_cfgobj *ini_config = NULL;
- char **error_list = NULL;
- char filename[PATH_MAX];
- char *srcdir;
- srcdir = getenv("srcdir");
- sprintf(filename, "%s/ini/ini.d/foo.conf",
(srcdir == NULL) ? "." : srcdir);
- INIOUT(printf("<==== Startup test ====>\n"));
- /* Open config file */
- error = ini_config_file_open(filename,
INI_STOP_ON_NONE,
0,
INI_META_STATS,
&file_ctx);
- if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
return error;
- }
- /* We will check just permissions here. */
- error = ini_config_access_check(file_ctx,
INI_ACCESS_CHECK_MODE, /* add uid & gui flags
* in real case
*/
0, /* <- will be real uid in real case */
0, /* <- will be real gid in real case */
0440, /* Checking for r--r----- */
0);
- /* This check is expected to fail since
* the actual permissions on the test file are: rw-rw-r--
*/
- if (!error) {
printf("Expected error got success!\n");
ini_config_file_destroy(file_ctx);
return EACCES;
- }
- error = ini_config_access_check(
file_ctx,
INI_ACCESS_CHECK_MODE, /* add uid & gui flags
* in real case
*/
0, /* <- will be real uid in real case */
0, /* <- will be real gid in real case */
0664, /* Checkling for rw-rw-r-- */
0);
- if (error) {
printf("Access check failed %d!\n", error);
ini_config_file_destroy(file_ctx);
return EACCES;
- }
- /* Create config object */
- error = ini_config_create(&ini_config);
- if (error) {
printf("Failed to create collection. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
- }
- error = ini_config_parse(file_ctx,
ini_config);
- if (error) {
INIOUT(printf("Failed to parse configuration. Error %d.\n", error));
if (ini_config_error_count(file_ctx)) {
INIOUT(printf("Errors detected while parsing: %s\n",
ini_config_get_filename(file_ctx)));
ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
ini_config_free_errors(error_list);
}
/* We do not return here intentionally */
- }
- ini_config_file_destroy(file_ctx);
- INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
- ini_config_destroy(ini_config);
- return 0;
+}
+int reload_test(void) +{
int error = EOK;
struct ini_cfgfile *file_ctx = NULL;
struct ini_cfgfile *file_ctx_new = NULL;
char infile[PATH_MAX];
char outfile[PATH_MAX];
char command[PATH_MAX * 3];
char *srcdir;
char *builddir;
int changed = 0;
INIOUT(printf("<==== Reload test ====>\n"));
srcdir = getenv("srcdir");
sprintf(infile, "%s/ini/ini.d/foo.conf",
(srcdir == NULL) ? "." : srcdir);
builddir = getenv("builddir");
sprintf(outfile, "%s/foo.conf",
(builddir == NULL) ? "." : builddir);
sprintf(command, "cp %s %s", infile, outfile);
errno = 0;
if(system(command)) {
error = errno;
printf("Failed to run copy command %d.\n", error);
return error;
}
/* Open config file */
error = ini_config_file_open(outfile,
INI_STOP_ON_NONE,
0,
INI_META_STATS,
&file_ctx);
if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
return error;
}
error = ini_config_access_check(
file_ctx,
INI_ACCESS_CHECK_MODE, /* add uid & gui flags
* in real case
*/
0, /* <- will be real uid in real case */
0, /* <- will be real gid in real case */
0664, /* Checkling for rw-rw-r-- */
0);
if (error) {
printf("Access check failed %d!\n", error);
ini_config_file_destroy(file_ctx);
return EACCES;
}
/* ... Create config object and read configuration - not shown here.
* See other examples ... */
/* Now close file but leave the context around */
ini_config_file_close(file_ctx);
/* Some time passed and we received a signal to reload... */
error = ini_config_file_reopen(file_ctx, &file_ctx_new);
if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
changed = 0;
error = ini_config_changed(file_ctx,
file_ctx_new,
&changed);
if (error) {
printf("Failed to compare files. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return error;
}
/* Check if file changed */
if (changed) {
printf("File changed when it shouldn't. This is unexpected error.\n");
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return EINVAL;
}
/* Close file */
ini_config_file_destroy(file_ctx_new);
/* Emulate as if file changed */
errno = 0;
if (unlink(outfile)) {
error = errno;
printf("Failed to delete file %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
sleep(1);
errno = 0;
if (system(command)) {
error = errno;
printf("Failed to run copy command %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
/* Read again */
file_ctx_new = NULL;
error = ini_config_file_reopen(file_ctx, &file_ctx_new);
if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
changed = 0;
error = ini_config_changed(file_ctx,
file_ctx_new,
&changed);
if (error) {
printf("Failed to compare files. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return error;
}
/* Check if file changed */
if (!changed) {
printf("File did not change when it should. This is an error.\n");
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return EINVAL;
}
/* We do not need original context any more. */
ini_config_file_destroy(file_ctx);
/* New context is now original context */
file_ctx = file_ctx_new;
/* ... Create config object and read configuration - not shown here.
* See other examples ... */
ini_config_file_destroy(file_ctx);
return 0;
}
/* Main function of the unit test */ int main(int argc, char *argv[]) { @@ -637,6 +883,8 @@ int main(int argc, char *argv[]) read_again_test, merge_values_test, merge_section_test,
startup_test,
test_fn t; int i = 0;reload_test, NULL };
-- 1.5.5.6
From 8654e77c640ac19e6997542589fbd1500ae6532d Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:45:39 -0500 Subject: [PATCH] [INI] Rename error print function
All config file processing functions start with "ini_config". The only function that does not comply is ini_print_errors. We can't rename it since it is a part of the current active interface. I marked that function needs to be removed when we remove old interface and created a copy with the correct name. I also updated unit test accordingly.
ini/ini_configobj.h | 5 +---- ini/ini_parse_ut.c | 8 ++++---- ini/ini_print.c | 24 ++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 913b91e6abed18d30ba256edc280a1d0aa9d76ef..7089b62da31887e21eeffd6dceff76907ca9f1a6 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -300,10 +300,7 @@ int ini_config_copy(struct ini_cfgobj *ini_config, struct ini_cfgobj **ini_new);
/* Function to print errors from the list */ -void ini_print_errors(FILE *file, char **error_list);
+void ini_config_print_errors(FILE *file, char **error_list);
/* Merge two configurations together creating a new one */ int ini_config_merge(struct ini_cfgobj *first, diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index f5b1c2c5b4e82de2baf29955901da28afc082cbb..696735aacee25fc71f2b60708aaf3d0e14081f2c 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -85,7 +85,7 @@ int test_one_file(const char *in_filename, INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); } /* We do not return here intentionally */
@@ -371,7 +371,7 @@ int merge_values_test(void) INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); }
@@ -548,7 +548,7 @@ int merge_section_test(void) INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); }
@@ -706,7 +706,7 @@ int startup_test(void) INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); } /* We do not return here intentionally */
diff --git a/ini/ini_print.c b/ini/ini_print.c index 1dcfa54bfd72daf2c790d04c37ff2b3107eb7295..42bd6fc221c71bf4f390a79e02a4928ecf747bd9 100644 --- a/ini/ini_print.c +++ b/ini/ini_print.c @@ -461,6 +461,9 @@ void print_config_parsing_errors(FILE *file,
/* Function to print errors from the list */ +/* THIS FUNCTION SHOUD BE REMOVED WHEN
- OLD INTERFACE IS REMOVED - TBD.
- */
void ini_print_errors(FILE *file, char **error_list) { unsigned count = 0; @@ -480,3 +483,24 @@ void ini_print_errors(FILE *file, char **error_list) TRACE_FLOW_EXIT(); return; }
+/* Function to print errors from the list */ +void ini_config_print_errors(FILE *file, char **error_list) +{
- unsigned count = 0;
- TRACE_FLOW_ENTRY();
- if (!error_list) {
TRACE_FLOW_STRING("List is empty.", "");
return;
- }
- while (error_list[count]) {
fprintf(file, "%s\n", error_list[count]);
count++;
- }
- TRACE_FLOW_EXIT();
- return;
+}
1.5.5.6
From baa1b6eb9604729fa678a0988138a7aaa3f5c9c6 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:58:24 -0500 Subject: [PATCH] [INI] Initialize variables in loops
It occured to me that one of the issues that Coverity did not like (and I could not understand what it is complaining about) is related to intializing the variables in the loop. This patch adds initialization in the loops.
ini/ini_parse_ut.c | 4 ++++ ini/ini_valueobj_ut.c | 3 +++ 2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 696735aacee25fc71f2b60708aaf3d0e14081f2c..5de79d954673a194bd080660f967c7b304dbdefe 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -343,6 +343,7 @@ int merge_values_test(void) INIOUT(printf("<==== Testing mode %s ====>\n", mstr[i]));
/* Create config collection */
ini_config = NULL; error = ini_config_create(&ini_config); if (error) { printf("Failed to create collection. Error %d.\n", error);
@@ -350,6 +351,7 @@ int merge_values_test(void) return error; }
file_ctx = NULL; error = ini_config_file_open(filename, INI_STOP_ON_ANY, mflags[i],
@@ -517,6 +519,7 @@ int merge_section_test(void) }
/* Create config collection */
ini_config = NULL; error = ini_config_create(&ini_config); if (error) { printf("Failed to create collection. "
@@ -525,6 +528,7 @@ int merge_section_test(void) return error; }
file_ctx = NULL; error = ini_config_file_open(filename, INI_STOP_ON_ANY, msecflags[i] | mflags[j],
diff --git a/ini/ini_valueobj_ut.c b/ini/ini_valueobj_ut.c index af62c140d215f9298dd5671d8aa544a84ef254b1..c07ec85772084f1fd6dd157a9befae26c9aa6806 100644 --- a/ini/ini_valueobj_ut.c +++ b/ini/ini_valueobj_ut.c @@ -404,6 +404,7 @@ int vo_basic_test(void) return error; }
vo = NULL; error = value_create_new(strvalue, strlen(strvalue), INI_VALUE_CREATED,
@@ -541,6 +542,7 @@ int vo_copy_test(void)
TRACE_INFO_NUMBER("Iteration:", wrap);
vo_copy = NULL; error = value_copy(vo, &vo_copy); if (error) { printf("Failed to create a new value object %d.\n", error);
@@ -559,6 +561,7 @@ int vo_copy_test(void) }
/* Get comment from the value */
ic = NULL; error = value_extract_comment(vo_copy, &ic); if (error) { printf("Failed to extract comment %d.\n", error);
-- 1.5.5.6
From f9f8998bef402648d2565ada6789305e0c0ad46e Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Mon, 3 Jan 2011 14:36:47 -0500 Subject: [PATCH] [INI] Exposing functions
This patch makes two internal functions resusable from different source modules.
ini/ini_config_priv.h | 8 ++++++++ ini/ini_fileobj.c | 2 +- ini/ini_parse.c | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/ini/ini_config_priv.h b/ini/ini_config_priv.h index 84742c70ceeb5b493b935c635e81c57d5ef487ce..e714774a68a5e16b7a221f712abe2ea9179e88c8 100644 --- a/ini/ini_config_priv.h +++ b/ini/ini_config_priv.h @@ -82,4 +82,12 @@ void ini_cleanup_cb(const char *property, /* Get parsing error */ const char *ini_get_error_str(int parsing_error, int family);
+/* Check if collision flags are valid */ +int valid_collision_flags(uint32_t collision_flags);
+/* Empty section */ +int empty_section(struct collection_item *sec);
#endif diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 6de963971a0e9501fb86c23ee5faf6bfb5824bf0..30a2f1545d7b22dcab3bb4eccd53c91fe7edfd62 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -34,7 +34,7 @@
/* Check if collision flags are valid */ -static int valid_collision_flags(uint32_t collision_flags) +int valid_collision_flags(uint32_t collision_flags) { uint32_t flag;
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 3f45ac71ae46dff3413a6d4db5dd59a0838d078b..e3ae938847b867780cb0d0d60d12868826952a85 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -357,7 +357,7 @@ static int check_section_collision(struct parser_obj *po) }
/* Clean all items in the section */ -static int empty_section(struct collection_item *sec) +int empty_section(struct collection_item *sec) { int error = EOK; struct collection_item *item = NULL; -- 1.5.5.6
From 02c14799196cd1ffd0f53c6b2e995ac17a7f8917 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Mon, 3 Jan 2011 14:41:03 -0500 Subject: [PATCH] [INI] Function to merge two configurations
This patch provides first draft of the implementation of the code to merge different configurations. It is similar to the merge code that is implemented inside the parser but different since it is not done during parsing of one file but addresses use case when the configuration is provided by different files that need to be merged together.
NOTE: It would make more sence to review function by function from bottom of the patch rather than from the top.
ini/ini_configobj.c | 456 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 456 insertions(+), 0 deletions(-)
diff --git a/ini/ini_configobj.c b/ini/ini_configobj.c index 5e5e40b566abdf3ce2cbc225babe4b1e20c2dd47..d8583a224e8eebc4365df3909b6bac7c98477dc5 100644 --- a/ini/ini_configobj.c +++ b/ini/ini_configobj.c @@ -30,11 +30,19 @@ #include "ini_config_priv.h" #include "ini_defines.h" #include "ini_valueobj.h" +#include "ini_configobj.h"
/* This constant belongs to ini_defines.h. Move from ini_config - TBD */ #define COL_CLASS_INI_BASE 20000 #define COL_CLASS_INI_CONFIG COL_CLASS_INI_BASE + 0
+struct merge_data {
- struct collection_item *ci;
- uint32_t flags;
- int error;
- int found;
+};
/* Callback */ void ini_cleanup_cb(const char *property, int property_len, @@ -254,3 +262,451 @@ int ini_config_copy(struct ini_cfgobj *ini_config, TRACE_FLOW_EXIT(); return error; }
+/* Callback to process merging of the sections */ +static int merge_section_handler(const char *property,
int property_len,
int type,
void *data,
int length,
void *custom_data,
int *dummy)
+{
- int error = EOK;
- struct value_obj *vo = NULL;
- struct value_obj *new_vo = NULL;
- struct value_obj *vo_old = NULL;
- struct merge_data *passed_data;
- struct collection_item *acceptor = NULL;
- struct collection_item *item = NULL;
- unsigned insertmode;
- uint32_t mergemode;
- int suppress = 0;
- int doinsert = 0;
- TRACE_FLOW_ENTRY();
- if ((type != COL_TYPE_BINARY) ||
((type == COL_TYPE_BINARY) &&
(strncmp(property, INI_SECTION_KEY,
sizeof(INI_SECTION_KEY)) == 0))) {
/* Skip items we do not care about */
TRACE_FLOW_EXIT();
return EOK;
- }
- /* Get value */
- vo = *((struct value_obj **)(data));
- /* Copy it */
- error = value_copy(vo, &new_vo);
- if (error) {
TRACE_ERROR_NUMBER("Failed to copy value", error);
return error;
- }
- passed_data = (struct merge_data *)(custom_data);
- acceptor = passed_data->ci;
- mergemode = passed_data->flags & INI_MV2S_MASK;
- switch (mergemode) {
- case INI_MV2S_ERROR: insertmode = COL_INSERT_DUPERROR;
doinsert = 1;
break;
- case INI_MV2S_PRESERVE: insertmode = COL_INSERT_DUPERROR;
doinsert = 1;
suppress = 1;
break;
- case INI_MV2S_ALLOW: insertmode = COL_INSERT_NOCHECK;
doinsert = 1;
break;
- case INI_MV2S_OVERWRITE: /* Special handling */
- case INI_MV2S_DETECT:
- default:
break;
- }
- /* Do not insert but search for dups first */
- if (!doinsert) {
TRACE_INFO_STRING("Overwrite mode. Looking for:",
property);
error = col_get_item(acceptor,
property,
COL_TYPE_BINARY,
COL_TRAVERSE_DEFAULT,
&item);
if (error) {
TRACE_ERROR_NUMBER("Failed searching for dup", error);
value_destroy(new_vo);
return error;
}
/* Check if there is a dup */
if (item) {
/* Check if we are in the detect mode */
if (mergemode == INI_MV2S_DETECT) {
passed_data->error = EEXIST;
doinsert = 1;
insertmode = COL_INSERT_NOCHECK;
}
else {
/* Dup exists - update it */
vo_old = *((struct value_obj **)(col_get_item_data(item)));
error = col_modify_binary_item(item,
NULL,
&new_vo,
sizeof(struct value_obj *));
if (error) {
TRACE_ERROR_NUMBER("Failed updating the value", error);
value_destroy(new_vo);
return error;
}
/* If we failed to update it is better to leak then crash,
* so destroy original value only on the successful update.
*/
value_destroy(vo_old);
}
}
else {
/* No dup found so we can insert with no check */
doinsert = 1;
insertmode = COL_INSERT_NOCHECK;
}
- }
- if (doinsert) {
/* Add value to collection */
error = col_insert_binary_property(acceptor,
NULL,
COL_DSP_END,
NULL,
0,
insertmode,
property,
&new_vo,
sizeof(struct value_obj *));
if (error) {
value_destroy(new_vo);
if ((suppress) && (error == EEXIST)) {
TRACE_INFO_STRING("Preseved exisitng value",
property);
}
else {
/* Check if this is a critical error or not */
if ((mergemode == INI_MV1S_ERROR) && (error == EEXIST)) {
TRACE_ERROR_NUMBER("Failed to add value object "
"to the section", error);
passed_data->error = EEXIST;
*dummy = 1;
}
else {
TRACE_ERROR_NUMBER("Failed to add value object"
" to the section", error);
return error;
}
}
}
- }
- TRACE_FLOW_EXIT();
- return error;
+}
+/* Internal function to merge two configs */ +static int merge_two_sections(struct collection_item *acceptor,
struct collection_item *donor,
uint32_t flags)
+{
- int error = EOK;
- struct merge_data data;
- TRACE_FLOW_ENTRY();
- data.ci = acceptor;
- data.flags = flags;
- data.error = 0;
- data.found = 0;
- error = col_traverse_collection(donor,
COL_TRAVERSE_ONELEVEL,
merge_section_handler,
(void *)(&data));
- if (error) {
TRACE_ERROR_NUMBER("Merge values failed", error);
return error;
- }
- TRACE_FLOW_EXIT();
- return data.error;
+}
+/* Callback to process the accepting config */ +static int acceptor_handler(const char *property,
int property_len,
int type,
void *data,
int length,
void *custom_data,
int *dummy)
+{
- int error = EOK;
- struct merge_data *passed_data;
- struct collection_item *acceptor = NULL;
- struct collection_item *donor = NULL;
- uint32_t mergemode;
- TRACE_FLOW_ENTRY();
- passed_data = (struct merge_data *)(custom_data);
- passed_data->found = 1;
- donor = passed_data->ci;
- acceptor = *((struct collection_item **)(data));
- mergemode = passed_data->flags & INI_MS_MASK;
- switch (mergemode) {
- case INI_MS_ERROR: /* Report error and return */
TRACE_INFO_STRING("Error ",
"duplicate section");
passed_data->error = EEXIST;
break;
- case INI_MS_PRESERVE: /* Preserve what we have */
TRACE_INFO_STRING("Preserve mode", "");
break;
- case INI_MS_OVERWRITE: /* Empty existing section */
TRACE_INFO_STRING("Ovewrite mode", "");
error = empty_section(acceptor);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"empty section",
error);
return error;
}
error = merge_two_sections(acceptor,
donor,
passed_data->flags);
if (error) {
TRACE_ERROR_NUMBER("Failed to merge "
"sections", error);
return error;
}
break;
- case INI_MS_DETECT: /* Detect mode */
TRACE_INFO_STRING("Detect mode", "");
passed_data->error = EEXIST;
passed_data->found = 0;
break;
- case INI_MS_MERGE: /* Merge */
- default: TRACE_INFO_STRING("Merge mode", "");
error = merge_two_sections(acceptor,
donor,
passed_data->flags);
if (error) {
if (error != EEXIST) {
TRACE_ERROR_NUMBER("Failed to merge "
"sections", error);
return error;
}
passed_data->error = error;
}
break;
- }
- *dummy = 1;
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Callback to process the donating config */ +static int donor_handler(const char *property,
int property_len,
int type,
void *data,
int length,
void *custom_data,
int *dummy)
+{
- int error = EOK;
- struct merge_data *passed_data;
- struct merge_data acceptor_data;
- struct collection_item *new_ci = NULL;
- TRACE_FLOW_ENTRY();
- passed_data = (struct merge_data *)(custom_data);
- /* All section are subcollections */
- if(type == COL_TYPE_COLLECTIONREF) {
acceptor_data.flags = passed_data->flags;
acceptor_data.ci = *((struct collection_item **)(data));
acceptor_data.error = 0;
acceptor_data.found = 0;
/* Try to resolve collision only non ALLOW modes */
if (!(acceptor_data.flags & INI_MS_ALLOW)) {
error = col_get_item_and_do(passed_data->ci,
property,
COL_TYPE_COLLECTIONREF,
COL_TRAVERSE_ONELEVEL,
acceptor_handler,
(void *)(&acceptor_data));
if (error) {
TRACE_ERROR_NUMBER("Critical error", error);
return error;
}
}
/* Was duplicate found ? */
if (acceptor_data.found) {
/* Check for logical error. It can be only EEXIST */
if (acceptor_data.error) {
/* Save error anyway */
passed_data->error = acceptor_data.error;
/* If it is section DETECT or MERGE+DETECT */
if ((passed_data->flags & INI_MS_DETECT) ||
((passed_data->flags & INI_MS_MERGE) &&
(passed_data->flags & INI_MV2S_DETECT))) {
TRACE_INFO_NUMBER("Non-critical error",
acceptor_data.error);
}
else {
/* In any other mode we need to stop */
TRACE_INFO_NUMBER("Merge error detected",
acceptor_data.error);
/* Force stop */
*dummy = 1;
}
}
}
else {
/* Not found? Then create a copy... */
error = col_copy_collection_with_cb(&new_ci,
acceptor_data.ci,
NULL,
COL_COPY_NORMAL,
ini_copy_cb,
NULL);
if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
return error;
}
/* ... and embed into the existing collection */
error = col_add_collection_to_collection(passed_data->ci,
NULL,
NULL,
new_ci,
COL_ADD_MODE_EMBED);
if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
col_destroy_collection(new_ci);
return error;
}
}
- }
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Internal function to merge two configs */ +static int merge_configs(struct ini_cfgobj *first,
struct ini_cfgobj *second,
uint32_t collision_flags)
+{
- int error = EOK;
- struct merge_data data;
- TRACE_FLOW_ENTRY();
- data.ci = first->cfg;
- data.flags = collision_flags;
- data.error = 0;
- data.found = 0;
- error = col_traverse_collection(second->cfg,
COL_TRAVERSE_ONELEVEL,
donor_handler,
(void *)(&data));
- if (error) {
TRACE_ERROR_NUMBER("Merge failed", error);
return error;
- }
- /* If boundaries are different re-align the values */
- if (first->boundary != second->boundary) {
error = ini_config_set_wrap(first, first->boundary);
if (error) {
TRACE_ERROR_NUMBER("Failed to re-align", error);
return error;
}
- }
- TRACE_FLOW_EXIT();
- return error;
+}
+/* Merge two configurations together creating a new one */ +int ini_config_merge(struct ini_cfgobj *first,
struct ini_cfgobj *second,
uint32_t collision_flags,
struct ini_cfgobj **result)
+{
- int error = EOK;
- struct ini_cfgobj *new_co = NULL;
- TRACE_FLOW_ENTRY();
- /* Check input params */
- if ((!first) ||
(!second) ||
(!result)) {
TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
return EINVAL;
- }
- /* Check collision flags */
- if (!valid_collision_flags(collision_flags)) {
TRACE_ERROR_NUMBER("Invalid flags.", EINVAL);
return EINVAL;
- }
- /* Create a copy */
- /* TBD - create a COMPACT copy */
- error = ini_config_copy(first, &new_co);
- if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
return error;
- }
- /* Merge configs */
- error = merge_configs(new_co, second, collision_flags);
- if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
ini_config_destroy(new_co);
return error;
- }
- *result = new_co;
- TRACE_FLOW_EXIT();
- return error;
+}
1.5.5.6
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
Sumit Bose wrote:
On Mon, Jan 03, 2011 at 06:12:38PM -0500, Dmitri Pal wrote:
Please see the attached patches. I tried to split the patches logically into manageable sets. Unfortunately I made a minor mistake and I am afraid I will do something wrong to fix it. I merged two wrong patches. Fortunately it was three liner with 1 liner so it is not a big of the deal but I am really scared that I will do something wrong and loose the work I have done. So I hope it is Ok to send it as is.
0001--INI-Making-Coverity-happy.patch <- this is the patch I submitted earlier that I merged by mistake. I was supposed to merge it with patch 25 but picked the wrong one instead. Patch 25 addresses the real issue found by Coverity as mentioned in Stephen's review mail but it did not apply cleanly since it relies on some code from the patches in the middle.
0002--INI-Adding-missing-function-declararion.patch <- this is the patch that was rejected from the second set sent earlier. Fixed according to review comment.
0003--BUILD-Allow-trace-per-component.patch <- This patch allows tracing per component
The following set of patches introduces the merging of sections during the reading of the file: 0004--INI-New-error-codes-and-messages.patch 0005--INI-New-merge-flags.patch 0006--INI-Add-new-vars-to-parse-structure.patch 0007--INI-Add-save_error-function.patch 0008--INI-Change-parse_error-to-use-save_error.patch 0009--INI-Preparing-for-merging-sections.patch 0010--INI-Enhance-value-processing.patch 0011--INI-Use-section-line-number.patch 0012--INI-Refactor-section-processing.patch 0013--INI-Return-error-in-DETECT-mode.patch 0014--INI-New-test-files-for-section-merge.patch 0015--INI-Test-DETECT-mode-and-use-new-file.patch 0016--INI-Test-for-all-section-merge-modes.patch
Patches related porting of the meta data from old way of doing things to the new way of doing things: 0017--INI-Separate-close-and-destroy.patch
You should set file_ctx->file to NULL after fclose(file_ctx->file) to make the if(file_ctx->file) checks work in ini_config_file_close() and ini_config_file_destroy().
There are tab indents in merge_values_test() and merge_section_test().
0018--INI-Function-to-reopen-file.patch 0019--INI-Metadata-collection-is-gone.patch
You remove metadata from struct ini_cfgfile without removing all references to metadata in the same patch. You should make clear that more patches are needed to create a buildable version of libini or remove all references in this patch.
I wonder is the following is a change of defaults. With the patch the new file_ctx->file_stats are only set if INI_META_STATS is set while previously file-ctx>metadata was set unconditionally.
0020--INI-Check-access-function.patch
I wonder if it is necessary to return EINVAL if flags == 0. I would say in this case no checks are requested and EOK could be returned?
I would prefer to copy file_ctx->file_stats.st_mode instead of modifying it, e.g. you might want to know the file type later on.
0021--INI-Avoid-double-free.patch <- patch related to 17 (missed check)
oops, so you can ignore my comment to 00017, let's see if there is also a patch for ini_config_file_destroy(). "I might squash this patch into one of the previous ones." Yes, please.
0022--INI-Function-to-check-for-changes.patch 0023--INI-Tests-for-access-and-changes.patch
Why do you need sleep(1) ? The man page of system() does not mention that system() sets errno, please check the return code instead.
0024--INI-Rename-error-print-function.patch <- rename error printing function for consistency with new interface
Maybe ini_print_errors() should print a deprecated warning to make migrations easier.
0025--INI-Initialize-variables-in-loops.patch <- Coverity issue addressed. Related to patch 0001.
0026--INI-Exposing-functions.patch <- Make some internal functions reusable
There is also patch 27. It is a piece of new functionality. It is a preview. Please see the comment before reviewing it. Do I need to split it into multiple patches or it is Ok as is? It is pretty big but all changes are in one file and logically related. The UNIT test is missing so I am not claiming it actually works as expected.
I didn't had a look at 0027 so far.
bye, Sumit
Thank you for the review. I will address the issues as soon as I find a moment.
-- Thank you, Dmitri Pal
Sr. Engineering Manager IPA project, Red Hat Inc.
Looking to carve out IT costs? www.redhat.com/carveoutcosts/
From 2cb4d6ad0bfad2170e09152379f29de2b9c29196 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Fri, 24 Dec 2010 00:38:48 -0500 Subject: [PATCH] [INI] Making Coverity happy
Coverity found issues 10078 & 10079. This patch should make it happy, however I think that Coverity is wrong unless I am missing something. If I am I hope that this patch would be able to reveal the real issue if any. For now just renaming a variable.
[INI] Added missing initialization
One liner to initialize a variable.
ini/ini_configobj.c | 2 +- ini/ini_valueobj_ut.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/ini/ini_configobj.c b/ini/ini_configobj.c index 3e5dec4733a49d03e44185637592f0efdbe7db3c..5e5e40b566abdf3ce2cbc225babe4b1e20c2dd47 100644 --- a/ini/ini_configobj.c +++ b/ini/ini_configobj.c @@ -215,7 +215,7 @@ int ini_config_copy(struct ini_cfgobj *ini_config, struct ini_cfgobj **ini_new) { int error = EOK;
- struct ini_cfgobj *new_co;
struct ini_cfgobj *new_co = NULL;
TRACE_FLOW_ENTRY();
diff --git a/ini/ini_valueobj_ut.c b/ini/ini_valueobj_ut.c index 767a64cc2fe624800bed7e9dc4b53a90fa2d59c2..af62c140d215f9298dd5671d8aa544a84ef254b1 100644 --- a/ini/ini_valueobj_ut.c +++ b/ini/ini_valueobj_ut.c @@ -378,6 +378,7 @@ int vo_basic_test(void) */
struct value_obj *vo = NULL;
- struct value_obj *other_vo = NULL; uint32_t wrap = 0; struct ini_comment *ic = NULL; FILE *ff = NULL;
@@ -429,7 +430,7 @@ int vo_basic_test(void) }
/* Run other create test here */
- error = other_create_test(ff, &vo);
- error = other_create_test(ff, &other_vo); if (error) { printf("Create test failed %d.\n", error); fclose(ff);
@@ -437,15 +438,15 @@ int vo_basic_test(void) }
/* Run modify test here */
- error = modify_test(ff, vo);
- error = modify_test(ff, other_vo); if (error) { printf("Modify test failed %d.\n", error); fclose(ff);
value_destroy(vo);
}value_destroy(other_vo); return error;
- value_destroy(vo);
value_destroy(other_vo);
ic = NULL;
-- 1.5.5.6
From 68ecd60fac51706c743a5c4a4cfe87ec6ca9d304 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Fri, 24 Dec 2010 21:27:24 -0500 Subject: [PATCH] [INI] Adding missing function declararion.
One-liner that eliminates compilation warning.
[INI] Include proper header
Value object needs its own header file.
ini/ini_valueobj.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/ini/ini_valueobj.c b/ini/ini_valueobj.c index a90fa451468aecc6c04f4411675ab67613a59cbe..f196c1ab3195db7cbe616e6e1275c656919fe156 100644 --- a/ini/ini_valueobj.c +++ b/ini/ini_valueobj.c @@ -29,6 +29,7 @@ #include "ini_comment.h" #include "ini_defines.h" #include "trace.h" +#include "ini_valueobj.h"
struct value_obj { struct ref_array *raw_lines; -- 1.5.5.6
From 574be6d8c0896c8bee0c16224f52c2dbea48a44e Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Fri, 24 Dec 2010 22:38:42 -0500 Subject: [PATCH] [BUILD] Allow trace per component
This patch add ability to build tracing for each component independently.
Makefile.am | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- configure.ac | 15 ++++++++++++++- 2 files changed, 60 insertions(+), 5 deletions(-)
diff --git a/Makefile.am b/Makefile.am index 0946169308bab6585c93cca36d45b360b565f6b5..1780e9b234e68006af910413b3e8312c9db72c7b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,7 @@ -TRACE_LEVEL=@TRACE_VAR@ +TRACE_INI=@TRACE_INI@ +TRACE_COLLECTION=@TRACE_COLLECTION@ +TRACE_REFARRAY=@TRACE_REFARRAY@ +TRACE_BASICOBJECTS=@TRACE_BASICOBJECTS@
RPMBUILD ?= $(PWD)/rpmbuild
@@ -28,8 +31,7 @@ AM_CPPFLAGS = \ -I$(srcdir)/ini \ -I$(srcdir)/basicobjects \ -I$(srcdir) \
- -I$(srcdir)/trace \
- $(TRACE_LEVEL)
- -I$(srcdir)/trace
ACLOCAL_AMFLAGS = -I m4
@@ -132,6 +134,10 @@ libcollection_la_SOURCES = \ libcollection_la_LDFLAGS = \ -version-info 3:0:0
+libcollection_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
check_PROGRAMS += \ collection_ut \ collection_stack_ut \ @@ -142,11 +148,21 @@ TESTS += \ collection_queue_ut
collection_ut_SOURCES = collection/collection_ut.c +collection_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
collection_ut_LDADD = libcollection.la collection_stack_ut_SOURCES = collection/collection_stack_ut.c collection_stack_ut_LDADD = libcollection.la +collection_stack_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
collection_queue_ut_SOURCES = collection/collection_queue_ut.c collection_queue_ut_LDADD = libcollection.la +collection_queue_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
collection-docs: if HAVE_DOXYGEN @@ -167,10 +183,15 @@ libref_array_la_SOURCES = \ trace/trace.h libref_array_la_LDFLAGS = \ -version-info 1:0:0
+libref_array_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_REFARRAY)
check_PROGRAMS += ref_array_ut TESTS += ref_array_ut ref_array_ut_SOURCES = refarray/ref_array_ut.c +ref_array_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_REFARRAY)
ref_array_ut_LDADD = libref_array.la
dist_doc_DATA += refarray/README.ref_array @@ -194,11 +215,17 @@ libbasicobjects_la_SOURCES = \ trace/trace.h libbasicobjects_la_LDFLAGS = \ -version-info 1:0:0 +libbasicobjects_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_BASICOBJECTS)
check_PROGRAMS += simplebuffer_ut TESTS += simplebuffer_ut simplebuffer_ut_SOURCES = basicobjects/simplebuffer_ut.c simplebuffer_ut_LDADD = libbasicobjects.la +simplebuffer_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_BASICOBJECTS)
basicobjects-docs: if HAVE_DOXYGEN @@ -243,6 +270,9 @@ libini_config_la_LIBADD = \ libbasicobjects.la libini_config_la_LDFLAGS = \ -version-info 3:0:0 +libini_config_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
dist_noinst_DATA += \ ini/ini.conf \ @@ -268,15 +298,27 @@ ini_config_ut_SOURCES = ini/ini_config_ut.c ini_config_ut_LDADD = \ libini_config.la \ libcollection.la +ini_config_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_comment_ut_SOURCES = ini/ini_comment_ut.c ini_comment_ut_LDADD = libini_config.la +ini_comment_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_valueobj_ut_SOURCES = ini/ini_valueobj_ut.c ini_valueobj_ut_LDADD = libini_config.la +ini_valueobj_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_parse_ut_SOURCES = ini/ini_parse_ut.c ini_parse_ut_LDADD = libini_config.la +ini_parse_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_config-docs: if HAVE_DOXYGEN diff --git a/configure.ac b/configure.ac index 2e22e8a6aaac271dfa4841c17f98411967e09fd9..d1b68f5fd76654e899738f6c8a29b516a23592c5 100644 --- a/configure.ac +++ b/configure.ac @@ -39,11 +39,24 @@ AC_PATH_PROG([DOXYGEN], [doxygen], [false]) AM_CONDITIONAL([HAVE_DOXYGEN], [test x$DOXYGEN != xfalse ])
# Enable trace build +# To turn on the tracing of one of the componenets one has not only +# to enable it with --enable-trace but to drop a file named "trace" +# into a corresponding directory. +# Tracing can be built for collection, ini, refarray or basicobjects. +# The approach allows building different libraries with trace +# independent of each other. AC_ARG_ENABLE([trace], [AS_HELP_STRING([--enable-trace[=LEVEL]],[build with low level tracing enabled])], [trace_level="$enableval"], [trace_level="0"]) -AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] ],[AC_SUBST([TRACE_VAR],["-DTRACE_LEVEL=$trace_level"])]) +AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/ini/trace] ],
[AC_SUBST([TRACE_INI],["-DTRACE_LEVEL=$trace_level"])])
+AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/collection/trace] ],
[AC_SUBST([TRACE_COLLECTION],["-DTRACE_LEVEL=$trace_level"])])
+AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/refarray/trace] ],
[AC_SUBST([TRACE_REFARRAY],["-DTRACE_LEVEL=$trace_level"])])
+AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/basicobjects/trace] ],
[AC_SUBST([TRACE_BASICOBJECTS],["-DTRACE_LEVEL=$trace_level"])])
AC_CHECK_SIZEOF([long]) AC_CHECK_SIZEOF([long long]) -- 1.5.5.6
From 6a66a986e962554b161ddb46f8b1e85a7c791e27 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:24:35 -0500 Subject: [PATCH] [INI] New error codes and messages
Patch consists of two parts:
- Adding new constants for error messages to ini_configobj.h file
- Making ini_print.c use this header file instead of the old one.
ini/ini_configobj.h | 12 ++++++---- ini/ini_print.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 9 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 88a8704277facb0f8883b2df28a709b26ae311f7..36558a701a86f6f656f2d0e3b155b9d901177fa7 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -72,13 +72,15 @@ #define ERR_READ 8 /** @brief Line starts with space when it should not (Error). */ #define ERR_SPACE 9 +/** @brief Duplicate key is not allowed (Error). */ +#define ERR_DUPKEY 10 +/** @brief Duplicate key is detected while merging sections (Error). */ +#define ERR_DUPKEYSEC 11 +/** @brief Duplicate section is not allowed (Error). */ +#define ERR_DUPSECTION 12
/** @brief Size of the error array. */ -#define ERR_MAXPARSE ERR_SPACE
-/**
- @}
- */
+#define ERR_MAXPARSE ERR_DUPSECTION
/** diff --git a/ini/ini_print.c b/ini/ini_print.c index 0430976cd56e89313cb386b99ad387263498c639..1dcfa54bfd72daf2c790d04c37ff2b3107eb7295 100644 --- a/ini/ini_print.c +++ b/ini/ini_print.c @@ -31,7 +31,8 @@ #include "collection.h" #include "collection_tools.h" #include "ini_defines.h" -#include "ini_config.h" +#include "ini_config_priv.h" +#include "ini_configobj.h"
/*============================================================*/ @@ -42,6 +43,16 @@
- check that the class IDs did not get reused over time by
- other classes.
*/ +/**
- @brief Collection of error collections.
- When multiple files are read during one call
- each file has its own set of parsing errors
- and warnings. This is the collection
- of such sets.
- */
+#define COL_CLASS_INI_PESET COL_CLASS_INI_BASE + 3
/** @brief Collection of grammar errors.
- Reserved for future use.
@@ -53,6 +64,37 @@ */ #define COL_CLASS_INI_VERROR COL_CLASS_INI_BASE + 6
+/**
- @}
- */
+/**
- @defgroup gramerr Grammar errors and warnings
- Placeholder for now. Reserved for future use.
- @{
- */
+#define ERR_MAXGRAMMAR 0 +/**
- @}
- */
+/**
- @defgroup valerr Validation errors and warnings
- Placeholder for now. Reserved for future use.
- @{
- */
+#define ERR_MAXVALID 0
+/**
- @}
- */
#ifdef HAVE_VALIDATION
/** @brief Collection of lines from the INI file. @@ -78,7 +120,11 @@ static const char *parsing_error_str(int parsing_error) _("Property name is too long."), _("Failed to read line."), _("Invalid space character at the "
"beginning of the line.")
"beginning of the line."),
_("Duplicate key is not allowed."),
_("Duplicate key is detected while "
"merging sections."),
_("Duplicate section is not allowed.")
};
/* Check the range */
@@ -208,7 +254,7 @@ static void print_error_list(FILE *file, struct collection_iterator *iterator; int error; struct collection_item *item = NULL;
- struct parse_error *pe;
struct ini_parse_error *pe; unsigned int count;
TRACE_FLOW_STRING("print_error_list", "Entry");
@@ -256,7 +302,7 @@ static void print_error_list(FILE *file, } else { /* Put error into provided format */
pe = (struct parse_error *)(col_get_item_data(item));
pe = (struct ini_parse_error *)(col_get_item_data(item)); fprintf(file, line_format, col_get_item_property(item, NULL), /* Error or warning */ pe->error, /* Error */
-- 1.5.5.6
From 2323da5507a13b5267152482a212442685cfcf05 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:29:05 -0500 Subject: [PATCH] [INI] New merge flags
Adding "DETECT" merge modes. These modes would be useable for dry run cases to detect if there are any potential merge conflicts. Patch just defines new constans and adds input checks.
ini/ini_configobj.h | 6 ++++++ ini/ini_fileobj.c | 9 ++++++--- 2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 36558a701a86f6f656f2d0e3b155b9d901177fa7..f0c6882dbb1e066972f98309bf78a99670b985c5 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -108,6 +108,8 @@ #define INI_MV1S_PRESERVE 0x0002 /** @brief Duplicates are allowed */ #define INI_MV1S_ALLOW 0x0003 +/** @brief Duplicates are allowed but errors are logged */ +#define INI_MV1S_DETECT 0x0004
/**
- @}
@@ -133,6 +135,8 @@ #define INI_MV2S_PRESERVE 0x0020 /** @brief Duplicates are allowed */ #define INI_MV2S_ALLOW 0x0030 +/** @brief Duplicates are allowed but errors are logged */ +#define INI_MV2S_DETECT 0x0040
/**
- @}
@@ -159,6 +163,8 @@ #define INI_MS_PRESERVE 0x0300 /** @brief Duplicates are allowed */ #define INI_MS_ALLOW 0x0400 +/** @brief Duplicates are allowed but errors are logged */ +#define INI_MS_DETECT 0x0500
/**
- @}
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 94494f78a41b6af5e44686134ab1e48290b9ab38..7bc599b948563964830f9ade75966cf4f9aa3018 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -44,7 +44,8 @@ static int valid_collision_flags(uint32_t collision_flags) if ((flag != INI_MV1S_OVERWRITE) && (flag != INI_MV1S_ERROR) && (flag != INI_MV1S_PRESERVE) &&
(flag != INI_MV1S_ALLOW)) {
(flag != INI_MV1S_ALLOW) &&
}(flag != INI_MV1S_DETECT)) { TRACE_ERROR_STRING("Invalid value collision flag",""); return 0;
@@ -53,7 +54,8 @@ static int valid_collision_flags(uint32_t collision_flags) if ((flag != INI_MV2S_OVERWRITE) && (flag != INI_MV2S_ERROR) && (flag != INI_MV2S_PRESERVE) &&
(flag != INI_MV2S_ALLOW)) {
(flag != INI_MV2S_ALLOW) &&
}(flag != INI_MV2S_DETECT)) { TRACE_ERROR_STRING("Invalid value cross-section collision flag",""); return 0;
@@ -63,7 +65,8 @@ static int valid_collision_flags(uint32_t collision_flags) (flag != INI_MS_OVERWRITE) && (flag != INI_MS_ERROR) && (flag != INI_MS_PRESERVE) &&
(flag != INI_MS_ALLOW)) {
(flag != INI_MS_ALLOW) &&
}(flag != INI_MS_DETECT)) { TRACE_ERROR_STRING("Invalid section collision flag",""); return 0;
-- 1.5.5.6
From 45efaa8dc8de649d4714066ccd3b8441dd55b0e6 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:36:06 -0500 Subject: [PATCH] [INI] Add new vars to parse structure
Adding new varibles to the internal parsing structure and initializing them.
ini/ini_parse.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 18edc629e90fe47597357b7953f06990ab5a48f0..9667a02926ef7d984886896b206997a841f04619 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -69,8 +69,11 @@ struct parser_obj { uint32_t linenum; /* Line number of the last found key */ uint32_t keylinenum;
- /* Line number of the last found section */
- uint32_t seclinenum; /* Internal variables */ struct collection_item *sec;
- struct collection_item *merge_sec; struct ini_comment *ic; char *last_read; uint32_t last_read_len;
@@ -78,12 +81,15 @@ struct parser_obj { uint32_t key_len; struct ref_array *raw_lines; struct ref_array *raw_lengths;
- char *merge_key;
- struct value_obj *merge_vo;
- /* Merge error */
- uint32_t merge_error; int ret;
};
typedef int (*action_fn)(struct parser_obj *);
#define PARSE_ACTION "action"
/* Actions */ @@ -181,9 +187,12 @@ static int parser_create(FILE *file,
/* Initialize internal varibles */ new_po->sec = NULL;
- new_po->merge_sec = NULL; new_po->ic = NULL; new_po->last_error = 0; new_po->linenum = 0;
- new_po->keylinenum = 0;
- new_po->seclinenum = 0; new_po->last_read = NULL; new_po->last_read_len = 0; new_po->key = NULL;
@@ -191,6 +200,9 @@ static int parser_create(FILE *file, new_po->raw_lines = NULL; new_po->raw_lengths = NULL; new_po->ret = EOK;
new_po->merge_key = NULL;
new_po->merge_vo = NULL;
new_po->merge_error = 0;
/* Create a queue */ new_po->queue = NULL;
-- 1.5.5.6
From 27cf7bc5c1089380cc7bc893deee8eb88db2d3d4 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:44:52 -0500 Subject: [PATCH] [INI] Add save_error function
Create a function to add error into error list.
ini/ini_parse.c | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 9667a02926ef7d984886896b206997a841f04619..a2e05f9311d38ff5904b016c5c8335d56b26a170 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -99,6 +99,13 @@ typedef int (*action_fn)(struct parser_obj *); #define PARSE_ERROR 3 /* Handle error */ #define PARSE_DONE 4 /* We are done */
+/* Declarations of the reusble functions: */ +static int complete_value_processing(struct parser_obj *po); +static int save_error(struct collection_item *el,
unsigned line,
int error,
int idx);
int is_just_spaces(const char *str, uint32_t len) { @@ -946,6 +953,28 @@ static int parser_post(struct parser_obj *po) return EOK; }
+static int save_error(struct collection_item *el,
unsigned line,
int inerr,
int idx)
+{
- int error = EOK;
- const char *errtxt[] = { ERROR_TXT, WARNING_TXT };
- struct ini_parse_error pe;
- TRACE_FLOW_ENTRY();
- /* Clear the warning bit */
- pe.error = inerr;
- pe.line = line;
- error = col_add_binary_property(el, NULL,
errtxt[idx], &pe, sizeof(pe));
- TRACE_FLOW_RETURN(error);
- return error;
+}
/* Error and warning processing */ static int parser_error(struct parser_obj *po) { -- 1.5.5.6
From e5a6bb7e8fab4b7e23f31ee1ab5ce10bf7dd33d5 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:48:35 -0500 Subject: [PATCH] [INI] Change parse_error to use save_error
- Changed parse_error to use save_error function created in previous commit.
- Fixed comment to be more clear.
ini/ini_parse.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index a2e05f9311d38ff5904b016c5c8335d56b26a170..e7eab28211655f7a225202552fd96b68c1e09450 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -981,19 +981,17 @@ static int parser_error(struct parser_obj *po) int error = EOK; uint32_t action; int idx = 0;
const char *errtxt[] = { ERROR_TXT, WARNING_TXT };
struct ini_parse_error pe;
TRACE_FLOW_ENTRY();
pe.line = po->linenum;
/* Clear the warning bit */
pe.error = po->last_error & ~INI_WARNING; if (po->last_error & INI_WARNING) idx = 1;
error = col_add_binary_property(po->el, NULL,
errtxt[idx], &pe, sizeof(pe));
- error = save_error(po->el,
po->linenum,
po->last_error & ~INI_WARNING,
if (error) {idx);
TRACE_ERROR_NUMBER("Failed to add error to collection",
}TRACE_ERROR_NUMBER("Failed to add error to error list", error); return error;
@@ -1043,7 +1041,9 @@ static int parser_error(struct parser_obj *po) /* If merging sections should produce error and we got error * or if we merge sections but dup values produce error and * we got error then it is not a fatal error so we need to handle
* it nicely. We check for reverse condition and return error,
* it nicely and suppress it here. We already in the procees
* of handling another error and merge error does not matter here.
* We check for reverse condition and return error, * otherwise fall through. */ if (!((((po->collision_flags & INI_MS_MASK) == INI_MS_ERROR) &&
-- 1.5.5.6
From 10610699c6db3d181011c85447073f5ee4a04153 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:56:51 -0500 Subject: [PATCH] [INI] Preparing for merging sections
Patch implements three functions:
- Function to detect a collision between two section names.
- Function to empty section from all its keys
- Function to add values one by one from one section to another.
ini/ini_parse.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 177 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index e7eab28211655f7a225202552fd96b68c1e09450..fc43cb06daca64309e47f43047263c5f066fc43e 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -318,6 +318,183 @@ static int parser_read(struct parser_obj *po) return EOK; }
+/* Find if there is a collistion */ +static int check_section_collision(struct parser_obj *po) +{
- int error = EOK;
- struct collection_item *item = NULL;
- TRACE_FLOW_ENTRY();
- TRACE_INFO_STRING("Searching for:", col_get_item_property(po->sec, NULL));
- error = col_get_item(po->top,
col_get_item_property(po->sec, NULL),
COL_TYPE_ANY,
COL_TRAVERSE_DEFAULT,
&item);
- if (error) {
TRACE_ERROR_NUMBER("Failed searching for dup", error);
return error;
- }
- /* Check if there is a dup */
- if (item) {
TRACE_INFO_STRING("Collision found:",
col_get_item_property(item, NULL));
/* Get the actual section collection instead of reference */
po->merge_sec = *((struct collection_item **)
(col_get_item_data(item)));
- }
- else {
TRACE_INFO_STRING("Collision not found.", "");
po->merge_sec = NULL;
- }
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Clean all items in the section */ +static int empty_section(struct collection_item *sec) +{
- int error = EOK;
- struct collection_item *item = NULL;
- struct collection_item *save_item = NULL;
- struct value_obj *vo = NULL;
- int work_to_do = 1;
- TRACE_FLOW_ENTRY();
- do {
item = NULL;
error = col_extract_item_from_current(sec,
COL_DSP_FRONT,
NULL,
0,
COL_TYPE_ANY,
&item);
if ((error) && (error != ENOENT)) {
TRACE_ERROR_NUMBER("Failed to extract item.", error);
return error;
}
if (item) {
TRACE_INFO_STRING("Item found:",
col_get_item_property(item, NULL));
if (strncmp(col_get_item_property(item, NULL),
INI_SECTION_KEY, 1) == 0) {
/* Just ignore the first item */
save_item = item;
continue;
}
vo = *((struct value_obj **)(col_get_item_data(item)));
value_destroy(vo);
col_delete_item(item);
}
else {
TRACE_INFO_STRING("No more items:", "");
/* Restore saved item */
error = col_insert_item(sec,
NULL,
save_item,
COL_DSP_END,
NULL,
0,
COL_INSERT_NOCHECK);
if (error) {
TRACE_ERROR_NUMBER("Failed to restore item.", error);
return error;
}
work_to_do = 0;
}
- }
- while (work_to_do);
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Merge contents of the section */ +static int merge_section(struct parser_obj *po) +{
- int error = EOK;
- struct collection_item *item = NULL;
- struct value_obj *vo = NULL;
- int work_to_do = 1;
- const char *key;
- TRACE_FLOW_ENTRY();
- do {
TRACE_INFO_STRING("Top of the merge loop", "");
item = NULL;
error = col_extract_item_from_current(po->sec,
COL_DSP_FRONT,
NULL,
0,
COL_TYPE_ANY,
&item);
if ((error) && (error != ENOENT)) {
TRACE_ERROR_NUMBER("Failed to extract item.", error);
return error;
}
if (item) {
TRACE_INFO_STRING("Item found:", col_get_item_property(item, NULL));
if (strncmp(col_get_item_property(item, NULL),
INI_SECTION_KEY, 1) == 0) {
/* Just ignore the first item */
vo = *((struct value_obj **)(col_get_item_data(item)));
value_destroy(vo);
col_delete_item(item);
continue;
}
po->merge_vo = *((struct value_obj **)(col_get_item_data(item)));
key = col_get_item_property(item, NULL);
/* To be able to use po->merge_key in the loop
* we have to overcome constraints imposed by
* the "const" declaration.
*/
memcpy(&(po->merge_key), &key, sizeof(char *));
/* Use the value processing function to inser the value */
error = complete_value_processing(po);
/* In case of error value is already cleaned */
po->merge_vo = NULL;
po->merge_key = NULL;
col_delete_item(item);
/* Now we can check the error */
if (error) {
TRACE_ERROR_NUMBER("Failed to merge item.", error);
return error;
}
}
else {
TRACE_INFO_STRING("No more items:", "");
work_to_do = 0;
}
- }
- while (work_to_do);
- /* If we reached this place the incoming section is empty.
* but just to be safe clean with callback. */
- col_destroy_collection_with_cb(po->sec, ini_cleanup_cb, NULL);
- po->sec = NULL;
- TRACE_FLOW_EXIT();
- return EOK;
+}
/* Function to read next line from the file */ static int parser_save_section(struct parser_obj *po) { -- 1.5.5.6
From aa35a75674482febe3f5f67b3e7c7c7faf507f05 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:03:33 -0500 Subject: [PATCH] [INI] Enhance value processing
This patch refactores the value processing function so that it can be used both in normal mode when velues need to be constrcuted and saved into the current section (po->sec) and in the merge mode when values are already constructed and need to be saved into a po->merge_sec.
ini/ini_parse.c | 165 ++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 116 insertions(+), 49 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index fc43cb06daca64309e47f43047263c5f066fc43e..5dd873a339e5fce36bc13ea8bde65dbefc5d617f 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -529,6 +529,7 @@ static int parser_save_section(struct parser_obj *po) static int complete_value_processing(struct parser_obj *po) { int error = EOK;
- int error2 = EOK; struct value_obj *vo = NULL; struct value_obj *vo_old = NULL; unsigned insertmode;
@@ -536,12 +537,19 @@ static int complete_value_processing(struct parser_obj *po) int suppress = 0; int doinsert = 0; struct collection_item *item = NULL;
struct collection_item *section = NULL;
int merging = 0;
TRACE_FLOW_ENTRY();
- /* If there is not open section create a default one */
- if(!(po->sec)) {
/* Create a new section */
- if (po->merge_sec) {
TRACE_INFO_STRING("Processing value in merge mode", "");
section = po->merge_sec;
merging = 1;
- }
- else if(!(po->sec)) {
TRACE_INFO_STRING("Creating default section", "");
/* If there is not open section create a default one */ error = col_create_collection(&po->sec, INI_DEFAULT_SECTION, COL_CLASS_INI_SECTION);
@@ -549,29 +557,44 @@ static int complete_value_processing(struct parser_obj *po) TRACE_ERROR_NUMBER("Failed to create default section", error); return error; }
}section = po->sec;
- /* Construct value object from what we have */
- error = value_create_from_refarray(po->raw_lines,
po->raw_lengths,
po->keylinenum,
INI_VALUE_READ,
po->key_len,
po->boundary,
po->ic,
&vo);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create value object", error);
return error;
- else {
TRACE_INFO_STRING("Processing value in normal mode", "");
}section = po->sec;
- /* Forget about the arrays. They are now owned by the value object */
- po->ic = NULL;
- po->raw_lines = NULL;
- po->raw_lengths = NULL;
- if (merging) {
TRACE_INFO_STRING("Using merge key:", po->merge_key);
vo = po->merge_vo;
/* We are adding to the merge section so use MV2S flags.
* But flags are done in such a way that deviding MV2S by MV1S mask
* will translate MV2S flags into MV1S so we can use
* MV1S constants. */
TRACE_INFO_NUMBER("Collisions flags:", po->collision_flags);
mergemode = (po->collision_flags & INI_MV2S_MASK) / INI_MV1S_MASK;
- }
- else {
/* Construct value object from what we have */
error = value_create_from_refarray(po->raw_lines,
po->raw_lengths,
po->keylinenum,
INI_VALUE_READ,
po->key_len,
po->boundary,
po->ic,
&vo);
- mergemode = po->collision_flags & INI_MV1S_MASK;
if (error) {
TRACE_ERROR_NUMBER("Failed to create value object", error);
return error;
}
/* Forget about the arrays. They are now owned by the value object */
po->ic = NULL;
po->raw_lines = NULL;
po->raw_lengths = NULL;
mergemode = po->collision_flags & INI_MV1S_MASK;
}
switch (mergemode) { case INI_MV1S_ERROR: insertmode = COL_INSERT_DUPERROR;
@@ -585,16 +608,18 @@ static int complete_value_processing(struct parser_obj *po) doinsert = 1; break; case INI_MV1S_OVERWRITE: /* Special handling */
case INI_MV1S_DETECT: default: break; }
/* Do not insert but search for dups first */ if (!doinsert) {
TRACE_INFO_STRING("Ovewrite mode. Lokking for:", po->key);
TRACE_INFO_STRING("Overwrite mode. Looking for:",
(char *)(merging ? po->merge_key : po->key));
error = col_get_item(po->sec,
po->key,
error = col_get_item(section,
merging ? po->merge_key : po->key, COL_TYPE_BINARY, COL_TRAVERSE_DEFAULT, &item);
@@ -607,21 +632,42 @@ static int complete_value_processing(struct parser_obj *po)
/* Check if there is a dup */ if (item) {
/* Dup exists - update it */
vo_old = *((struct value_obj **)(col_get_item_data(item)));
error = col_modify_binary_item(item,
NULL,
&vo,
sizeof(struct value_obj *));
if (error) {
TRACE_ERROR_NUMBER("Failed updating the value", error);
value_destroy(vo);
return error;
/* Check if we are in the detect mode */
if (mergemode == INI_MV1S_DETECT) {
po->merge_error = EEXIST;
/* There is a dup - inform user about it and continue */
error = save_error(po->el,
merging ? po->seclinenum : po->keylinenum,
merging ? ERR_DUPKEYSEC : ERR_DUPKEY,
0);
if (error) {
TRACE_ERROR_NUMBER("Failed to save error", error);
value_destroy(vo);
return error;
}
doinsert = 1;
insertmode = COL_INSERT_NOCHECK;
}
else {
/* Dup exists - update it */
vo_old = *((struct value_obj **)(col_get_item_data(item)));
error = col_modify_binary_item(item,
NULL,
&vo,
sizeof(struct value_obj *));
if (error) {
TRACE_ERROR_NUMBER("Failed updating the value", error);
value_destroy(vo);
return error;
}
/* If we failed to update it is better to leak then crash,
* so destroy original value only on the successful update.
*/
value_destroy(vo_old); }
/* If we failed to update it is better to leak then crash,
* so desctroy original value only on the successful update.
*/
value_destroy(vo_old); } else { /* No dup found so we can insert with no check */
@@ -632,31 +678,52 @@ static int complete_value_processing(struct parser_obj *po)
if (doinsert) { /* Add value to collection */
error = col_insert_binary_property(po->sec,
error = col_insert_binary_property(section, NULL, COL_DSP_END, NULL, 0, insertmode,
po->key,
merging ? po->merge_key : po->key, &vo, sizeof(struct value_obj *)); if (error) {
value_destroy(vo);
if ((suppress) && (error == EEXIST)) {
TRACE_INFO_STRING("Preseved exisitng value", po->key);
value_destroy(vo);
TRACE_INFO_STRING("Preseved exisitng value",
(char *)(merging ? po->merge_key : po->key)); } else {
TRACE_ERROR_NUMBER("Failed to add value object to the section", error);
value_destroy(vo);
return error;
/* Check if this is a critical error or not */
if ((mergemode == INI_MV1S_ERROR) && (error == EEXIST)) {
TRACE_ERROR_NUMBER("Failed to add value object "
"to the section", error);
error2 = save_error(po->el,
merging ? po->seclinenum : po->keylinenum,
merging ? ERR_DUPKEYSEC : ERR_DUPKEY,
0);
if (error2) {
TRACE_ERROR_NUMBER("Failed to save error", error2);
return error2;
}
return error;
}
else {
TRACE_ERROR_NUMBER("Failed to add value object"
" to the section", error);
return error;
}} } }
- free(po->key);
- po->key = NULL;
- po->key_len = 0;
- if (!merging) {
free(po->key);
po->key = NULL;
po->key_len = 0;
- }
- TRACE_FLOW_EXIT(); return EOK;
}
1.5.5.6
From f5e1f6494f6350d41fce3e063a8aebf72aa7c4ea Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:05:28 -0500 Subject: [PATCH] [INI] Use section line number
Use section line number for error reporting about the section collisions.
ini/ini_parse.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 5dd873a339e5fce36bc13ea8bde65dbefc5d617f..a1c3a26f0f88c80616bad5336be1126a1f9b99bf 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -1069,9 +1069,12 @@ static int handle_section(struct parser_obj *po, uint32_t *action) }
/* Save the line number of the last found key */
- po->keylinenum = po->linenum;
- po->seclinenum = po->linenum;
- /* Complete processing of this value */
- /* Complete processing of this value.
* A new section will be created inside and a special
* value will be added.
error = complete_value_processing(po); if (error) { TRACE_ERROR_NUMBER("Failed to complete value processing", error);*/
-- 1.5.5.6
From 6d4b2785106cd6614eedb62069da76ecc2e90457 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:08:19 -0500 Subject: [PATCH] [INI] Refactor section processing
This patch adds functionality to respect merge section flags and to process section collisions differently dpending on these flags.
ini/ini_parse.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 105 insertions(+), 9 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index a1c3a26f0f88c80616bad5336be1126a1f9b99bf..d9c6d0a9bc71f197eb4bf752fd56958ba6f64df2 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -499,25 +499,121 @@ static int merge_section(struct parser_obj *po) static int parser_save_section(struct parser_obj *po) { int error = EOK;
uint32_t mergemode;
int add = 0;
int merge = 0;
TRACE_FLOW_ENTRY();
if (po->sec) {
/* For now just add as we did.
* Add merge code here !!!!
*/
error = col_add_collection_to_collection(po->top,
NULL, NULL,
po->sec,
COL_ADD_MODE_EMBED);
TRACE_INFO_STRING("Section exists.", "");
/* First detect if we have collision */
error = check_section_collision(po); if (error) {
TRACE_ERROR_NUMBER("Failed to embed section", error);
TRACE_ERROR_NUMBER("Failed to check for collision", error); return error; }
po->sec = NULL;
if (po->merge_sec) {
TRACE_INFO_STRING("Merge collision detected", "");
mergemode = po->collision_flags & INI_MS_MASK;
switch (mergemode) {
case INI_MS_ERROR: /* Report error and return */
TRACE_INFO_STRING("Reporting error",
"duplicate section");
error = save_error(po->el,
po->seclinenum,
ERR_DUPSECTION,
0);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"save error",
error);
return error;
}
/* Return error */
TRACE_FLOW_RETURN(EEXIST);
return EEXIST;
case INI_MS_PRESERVE: /* Delete new section */
TRACE_INFO_STRING("Preserve mode", "");
col_destroy_collection_with_cb(
po->sec,
ini_cleanup_cb,
NULL);
po->sec = NULL;
break;
case INI_MS_ALLOW: TRACE_INFO_STRING("Allow mode", "");
add = 1;
break;
case INI_MS_OVERWRITE: /* Empty existing section */
TRACE_INFO_STRING("Ovewrite mode", "");
error = empty_section(po->merge_sec);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"empty section",
error);
return error;
}
merge = 1;
break;
case INI_MS_DETECT: /* Detect mode */
TRACE_INFO_STRING("Detect mode", "");
po->merge_error = EEXIST;
error = save_error(po->el,
po->seclinenum,
ERR_DUPSECTION,
0);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"save error",
error);
return error;
}
merge = 1;
break;
case INI_MS_MERGE: /* Merge */
default: TRACE_INFO_STRING("Merge mode", "");
merge = 1;
break;
}
if (merge) {
error = merge_section(po);
if (error) {
TRACE_ERROR_NUMBER("Failed to merge section", error);
return error;
}
}
po->merge_sec = NULL;
}
else add = 1;
if (add) {
/* Add section to configuration */
TRACE_INFO_STRING("Now adding collection", "");
error = col_add_collection_to_collection(po->top,
NULL, NULL,
po->sec,
COL_ADD_MODE_EMBED);
if (error) {
TRACE_ERROR_NUMBER("Failed to embed section", error);
return error;
}
po->sec = NULL;
}
}
TRACE_FLOW_EXIT();
-- 1.5.5.6
From 8fb3799dc674770bb622b630267a7a436449069e Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:10:23 -0500 Subject: [PATCH] [INI] Return error in DETECT mode
If in merge DETECT mode and there were no parsing errors return error if there were merge collisions.
ini/ini_parse.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index d9c6d0a9bc71f197eb4bf752fd56958ba6f64df2..3f45ac71ae46dff3413a6d4db5dd59a0838d078b 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -1441,7 +1441,18 @@ int parser_run(struct parser_obj *po) col_delete_item(item);
if (action == PARSE_DONE) {
TRACE_INFO_NUMBER("We are done", error);
/* Report merge error in detect mode
* if no other error was detected. */
if ((po->ret == 0) &&
(po->merge_error != 0) &&
((po->collision_flags & INI_MV1S_DETECT) ||
(po->collision_flags & INI_MV2S_DETECT) ||
(po->collision_flags & INI_MS_DETECT)))
po->ret = po->merge_error;
error = po->ret; break; }
-- 1.5.5.6
From 235393228925b4aee6138820276450c233853464 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:15:12 -0500 Subject: [PATCH] [INI] New test files for section merge
smerge.conf - test file sexpect.conf - file contains output of the smerge.conf processed in different merge modes for sections and values
Makefile.am | 4 +- ini/ini.d/sexpect.conf | 644 ++++++++++++++++++++++++++++++++++++++++++++++++ ini/ini.d/smerge.conf | 33 +++ 3 files changed, 680 insertions(+), 1 deletions(-) create mode 100644 ini/ini.d/sexpect.conf create mode 100644 ini/ini.d/smerge.conf
diff --git a/Makefile.am b/Makefile.am index 1780e9b234e68006af910413b3e8312c9db72c7b..4f9ab3427bb309b19ddec0da5e2125046d03babc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -280,7 +280,9 @@ dist_noinst_DATA += \ ini/ini.d/test.conf \ ini/ini.d/ipa.conf \ ini/ini.d/foo.conf \
- ini/ini.d/mysssd.conf
- ini/ini.d/mysssd.conf \
- ini/ini.d/smerge.conf \
- ini/ini.d/sexpect.conf
check_PROGRAMS += \ ini_config_ut \ diff --git a/ini/ini.d/sexpect.conf b/ini/ini.d/sexpect.conf new file mode 100644 index 0000000000000000000000000000000000000000..6a9222b0a9003ed1a6e9c10401573832980a3706 --- /dev/null +++ b/ini/ini.d/sexpect.conf @@ -0,0 +1,644 @@ +# Section mode: MERGE, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: MERGE, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: MERGE, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+#End of file +# Section mode: MERGE, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: MERGE, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ERROR, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: OVERWRITE, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: ERROR +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: ALLOW +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: DETECT +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: PRESERVE, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ALLOW, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: DETECT, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: DETECT, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: DETECT, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+#End of file +# Section mode: DETECT, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: DETECT, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file diff --git a/ini/ini.d/smerge.conf b/ini/ini.d/smerge.conf new file mode 100644 index 0000000000000000000000000000000000000000..bdec46d86fb6ecd0d39f4b50aca01a53dabd9ebf --- /dev/null +++ b/ini/ini.d/smerge.conf @@ -0,0 +1,33 @@ +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file
1.5.5.6
From a2b8565c919f3b39e9d7eeef9baa29081bb80f43 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:18:48 -0500 Subject: [PATCH] [INI] Test DETECT mode and use new file
Patch adds smerge.conf file to the list of files to test and adds test for the DETECT mode for inidividual values.
ini/ini_parse_ut.c | 30 +++++++++++++++++++++++------- 1 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 9327ebaab2dc529b593e0b550011bbac6b949b94..40c64bb15c0535dd2e8f5e62129a31ae53c3f35f 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -173,6 +173,7 @@ int read_save_test(void) "mysssd", "ipa", "test",
"smerge", NULL };
@@ -203,6 +204,7 @@ int read_again_test(void) "mysssd", "ipa", "test",
"smerge", NULL };
@@ -279,14 +281,25 @@ int create_expect(const char *checkname) fprintf(ff,"#Second value\n"); fprintf(ff,"bar = second value\n"); fprintf(ff,"#End of section\n");
/* Detect */
fprintf(ff,"#Hoho section\n");
fprintf(ff,"[hoho]\n");
fprintf(ff,"#Hoho value\n");
fprintf(ff,"val = hoho\n");
fprintf(ff,"#End of hoho\n");
fprintf(ff,"#Start of section\n");
fprintf(ff,"[foo]\n");
fprintf(ff,"#First value\n");
fprintf(ff,"bar = first value\n");
fprintf(ff,"#Second value\n");
fprintf(ff,"bar = second value\n");
fprintf(ff,"#End of section\n");
fclose(ff);
return EOK;
}
/* Check merge modes */ int merge_values_test(void) { @@ -301,12 +314,14 @@ int merge_values_test(void) uint32_t mflags[] = { INI_MV1S_OVERWRITE, INI_MV1S_ERROR, INI_MV1S_PRESERVE,
INI_MV1S_ALLOW };
INI_MV1S_ALLOW,
INI_MV1S_DETECT };
const char *mstr[] = { "OVERWRITE", "ERROR", "PRESERVE",
"ALLOW" };
"ALLOW",
"DETECT" };
char filename[PATH_MAX]; const char *resname = "./merge.conf.out";
@@ -323,7 +338,7 @@ int merge_values_test(void) return error; }
- for (i = 0; i < 4; i++) {
for (i = 0; i < 5; i++) {
INIOUT(printf("<==== Testing mode %s ====>\n", mstr[i]));
@@ -360,8 +375,9 @@ int merge_values_test(void) ini_config_free_errors(error_list); }
if ((mflags[i] != INI_MV1S_ERROR) ||
((mflags[i] = INI_MV1S_ERROR) && (error != EEXIST))) {
if (((mflags[i] != INI_MV1S_ERROR) && (mflags[i]!= INI_MV1S_DETECT)) ||
((mflags[i] = INI_MV1S_ERROR) && (error != EEXIST)) ||
((mflags[i] = INI_MV1S_DETECT) && (error != EEXIST))) { printf("This is unexpected error %d in mode %d\n", error, mflags[i]); ini_config_destroy(ini_config); simplebuffer_free(sbobj);
-- 1.5.5.6
From 24241d6fa2aa0b7e1595f0600d28238945f647d3 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:20:54 -0500 Subject: [PATCH] [INI] Test for all section merge modes
New test reads smerge.conf in all possible modes and compares the combined result with the sexpect.conf function.
ini/ini_parse_ut.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 188 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 40c64bb15c0535dd2e8f5e62129a31ae53c3f35f..95793dc39cfa73966192802a12d9bdc54c5ec545 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -438,6 +438,193 @@ int merge_values_test(void) resname, checkname, error));
return error;
+}
+/* Check merge modes */ +int merge_section_test(void) +{
- int error = EOK;
- int i, j;
- struct ini_cfgfile *file_ctx = NULL;
- FILE *ff = NULL;
- struct ini_cfgobj *ini_config = NULL;
- char **error_list = NULL;
- struct simplebuffer *sbobj = NULL;
- uint32_t left = 0;
- uint32_t msecflags[] = { INI_MS_MERGE,
INI_MS_ERROR,
INI_MS_OVERWRITE,
INI_MS_PRESERVE,
INI_MS_ALLOW,
INI_MS_DETECT };
- uint32_t mflags[] = { INI_MV2S_OVERWRITE,
INI_MV2S_ERROR,
INI_MV2S_PRESERVE,
INI_MV2S_ALLOW,
INI_MV2S_DETECT };
- const char *secmstr[] = { "MERGE",
"ERROR",
"OVERWRITE",
"PRESERVE",
"ALLOW",
"DETECT" };
- const char *mstr[] = { "OVERWRITE",
"ERROR",
"PRESERVE",
"ALLOW",
"DETECT" };
- char filename[PATH_MAX];
- char checkname[PATH_MAX];
- const char *resname = "./smerge.conf.out";
- char command[PATH_MAX * 3];
- char mode[100];
- char *srcdir;
- srcdir = getenv("srcdir");
- sprintf(filename, "%s/ini/ini.d/smerge.conf",
(srcdir == NULL) ? "." : srcdir);
- sprintf(checkname, "%s/ini/ini.d/sexpect.conf",
(srcdir == NULL) ? "." : srcdir);
- error = simplebuffer_alloc(&sbobj);
- if (error) {
TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error);
return error;
- }
- for (i = 0; i < 6; i++) {
for (j = 0; j < 5; j++) {
INIOUT(printf("<==== Testing mode %s + %s ====>\n",
secmstr[i], mstr[j]));
sprintf(mode, "# Section mode: %s, value mode: %s\n",
secmstr[i], mstr[j]);
error = simplebuffer_add_str(sbobj,
mode,
strlen(mode),
100);
if (error) {
TRACE_ERROR_NUMBER("Failed to add string.",
error);
simplebuffer_free(sbobj);
return error;
}
/* Create config collection */
error = ini_config_create(&ini_config);
if (error) {
printf("Failed to create collection. "
"Error %d.\n", error);
simplebuffer_free(sbobj);
return error;
}
error = ini_config_file_open(filename,
INI_STOP_ON_ANY,
msecflags[i] | mflags[j],
0, /* TBD */
&file_ctx);
if (error) {
printf("Failed to open file for reading. "
"Error %d.\n", error);
ini_config_destroy(ini_config);
simplebuffer_free(sbobj);
return error;
}
error = ini_config_parse(file_ctx,
ini_config);
if (error) {
INIOUT(printf("Failed to parse configuration. "
"Error %d.\n", error));
if (ini_config_error_count(file_ctx)) {
INIOUT(printf("Errors detected while parsing: %s\n",
ini_config_get_filename(file_ctx)));
ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
ini_config_free_errors(error_list);
}
if (((msecflags[i] == INI_MS_ERROR) &&
(error == EEXIST)) ||
((msecflags[i] == INI_MS_DETECT) &&
(error == EEXIST)) ||
((msecflags[i] == INI_MS_MERGE) &&
((mflags[j] == INI_MV2S_ERROR) ||
(mflags[j] == INI_MV2S_DETECT)) &&
(error == EEXIST))) {
INIOUT(printf("This is an expected error "
"%d in mode %d + %d\n",
error,
msecflags[i],
mflags[j]));
/* We do not return here intentionally */
}
else {
printf("This is unexpected error %d in mode %d + %d\n",
error, msecflags[i], mflags[j]);
ini_config_destroy(ini_config);
simplebuffer_free(sbobj);
ini_config_file_close(file_ctx);
return error;
}
}
ini_config_file_close(file_ctx);
INIOUT(col_debug_collection(ini_config->cfg,
COL_TRAVERSE_DEFAULT));
error = ini_config_serialize(ini_config, sbobj);
if (error != EOK) {
printf("Failed to serialize configuration. "
"Error %d.\n", error);
ini_config_destroy(ini_config);
simplebuffer_free(sbobj);
return error;
}
ini_config_destroy(ini_config);
}
- }
- errno = 0;
- ff = fopen(resname, "w");
- if(!ff) {
error = errno;
printf("Failed to open file for writing. Error %d.\n", error);
simplebuffer_free(sbobj);
return error;
- }
- /* Save */
- left = simplebuffer_get_len(sbobj);
- while (left > 0) {
error = simplebuffer_write(fileno(ff), sbobj, &left);
if (error) {
printf("Failed to write back the configuration %d.\n", error);
simplebuffer_free(sbobj);
fclose(ff);
return error;
}
- }
- simplebuffer_free(sbobj);
- fclose(ff);
- sprintf(command,"diff -q %s %s", resname, checkname);
- error = system(command);
- INIOUT(printf("Comparison of %s %s returned: %d\n",
resname, checkname, error));
- return error;
} @@ -449,6 +636,7 @@ int main(int argc, char *argv[]) test_fn tests[] = { read_save_test, read_again_test, merge_values_test,
test_fn t; int i = 0;merge_section_test, NULL };
-- 1.5.5.6
From 8176dad24b0124a634450741f00b2d03c48ce437 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 18:08:27 -0500 Subject: [PATCH] [INI] Separate close and destroy
Allow closing file without destroying the context.
ini/ini_configobj.h | 5 ++++- ini/ini_fileobj.c | 25 +++++++++++++++++++------ ini/ini_parse_ut.c | 10 +++++----- 3 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index f0c6882dbb1e066972f98309bf78a99670b985c5..e728c2e3cbc787586a542a184a07593ad1e03331 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -213,9 +213,12 @@ int ini_config_file_open(const char *filename, uint32_t metadata_flags, struct ini_cfgfile **file_ctx);
-/* Close file context and destroy the object */ +/* Close file context */ void ini_config_file_close(struct ini_cfgfile *file_ctx);
+/* Close file context and destroy the object */ +void ini_config_file_destroy(struct ini_cfgfile *file_ctx);
/* How many errors do we have in the list ? */ unsigned ini_config_error_count(struct ini_cfgfile *file_ctx);
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 7bc599b948563964830f9ade75966cf4f9aa3018..f998eb09d1b5c271be9a316196a510bac39455c2 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -75,12 +75,25 @@ static int valid_collision_flags(uint32_t collision_flags) return 1; }
-/* Close file context and destroy the object */
+/* Close file but not destroy the object */ void ini_config_file_close(struct ini_cfgfile *file_ctx) { TRACE_FLOW_ENTRY();
if(file_ctx) {
if(file_ctx->file) fclose(file_ctx->file);
- }
- TRACE_FLOW_EXIT();
+}
+/* Close file context and destroy the object */ +void ini_config_file_destroy(struct ini_cfgfile *file_ctx) +{
- TRACE_FLOW_ENTRY();
- if(file_ctx) { free(file_ctx->filename); col_destroy_collection(file_ctx->error_list); col_destroy_collection(file_ctx->metadata);
@@ -144,7 +157,7 @@ int ini_config_file_open(const char *filename, new_ctx->filename = malloc(PATH_MAX + 1); if (!(new_ctx->filename)) { error = errno;
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); TRACE_ERROR_NUMBER("Failed to allocate memory for file path.", error); return error;
@@ -155,7 +168,7 @@ int ini_config_file_open(const char *filename, filename); if(error) { TRACE_ERROR_NUMBER("Failed to resolve path", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
@@ -166,7 +179,7 @@ int ini_config_file_open(const char *filename, if (!(new_ctx->file)) { error = errno; TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
@@ -176,7 +189,7 @@ int ini_config_file_open(const char *filename, COL_CLASS_INI_PERROR); if (error) { TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
@@ -185,7 +198,7 @@ int ini_config_file_open(const char *filename, COL_CLASS_INI_META); if (error) { TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 95793dc39cfa73966192802a12d9bdc54c5ec545..f0a95527aa315b559e5c6fa42740fe4a3ba4e4b3 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -91,7 +91,7 @@ int test_one_file(const char *in_filename, /* We do not return here intentionally */ }
- ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx);
INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
@@ -381,13 +381,13 @@ int merge_values_test(void) printf("This is unexpected error %d in mode %d\n", error, mflags[i]); ini_config_destroy(ini_config); simplebuffer_free(sbobj);
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); return error; } /* We do not return here intentionally */ }
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
@@ -572,12 +572,12 @@ int merge_section_test(void) error, msecflags[i], mflags[j]); ini_config_destroy(ini_config); simplebuffer_free(sbobj);
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); return error; } }
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
-- 1.5.5.6
From 29e4a0a028b802eaa3bb1dfbc7a9080fc7f21f4b Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 18:34:02 -0500 Subject: [PATCH] [INI] Function to reopen file
This patch would allow to reopen file and create a new context based on the old one.
ini/ini_configobj.h | 4 ++ ini/ini_fileobj.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 0 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index e728c2e3cbc787586a542a184a07593ad1e03331..3321bd3ea8985b9b12f04ab792fbcac307bbbe2e 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -213,6 +213,10 @@ int ini_config_file_open(const char *filename, uint32_t metadata_flags, struct ini_cfgfile **file_ctx);
+/* Create a file object from existing one */ +int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in,
struct ini_cfgfile **file_ctx_out);
/* Close file context */ void ini_config_file_close(struct ini_cfgfile *file_ctx);
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index f998eb09d1b5c271be9a316196a510bac39455c2..200c7af9de896c1abd26a57a508f9f540475b19d 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -210,6 +210,92 @@ int ini_config_file_open(const char *filename, return error; }
+/* Create a file object from existing one */ +int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in,
struct ini_cfgfile **file_ctx_out)
+{
- int error = EOK;
- struct ini_cfgfile *new_ctx = NULL;
- TRACE_FLOW_ENTRY();
- if ((!file_ctx_in) || (!file_ctx_out)) {
TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
return EINVAL;
- }
- /* Allocate structure */
- errno = 0;
- new_ctx = malloc(sizeof(struct ini_cfgfile));
- if (!new_ctx) {
error = errno;
TRACE_ERROR_NUMBER("Failed to allocate file ctx.", error);
return error;
- }
- new_ctx->filename = NULL;
- new_ctx->file = NULL;
- new_ctx->error_list = NULL;
- new_ctx->metadata = NULL;
- /* TBD - decide whether we actually need an FD.
It will be done when we move the metadata
processing into this function. */
- new_ctx->fd = -1;
- /* Store flags */
- new_ctx->error_level = file_ctx_in->error_level;
- new_ctx->collision_flags = file_ctx_in->collision_flags;
- new_ctx->metadata_flags = file_ctx_in->metadata_flags;
- new_ctx->count = 0;
- /* Copy full file path */
- errno = 0;
- new_ctx->filename = strndup(file_ctx_in->filename, PATH_MAX);
- if (!(new_ctx->filename)) {
error = errno;
ini_config_file_destroy(new_ctx);
TRACE_ERROR_NUMBER("Failed to allocate memory for file path.", error);
return error;
- }
- /* Open file */
- TRACE_INFO_STRING("File", new_ctx->filename);
- errno = 0;
- new_ctx->file = fopen(new_ctx->filename, "r");
- if (!(new_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(new_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_close(new_ctx);
return error;
- }
- error = col_create_collection(&(new_ctx->metadata),
INI_METADATA,
COL_CLASS_INI_META);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* TBD - Add metadata processing here */
- *file_ctx_out = new_ctx;
- TRACE_FLOW_EXIT();
- return error;
+}
/* How many errors do we have in the list ? */ unsigned ini_config_error_count(struct ini_cfgfile *file_ctx) -- 1.5.5.6
From 7030e51bb22e62e6f5d63b0faa923d2151336818 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 19:21:32 -0500 Subject: [PATCH] [INI] Metadata collection is gone
After some more thinking I decided not to use metadata collection. It seems to be an overhead. Patch does following:
- Replaces metadata collection in file context structure with standard file stats
- Removes all operations against old metadata collection
- Defines new flags for data to collect
- Creates a function that consolidates common operations between open and reopen functions.
ini/ini_config_priv.h | 11 +++-- ini/ini_configobj.h | 20 ++++++++ ini/ini_fileobj.c | 121 ++++++++++++++++++++----------------------------- 3 files changed, 75 insertions(+), 77 deletions(-)
diff --git a/ini/ini_config_priv.h b/ini/ini_config_priv.h index 1880c3ff4caa91e7ed3a37e445a20294e76d8037..84742c70ceeb5b493b935c635e81c57d5ef487ce 100644 --- a/ini/ini_config_priv.h +++ b/ini/ini_config_priv.h @@ -22,6 +22,9 @@ #ifndef INI_CONFIG_PRIV_H #define INI_CONFIG_PRIV_H
+#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include "collection.h"
/* Configuration object */ @@ -45,21 +48,19 @@ struct ini_cfgfile { char *filename; /* File stream */ FILE *file;
- /* File descriptor that is passed in */
- int fd; /* Error level */ int error_level; /* Collision flags - define how to merge things */ uint32_t collision_flags;
- /* Collision flags - define how to merge things */
- /* What meta data to collect */ uint32_t metadata_flags; /**********************/ /* Internal variables */ /**********************/ /* Collection of errors detected during parsing */ struct collection_item *error_list;
- /* Metadata about the file */
- struct collection_item *metadata;
- /* File stats */
- struct stat file_stats; /* Count of error lines */ unsigned count;
}; diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 3321bd3ea8985b9b12f04ab792fbcac307bbbe2e..898440252ef3a547566fe2b5e80753d7971a8e47 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -82,6 +82,26 @@ /** @brief Size of the error array. */ #define ERR_MAXPARSE ERR_DUPSECTION
+/**
- @}
- */
+/**
- @defgroup metacollect Constants that define what meta data to collect
- Constants in this section define what meta data to collect
- @{
- */
+/** @brief Do not collect any data. */ +#define INI_META_NONE 0 +/** @brief Collect file stats. */ +#define INI_META_STATS 1
+/**
- @}
- */
/**
- @defgroup collisionflags Flags that define collision resolution logic.
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 200c7af9de896c1abd26a57a508f9f540475b19d..c10b4bf954366ddae90f1d06c53acd0332968599 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -96,7 +96,6 @@ void ini_config_file_destroy(struct ini_cfgfile *file_ctx) if(file_ctx) { free(file_ctx->filename); col_destroy_collection(file_ctx->error_list);
}col_destroy_collection(file_ctx->metadata); if(file_ctx->file) fclose(file_ctx->file); free(file_ctx);
@@ -104,6 +103,47 @@ void ini_config_file_destroy(struct ini_cfgfile *file_ctx) TRACE_FLOW_EXIT(); }
+/* Internal common initialization part */ +static int common_file_init(struct ini_cfgfile *file_ctx) +{
- int error = EOK;
- TRACE_FLOW_ENTRY();
- /* Open file */
- TRACE_INFO_STRING("File", file_ctx->filename);
- errno = 0;
- file_ctx->file = fopen(file_ctx->filename, "r");
- if (!(file_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(file_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
return error;
- }
- /* Collect stats */
- if (file_ctx->metadata_flags & INI_META_STATS) {
errno = 0;
if (fstat(fileno(file_ctx->file),
&(file_ctx->file_stats)) < 0) {
error = errno;
TRACE_ERROR_NUMBER("Failed to get file stats.", error);
return error;
}
- }
- TRACE_FLOW_EXIT();
- return EOK;
+}
/* Create a file object for parsing a config file */ int ini_config_file_open(const char *filename, int error_level, @@ -135,16 +175,9 @@ int ini_config_file_open(const char *filename, return error; }
new_ctx->filename = NULL; new_ctx->file = NULL; new_ctx->error_list = NULL;
new_ctx->metadata = NULL;
/* TBD - decide whether we actually need an FD.
It will be done when we move the metadata
processing into this function. */
new_ctx->fd = -1;
/* Store flags */ new_ctx->error_level = error_level;
@@ -172,39 +205,14 @@ int ini_config_file_open(const char *filename, return error; }
- /* Open file */
- TRACE_INFO_STRING("File", new_ctx->filename);
- errno = 0;
- new_ctx->file = fopen(new_ctx->filename, "r");
- if (!(new_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(new_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- error = col_create_collection(&(new_ctx->metadata),
INI_METADATA,
COL_CLASS_INI_META);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
- /* Do common init */
- error = common_file_init(new_ctx);
- if(error) {
}TRACE_ERROR_NUMBER("Failed to do common init", error); ini_config_file_destroy(new_ctx); return error;
- /* TBD - Add metadata processing here */
- *file_ctx = new_ctx; TRACE_FLOW_EXIT(); return error;
@@ -236,12 +244,6 @@ int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in, new_ctx->filename = NULL; new_ctx->file = NULL; new_ctx->error_list = NULL;
new_ctx->metadata = NULL;
/* TBD - decide whether we actually need an FD.
It will be done when we move the metadata
processing into this function. */
new_ctx->fd = -1;
/* Store flags */ new_ctx->error_level = file_ctx_in->error_level;
@@ -259,39 +261,14 @@ int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in, return error; }
- /* Open file */
- TRACE_INFO_STRING("File", new_ctx->filename);
- errno = 0;
- new_ctx->file = fopen(new_ctx->filename, "r");
- if (!(new_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(new_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_close(new_ctx);
return error;
- }
- error = col_create_collection(&(new_ctx->metadata),
INI_METADATA,
COL_CLASS_INI_META);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
- /* Do common init */
- error = common_file_init(new_ctx);
- if(error) {
}TRACE_ERROR_NUMBER("Failed to do common init", error); ini_config_file_destroy(new_ctx); return error;
- /* TBD - Add metadata processing here */
- *file_ctx_out = new_ctx; TRACE_FLOW_EXIT(); return error;
-- 1.5.5.6
From 87be7cfc4b8cc143a582a38a0d024e166d91df35 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 19:46:15 -0500 Subject: [PATCH] [INI] Check access function
Added check access constants and the check access function. The function is effectively copied from ini_metadata.c The flags are copied from ini_config.h
ini/ini_configobj.h | 35 +++++++++++++++++++++++ ini/ini_fileobj.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 898440252ef3a547566fe2b5e80753d7971a8e47..eccad71c7245f1d035c5133c13b6078fc3e3dc5b 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -104,6 +104,41 @@ */
/**
- @defgroup accesscheck Access control check flags
- @{
- */
+/**
- @brief Validate access mode
- If this flag is specified the mode parameter
- will be matched against the permissions set on the file
- using the provided mask.
- */
+#define INI_ACCESS_CHECK_MODE 0x00000001
+/**
- @brief Validate uid
- Provided uid will be checked against uid
- of the file.
- */
+#define INI_ACCESS_CHECK_UID 0x00000002
+/**
- @brief Validate gid
- Provided gid will be checked against gid
- of the file.
- */
+#define INI_ACCESS_CHECK_GID 0x00000004
+/**
- @}
- */
+/**
- @defgroup collisionflags Flags that define collision resolution logic.
- @{
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index c10b4bf954366ddae90f1d06c53acd0332968599..93a9372f3e37489862a33f1676ca68a532c62441 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -406,3 +406,78 @@ const char *ini_config_get_filename(struct ini_cfgfile *file_ctx) TRACE_FLOW_EXIT(); return ret; }
+/* Check access */ +int ini_config_access_check(struct ini_cfgfile *file_ctx,
uint32_t flags,
uid_t uid,
gid_t gid,
mode_t mode,
mode_t mask)
+{
- int error = EOK;
- TRACE_FLOW_ENTRY();
- flags &= INI_ACCESS_CHECK_MODE |
INI_ACCESS_CHECK_GID |
INI_ACCESS_CHECK_UID;
- if ((file_ctx == NULL) || (flags == 0)) {
TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
return EINVAL;
- }
- /* Check mode */
- if (flags & INI_ACCESS_CHECK_MODE) {
TRACE_INFO_NUMBER("File mode as saved.",
file_ctx->file_stats.st_mode);
file_ctx->file_stats.st_mode &= S_IRWXU | S_IRWXG | S_IRWXO;
TRACE_INFO_NUMBER("File mode adjusted.",
file_ctx->file_stats.st_mode);
TRACE_INFO_NUMBER("Mode as provided.", mode);
mode &= S_IRWXU | S_IRWXG | S_IRWXO;
TRACE_INFO_NUMBER("Mode adjusted.", mode);
/* Adjust mask */
if (mask == 0) mask = S_IRWXU | S_IRWXG | S_IRWXO;
else mask &= S_IRWXU | S_IRWXG | S_IRWXO;
if ((mode & mask) != (file_ctx->file_stats.st_mode & mask)) {
TRACE_INFO_NUMBER("File mode:", (mode & mask));
TRACE_INFO_NUMBER("Mode adjusted.",
(file_ctx->file_stats.st_mode & mask));
TRACE_ERROR_NUMBER("Access denied.", EACCES);
return EACCES;
}
- }
- /* Check uid */
- if (flags & INI_ACCESS_CHECK_UID) {
if (file_ctx->file_stats.st_uid != uid) {
TRACE_ERROR_NUMBER("GID:", file_ctx->file_stats.st_uid);
TRACE_ERROR_NUMBER("GID passed in.", uid);
TRACE_ERROR_NUMBER("Access denied.", EACCES);
return EACCES;
}
- }
- /* Check gid */
- if (flags & INI_ACCESS_CHECK_GID) {
if (file_ctx->file_stats.st_gid != gid) {
TRACE_ERROR_NUMBER("GID:", file_ctx->file_stats.st_gid);
TRACE_ERROR_NUMBER("GID passed in.", gid);
TRACE_ERROR_NUMBER("Access denied.", EACCES);
return EACCES;
}
- }
- TRACE_FLOW_EXIT();
- return error;
+}
1.5.5.6
From c4d2383282b898f4c5914bf720301cdcabf5eb51 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:24:08 -0500 Subject: [PATCH] [INI] Avoid double free
I might squash this patch into one of the previous ones.
ini/ini_fileobj.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 93a9372f3e37489862a33f1676ca68a532c62441..2d47c8ff1d1a613dfc5baa8efd00b05c368f8447 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -82,7 +82,10 @@ void ini_config_file_close(struct ini_cfgfile *file_ctx) TRACE_FLOW_ENTRY();
if(file_ctx) {
if(file_ctx->file) fclose(file_ctx->file);
if(file_ctx->file) {
fclose(file_ctx->file);
file_ctx->file = NULL;
}
}
TRACE_FLOW_EXIT();
-- 1.5.5.6
From 81e90b377b432ef874fda11b6e82f6f0eb894807 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:28:59 -0500 Subject: [PATCH] [INI] Function to check for changes
Added function to detect changes to the configuration file.
ini/ini_configobj.h | 4 ++-- ini/ini_fileobj.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index eccad71c7245f1d035c5133c13b6078fc3e3dc5b..913b91e6abed18d30ba256edc280a1d0aa9d76ef 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -335,8 +335,8 @@ int ini_config_access_check(struct ini_cfgfile *file_ctx,
- device ID
- i-node
*/ -int ini_config_changed(struct ini_cfgfile *file_ctx,
struct ini_cfgfile *file_ctx_saved,
+int ini_config_changed(struct ini_cfgfile *file_ctx1,
struct ini_cfgfile *file_ctx2, int *changed);
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 2d47c8ff1d1a613dfc5baa8efd00b05c368f8447..6de963971a0e9501fb86c23ee5faf6bfb5824bf0 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -484,3 +484,40 @@ int ini_config_access_check(struct ini_cfgfile *file_ctx, return error;
}
+/* Determins if two file context different by comparing
- time stamp
- device ID
- i-node
- */
+int ini_config_changed(struct ini_cfgfile *file_ctx1,
struct ini_cfgfile *file_ctx2,
int *changed)
+{
- int error = EOK;
- TRACE_FLOW_ENTRY();
- if ((file_ctx1 == NULL) ||
(file_ctx2 == NULL) ||
(changed == NULL)) {
TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
return EINVAL;
- }
- *changed = 0;
- if((file_ctx1->file_stats.st_mtime !=
file_ctx2->file_stats.st_mtime) ||
(file_ctx1->file_stats.st_dev !=
file_ctx2->file_stats.st_dev) ||
(file_ctx1->file_stats.st_ino !=
file_ctx2->file_stats.st_ino)) {
TRACE_INFO_STRING("File changed!", "");
*changed = 1;
- }
- TRACE_FLOW_EXIT();
- return error;
+}
1.5.5.6
From 2ec4163bcbbcfa6c025b32cdbdbd3adf8c7a84f2 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:31:33 -0500 Subject: [PATCH] [INI] Tests for access and changes
Patch adds two functions. One tests permissions, another validates if the file has changed or not.
ini/ini_parse_ut.c | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 248 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index f0a95527aa315b559e5c6fa42740fe4a3ba4e4b3..f5b1c2c5b4e82de2baf29955901da28afc082cbb 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -625,10 +625,256 @@ int merge_section_test(void) resname, checkname, error));
return error;
+}
+int startup_test(void) +{
- int error = EOK;
- struct ini_cfgfile *file_ctx = NULL;
- struct ini_cfgobj *ini_config = NULL;
- char **error_list = NULL;
- char filename[PATH_MAX];
- char *srcdir;
- srcdir = getenv("srcdir");
- sprintf(filename, "%s/ini/ini.d/foo.conf",
(srcdir == NULL) ? "." : srcdir);
- INIOUT(printf("<==== Startup test ====>\n"));
- /* Open config file */
- error = ini_config_file_open(filename,
INI_STOP_ON_NONE,
0,
INI_META_STATS,
&file_ctx);
- if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
return error;
- }
- /* We will check just permissions here. */
- error = ini_config_access_check(file_ctx,
INI_ACCESS_CHECK_MODE, /* add uid & gui flags
* in real case
*/
0, /* <- will be real uid in real case */
0, /* <- will be real gid in real case */
0440, /* Checking for r--r----- */
0);
- /* This check is expected to fail since
* the actual permissions on the test file are: rw-rw-r--
*/
- if (!error) {
printf("Expected error got success!\n");
ini_config_file_destroy(file_ctx);
return EACCES;
- }
- error = ini_config_access_check(
file_ctx,
INI_ACCESS_CHECK_MODE, /* add uid & gui flags
* in real case
*/
0, /* <- will be real uid in real case */
0, /* <- will be real gid in real case */
0664, /* Checkling for rw-rw-r-- */
0);
- if (error) {
printf("Access check failed %d!\n", error);
ini_config_file_destroy(file_ctx);
return EACCES;
- }
- /* Create config object */
- error = ini_config_create(&ini_config);
- if (error) {
printf("Failed to create collection. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
- }
- error = ini_config_parse(file_ctx,
ini_config);
- if (error) {
INIOUT(printf("Failed to parse configuration. Error %d.\n", error));
if (ini_config_error_count(file_ctx)) {
INIOUT(printf("Errors detected while parsing: %s\n",
ini_config_get_filename(file_ctx)));
ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
ini_config_free_errors(error_list);
}
/* We do not return here intentionally */
- }
- ini_config_file_destroy(file_ctx);
- INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
- ini_config_destroy(ini_config);
- return 0;
+}
+int reload_test(void) +{
int error = EOK;
struct ini_cfgfile *file_ctx = NULL;
struct ini_cfgfile *file_ctx_new = NULL;
char infile[PATH_MAX];
char outfile[PATH_MAX];
char command[PATH_MAX * 3];
char *srcdir;
char *builddir;
int changed = 0;
INIOUT(printf("<==== Reload test ====>\n"));
srcdir = getenv("srcdir");
sprintf(infile, "%s/ini/ini.d/foo.conf",
(srcdir == NULL) ? "." : srcdir);
builddir = getenv("builddir");
sprintf(outfile, "%s/foo.conf",
(builddir == NULL) ? "." : builddir);
sprintf(command, "cp %s %s", infile, outfile);
errno = 0;
if(system(command)) {
error = errno;
printf("Failed to run copy command %d.\n", error);
return error;
}
/* Open config file */
error = ini_config_file_open(outfile,
INI_STOP_ON_NONE,
0,
INI_META_STATS,
&file_ctx);
if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
return error;
}
error = ini_config_access_check(
file_ctx,
INI_ACCESS_CHECK_MODE, /* add uid & gui flags
* in real case
*/
0, /* <- will be real uid in real case */
0, /* <- will be real gid in real case */
0664, /* Checkling for rw-rw-r-- */
0);
if (error) {
printf("Access check failed %d!\n", error);
ini_config_file_destroy(file_ctx);
return EACCES;
}
/* ... Create config object and read configuration - not shown here.
* See other examples ... */
/* Now close file but leave the context around */
ini_config_file_close(file_ctx);
/* Some time passed and we received a signal to reload... */
error = ini_config_file_reopen(file_ctx, &file_ctx_new);
if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
changed = 0;
error = ini_config_changed(file_ctx,
file_ctx_new,
&changed);
if (error) {
printf("Failed to compare files. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return error;
}
/* Check if file changed */
if (changed) {
printf("File changed when it shouldn't. This is unexpected error.\n");
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return EINVAL;
}
/* Close file */
ini_config_file_destroy(file_ctx_new);
/* Emulate as if file changed */
errno = 0;
if (unlink(outfile)) {
error = errno;
printf("Failed to delete file %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
sleep(1);
errno = 0;
if (system(command)) {
error = errno;
printf("Failed to run copy command %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
/* Read again */
file_ctx_new = NULL;
error = ini_config_file_reopen(file_ctx, &file_ctx_new);
if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
changed = 0;
error = ini_config_changed(file_ctx,
file_ctx_new,
&changed);
if (error) {
printf("Failed to compare files. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return error;
}
/* Check if file changed */
if (!changed) {
printf("File did not change when it should. This is an error.\n");
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return EINVAL;
}
/* We do not need original context any more. */
ini_config_file_destroy(file_ctx);
/* New context is now original context */
file_ctx = file_ctx_new;
/* ... Create config object and read configuration - not shown here.
* See other examples ... */
ini_config_file_destroy(file_ctx);
return 0;
}
/* Main function of the unit test */ int main(int argc, char *argv[]) { @@ -637,6 +883,8 @@ int main(int argc, char *argv[]) read_again_test, merge_values_test, merge_section_test,
startup_test,
test_fn t; int i = 0;reload_test, NULL };
-- 1.5.5.6
From 8654e77c640ac19e6997542589fbd1500ae6532d Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:45:39 -0500 Subject: [PATCH] [INI] Rename error print function
All config file processing functions start with "ini_config". The only function that does not comply is ini_print_errors. We can't rename it since it is a part of the current active interface. I marked that function needs to be removed when we remove old interface and created a copy with the correct name. I also updated unit test accordingly.
ini/ini_configobj.h | 5 +---- ini/ini_parse_ut.c | 8 ++++---- ini/ini_print.c | 24 ++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 913b91e6abed18d30ba256edc280a1d0aa9d76ef..7089b62da31887e21eeffd6dceff76907ca9f1a6 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -300,10 +300,7 @@ int ini_config_copy(struct ini_cfgobj *ini_config, struct ini_cfgobj **ini_new);
/* Function to print errors from the list */ -void ini_print_errors(FILE *file, char **error_list);
+void ini_config_print_errors(FILE *file, char **error_list);
/* Merge two configurations together creating a new one */ int ini_config_merge(struct ini_cfgobj *first, diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index f5b1c2c5b4e82de2baf29955901da28afc082cbb..696735aacee25fc71f2b60708aaf3d0e14081f2c 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -85,7 +85,7 @@ int test_one_file(const char *in_filename, INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); } /* We do not return here intentionally */
@@ -371,7 +371,7 @@ int merge_values_test(void) INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); }
@@ -548,7 +548,7 @@ int merge_section_test(void) INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); }
@@ -706,7 +706,7 @@ int startup_test(void) INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); } /* We do not return here intentionally */
diff --git a/ini/ini_print.c b/ini/ini_print.c index 1dcfa54bfd72daf2c790d04c37ff2b3107eb7295..42bd6fc221c71bf4f390a79e02a4928ecf747bd9 100644 --- a/ini/ini_print.c +++ b/ini/ini_print.c @@ -461,6 +461,9 @@ void print_config_parsing_errors(FILE *file,
/* Function to print errors from the list */ +/* THIS FUNCTION SHOUD BE REMOVED WHEN
- OLD INTERFACE IS REMOVED - TBD.
- */
void ini_print_errors(FILE *file, char **error_list) { unsigned count = 0; @@ -480,3 +483,24 @@ void ini_print_errors(FILE *file, char **error_list) TRACE_FLOW_EXIT(); return; }
+/* Function to print errors from the list */ +void ini_config_print_errors(FILE *file, char **error_list) +{
- unsigned count = 0;
- TRACE_FLOW_ENTRY();
- if (!error_list) {
TRACE_FLOW_STRING("List is empty.", "");
return;
- }
- while (error_list[count]) {
fprintf(file, "%s\n", error_list[count]);
count++;
- }
- TRACE_FLOW_EXIT();
- return;
+}
1.5.5.6
From baa1b6eb9604729fa678a0988138a7aaa3f5c9c6 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:58:24 -0500 Subject: [PATCH] [INI] Initialize variables in loops
It occured to me that one of the issues that Coverity did not like (and I could not understand what it is complaining about) is related to intializing the variables in the loop. This patch adds initialization in the loops.
ini/ini_parse_ut.c | 4 ++++ ini/ini_valueobj_ut.c | 3 +++ 2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 696735aacee25fc71f2b60708aaf3d0e14081f2c..5de79d954673a194bd080660f967c7b304dbdefe 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -343,6 +343,7 @@ int merge_values_test(void) INIOUT(printf("<==== Testing mode %s ====>\n", mstr[i]));
/* Create config collection */
ini_config = NULL; error = ini_config_create(&ini_config); if (error) { printf("Failed to create collection. Error %d.\n", error);
@@ -350,6 +351,7 @@ int merge_values_test(void) return error; }
file_ctx = NULL; error = ini_config_file_open(filename, INI_STOP_ON_ANY, mflags[i],
@@ -517,6 +519,7 @@ int merge_section_test(void) }
/* Create config collection */
ini_config = NULL; error = ini_config_create(&ini_config); if (error) { printf("Failed to create collection. "
@@ -525,6 +528,7 @@ int merge_section_test(void) return error; }
file_ctx = NULL; error = ini_config_file_open(filename, INI_STOP_ON_ANY, msecflags[i] | mflags[j],
diff --git a/ini/ini_valueobj_ut.c b/ini/ini_valueobj_ut.c index af62c140d215f9298dd5671d8aa544a84ef254b1..c07ec85772084f1fd6dd157a9befae26c9aa6806 100644 --- a/ini/ini_valueobj_ut.c +++ b/ini/ini_valueobj_ut.c @@ -404,6 +404,7 @@ int vo_basic_test(void) return error; }
vo = NULL; error = value_create_new(strvalue, strlen(strvalue), INI_VALUE_CREATED,
@@ -541,6 +542,7 @@ int vo_copy_test(void)
TRACE_INFO_NUMBER("Iteration:", wrap);
vo_copy = NULL; error = value_copy(vo, &vo_copy); if (error) { printf("Failed to create a new value object %d.\n", error);
@@ -559,6 +561,7 @@ int vo_copy_test(void) }
/* Get comment from the value */
ic = NULL; error = value_extract_comment(vo_copy, &ic); if (error) { printf("Failed to extract comment %d.\n", error);
-- 1.5.5.6
From f9f8998bef402648d2565ada6789305e0c0ad46e Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Mon, 3 Jan 2011 14:36:47 -0500 Subject: [PATCH] [INI] Exposing functions
This patch makes two internal functions resusable from different source modules.
ini/ini_config_priv.h | 8 ++++++++ ini/ini_fileobj.c | 2 +- ini/ini_parse.c | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/ini/ini_config_priv.h b/ini/ini_config_priv.h index 84742c70ceeb5b493b935c635e81c57d5ef487ce..e714774a68a5e16b7a221f712abe2ea9179e88c8 100644 --- a/ini/ini_config_priv.h +++ b/ini/ini_config_priv.h @@ -82,4 +82,12 @@ void ini_cleanup_cb(const char *property, /* Get parsing error */ const char *ini_get_error_str(int parsing_error, int family);
+/* Check if collision flags are valid */ +int valid_collision_flags(uint32_t collision_flags);
+/* Empty section */ +int empty_section(struct collection_item *sec);
#endif diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 6de963971a0e9501fb86c23ee5faf6bfb5824bf0..30a2f1545d7b22dcab3bb4eccd53c91fe7edfd62 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -34,7 +34,7 @@
/* Check if collision flags are valid */ -static int valid_collision_flags(uint32_t collision_flags) +int valid_collision_flags(uint32_t collision_flags) { uint32_t flag;
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 3f45ac71ae46dff3413a6d4db5dd59a0838d078b..e3ae938847b867780cb0d0d60d12868826952a85 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -357,7 +357,7 @@ static int check_section_collision(struct parser_obj *po) }
/* Clean all items in the section */ -static int empty_section(struct collection_item *sec) +int empty_section(struct collection_item *sec) { int error = EOK; struct collection_item *item = NULL; -- 1.5.5.6
From 02c14799196cd1ffd0f53c6b2e995ac17a7f8917 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Mon, 3 Jan 2011 14:41:03 -0500 Subject: [PATCH] [INI] Function to merge two configurations
This patch provides first draft of the implementation of the code to merge different configurations. It is similar to the merge code that is implemented inside the parser but different since it is not done during parsing of one file but addresses use case when the configuration is provided by different files that need to be merged together.
NOTE: It would make more sence to review function by function from bottom of the patch rather than from the top.
ini/ini_configobj.c | 456 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 456 insertions(+), 0 deletions(-)
diff --git a/ini/ini_configobj.c b/ini/ini_configobj.c index 5e5e40b566abdf3ce2cbc225babe4b1e20c2dd47..d8583a224e8eebc4365df3909b6bac7c98477dc5 100644 --- a/ini/ini_configobj.c +++ b/ini/ini_configobj.c @@ -30,11 +30,19 @@ #include "ini_config_priv.h" #include "ini_defines.h" #include "ini_valueobj.h" +#include "ini_configobj.h"
/* This constant belongs to ini_defines.h. Move from ini_config - TBD */ #define COL_CLASS_INI_BASE 20000 #define COL_CLASS_INI_CONFIG COL_CLASS_INI_BASE + 0
+struct merge_data {
- struct collection_item *ci;
- uint32_t flags;
- int error;
- int found;
+};
/* Callback */ void ini_cleanup_cb(const char *property, int property_len, @@ -254,3 +262,451 @@ int ini_config_copy(struct ini_cfgobj *ini_config, TRACE_FLOW_EXIT(); return error; }
+/* Callback to process merging of the sections */ +static int merge_section_handler(const char *property,
int property_len,
int type,
void *data,
int length,
void *custom_data,
int *dummy)
+{
- int error = EOK;
- struct value_obj *vo = NULL;
- struct value_obj *new_vo = NULL;
- struct value_obj *vo_old = NULL;
- struct merge_data *passed_data;
- struct collection_item *acceptor = NULL;
- struct collection_item *item = NULL;
- unsigned insertmode;
- uint32_t mergemode;
- int suppress = 0;
- int doinsert = 0;
- TRACE_FLOW_ENTRY();
- if ((type != COL_TYPE_BINARY) ||
((type == COL_TYPE_BINARY) &&
(strncmp(property, INI_SECTION_KEY,
sizeof(INI_SECTION_KEY)) == 0))) {
/* Skip items we do not care about */
TRACE_FLOW_EXIT();
return EOK;
- }
- /* Get value */
- vo = *((struct value_obj **)(data));
- /* Copy it */
- error = value_copy(vo, &new_vo);
- if (error) {
TRACE_ERROR_NUMBER("Failed to copy value", error);
return error;
- }
- passed_data = (struct merge_data *)(custom_data);
- acceptor = passed_data->ci;
- mergemode = passed_data->flags & INI_MV2S_MASK;
- switch (mergemode) {
- case INI_MV2S_ERROR: insertmode = COL_INSERT_DUPERROR;
doinsert = 1;
break;
- case INI_MV2S_PRESERVE: insertmode = COL_INSERT_DUPERROR;
doinsert = 1;
suppress = 1;
break;
- case INI_MV2S_ALLOW: insertmode = COL_INSERT_NOCHECK;
doinsert = 1;
break;
- case INI_MV2S_OVERWRITE: /* Special handling */
- case INI_MV2S_DETECT:
- default:
break;
- }
- /* Do not insert but search for dups first */
- if (!doinsert) {
TRACE_INFO_STRING("Overwrite mode. Looking for:",
property);
error = col_get_item(acceptor,
property,
COL_TYPE_BINARY,
COL_TRAVERSE_DEFAULT,
&item);
if (error) {
TRACE_ERROR_NUMBER("Failed searching for dup", error);
value_destroy(new_vo);
return error;
}
/* Check if there is a dup */
if (item) {
/* Check if we are in the detect mode */
if (mergemode == INI_MV2S_DETECT) {
passed_data->error = EEXIST;
doinsert = 1;
insertmode = COL_INSERT_NOCHECK;
}
else {
/* Dup exists - update it */
vo_old = *((struct value_obj **)(col_get_item_data(item)));
error = col_modify_binary_item(item,
NULL,
&new_vo,
sizeof(struct value_obj *));
if (error) {
TRACE_ERROR_NUMBER("Failed updating the value", error);
value_destroy(new_vo);
return error;
}
/* If we failed to update it is better to leak then crash,
* so destroy original value only on the successful update.
*/
value_destroy(vo_old);
}
}
else {
/* No dup found so we can insert with no check */
doinsert = 1;
insertmode = COL_INSERT_NOCHECK;
}
- }
- if (doinsert) {
/* Add value to collection */
error = col_insert_binary_property(acceptor,
NULL,
COL_DSP_END,
NULL,
0,
insertmode,
property,
&new_vo,
sizeof(struct value_obj *));
if (error) {
value_destroy(new_vo);
if ((suppress) && (error == EEXIST)) {
TRACE_INFO_STRING("Preseved exisitng value",
property);
}
else {
/* Check if this is a critical error or not */
if ((mergemode == INI_MV1S_ERROR) && (error == EEXIST)) {
TRACE_ERROR_NUMBER("Failed to add value object "
"to the section", error);
passed_data->error = EEXIST;
*dummy = 1;
}
else {
TRACE_ERROR_NUMBER("Failed to add value object"
" to the section", error);
return error;
}
}
}
- }
- TRACE_FLOW_EXIT();
- return error;
+}
+/* Internal function to merge two configs */ +static int merge_two_sections(struct collection_item *acceptor,
struct collection_item *donor,
uint32_t flags)
+{
- int error = EOK;
- struct merge_data data;
- TRACE_FLOW_ENTRY();
- data.ci = acceptor;
- data.flags = flags;
- data.error = 0;
- data.found = 0;
- error = col_traverse_collection(donor,
COL_TRAVERSE_ONELEVEL,
merge_section_handler,
(void *)(&data));
- if (error) {
TRACE_ERROR_NUMBER("Merge values failed", error);
return error;
- }
- TRACE_FLOW_EXIT();
- return data.error;
+}
+/* Callback to process the accepting config */ +static int acceptor_handler(const char *property,
int property_len,
int type,
void *data,
int length,
void *custom_data,
int *dummy)
+{
- int error = EOK;
- struct merge_data *passed_data;
- struct collection_item *acceptor = NULL;
- struct collection_item *donor = NULL;
- uint32_t mergemode;
- TRACE_FLOW_ENTRY();
- passed_data = (struct merge_data *)(custom_data);
- passed_data->found = 1;
- donor = passed_data->ci;
- acceptor = *((struct collection_item **)(data));
- mergemode = passed_data->flags & INI_MS_MASK;
- switch (mergemode) {
- case INI_MS_ERROR: /* Report error and return */
TRACE_INFO_STRING("Error ",
"duplicate section");
passed_data->error = EEXIST;
break;
- case INI_MS_PRESERVE: /* Preserve what we have */
TRACE_INFO_STRING("Preserve mode", "");
break;
- case INI_MS_OVERWRITE: /* Empty existing section */
TRACE_INFO_STRING("Ovewrite mode", "");
error = empty_section(acceptor);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"empty section",
error);
return error;
}
error = merge_two_sections(acceptor,
donor,
passed_data->flags);
if (error) {
TRACE_ERROR_NUMBER("Failed to merge "
"sections", error);
return error;
}
break;
- case INI_MS_DETECT: /* Detect mode */
TRACE_INFO_STRING("Detect mode", "");
passed_data->error = EEXIST;
passed_data->found = 0;
break;
- case INI_MS_MERGE: /* Merge */
- default: TRACE_INFO_STRING("Merge mode", "");
error = merge_two_sections(acceptor,
donor,
passed_data->flags);
if (error) {
if (error != EEXIST) {
TRACE_ERROR_NUMBER("Failed to merge "
"sections", error);
return error;
}
passed_data->error = error;
}
break;
- }
- *dummy = 1;
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Callback to process the donating config */ +static int donor_handler(const char *property,
int property_len,
int type,
void *data,
int length,
void *custom_data,
int *dummy)
+{
- int error = EOK;
- struct merge_data *passed_data;
- struct merge_data acceptor_data;
- struct collection_item *new_ci = NULL;
- TRACE_FLOW_ENTRY();
- passed_data = (struct merge_data *)(custom_data);
- /* All section are subcollections */
- if(type == COL_TYPE_COLLECTIONREF) {
acceptor_data.flags = passed_data->flags;
acceptor_data.ci = *((struct collection_item **)(data));
acceptor_data.error = 0;
acceptor_data.found = 0;
/* Try to resolve collision only non ALLOW modes */
if (!(acceptor_data.flags & INI_MS_ALLOW)) {
error = col_get_item_and_do(passed_data->ci,
property,
COL_TYPE_COLLECTIONREF,
COL_TRAVERSE_ONELEVEL,
acceptor_handler,
(void *)(&acceptor_data));
if (error) {
TRACE_ERROR_NUMBER("Critical error", error);
return error;
}
}
/* Was duplicate found ? */
if (acceptor_data.found) {
/* Check for logical error. It can be only EEXIST */
if (acceptor_data.error) {
/* Save error anyway */
passed_data->error = acceptor_data.error;
/* If it is section DETECT or MERGE+DETECT */
if ((passed_data->flags & INI_MS_DETECT) ||
((passed_data->flags & INI_MS_MERGE) &&
(passed_data->flags & INI_MV2S_DETECT))) {
TRACE_INFO_NUMBER("Non-critical error",
acceptor_data.error);
}
else {
/* In any other mode we need to stop */
TRACE_INFO_NUMBER("Merge error detected",
acceptor_data.error);
/* Force stop */
*dummy = 1;
}
}
}
else {
/* Not found? Then create a copy... */
error = col_copy_collection_with_cb(&new_ci,
acceptor_data.ci,
NULL,
COL_COPY_NORMAL,
ini_copy_cb,
NULL);
if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
return error;
}
/* ... and embed into the existing collection */
error = col_add_collection_to_collection(passed_data->ci,
NULL,
NULL,
new_ci,
COL_ADD_MODE_EMBED);
if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
col_destroy_collection(new_ci);
return error;
}
}
- }
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Internal function to merge two configs */ +static int merge_configs(struct ini_cfgobj *first,
struct ini_cfgobj *second,
uint32_t collision_flags)
+{
- int error = EOK;
- struct merge_data data;
- TRACE_FLOW_ENTRY();
- data.ci = first->cfg;
- data.flags = collision_flags;
- data.error = 0;
- data.found = 0;
- error = col_traverse_collection(second->cfg,
COL_TRAVERSE_ONELEVEL,
donor_handler,
(void *)(&data));
- if (error) {
TRACE_ERROR_NUMBER("Merge failed", error);
return error;
- }
- /* If boundaries are different re-align the values */
- if (first->boundary != second->boundary) {
error = ini_config_set_wrap(first, first->boundary);
if (error) {
TRACE_ERROR_NUMBER("Failed to re-align", error);
return error;
}
- }
- TRACE_FLOW_EXIT();
- return error;
+}
+/* Merge two configurations together creating a new one */ +int ini_config_merge(struct ini_cfgobj *first,
struct ini_cfgobj *second,
uint32_t collision_flags,
struct ini_cfgobj **result)
+{
- int error = EOK;
- struct ini_cfgobj *new_co = NULL;
- TRACE_FLOW_ENTRY();
- /* Check input params */
- if ((!first) ||
(!second) ||
(!result)) {
TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
return EINVAL;
- }
- /* Check collision flags */
- if (!valid_collision_flags(collision_flags)) {
TRACE_ERROR_NUMBER("Invalid flags.", EINVAL);
return EINVAL;
- }
- /* Create a copy */
- /* TBD - create a COMPACT copy */
- error = ini_config_copy(first, &new_co);
- if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
return error;
- }
- /* Merge configs */
- error = merge_configs(new_co, second, collision_flags);
- if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
ini_config_destroy(new_co);
return error;
- }
- *result = new_co;
- TRACE_FLOW_EXIT();
- return error;
+}
1.5.5.6
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
On 01/24/2011 12:27 PM, Sumit Bose wrote:
The numeration changed. But the ste is the same. The patches in this mail are dependent on the patches sent in the previous email on Friday.
Patches related porting of the meta data from old way of doing things to the new way of doing things: 0017--INI-Separate-close-and-destroy.patch
You should set file_ctx->file to NULL after fclose(file_ctx->file) to make the if(file_ctx->file) checks work in ini_config_file_close() and ini_config_file_destroy().
Yes it was fixed in a different patch. Now merged together.
There are tab indents in merge_values_test() and merge_section_test().
Fixed.
0018--INI-Function-to-reopen-file.patch
Unchanged
0019--INI-Metadata-collection-is-gone.patch
You remove metadata from struct ini_cfgfile without removing all references to metadata in the same patch. You should make clear that more patches are needed to create a buildable version of libini or remove all references in this patch.
This is not true. The buildable version is still preserved. All the code that I am building is not executed yet. It is a parallel interface. There are currently two interfaces: ini_config.h and ini_configobj.h The external code is still suing the ini_config.h. The new interface that the UT are executing is pointing to the interface growing in ini_configobj.h. This metadata functions of the existing ini_config interface are not affected. After some thinking I realized that there is too much overhead for doing the metadata handling the way I did it in the first implementation. The new interface corrects this but does not affect the old code yet. So the metadata collection is gone from the new interface not from the old one. The code compiles fine after this patch and the three patches right after it take advantage of this change. Patches 18-21 should be considered together as a block of related patches.
I wonder is the following is a change of defaults. With the patch the new file_ctx->file_stats are only set if INI_META_STATS is set while previously file-ctx>metadata was set unconditionally.
Fixed by memset.
0020--INI-Check-access-function.patch
This is now 19.
I wonder if it is necessary to return EINVAL if flags == 0. I would say in this case no checks are requested and EOK could be returned?
I disagree with this one. With flags 0 I think it is a noop and might lead to the wrong assumptions while no operation was actually performed. IMO passing flags=0 is a codding error in this case and thus should be reported as such.
I would prefer to copy file_ctx->file_stats.st_mode instead of modifying it, e.g. you might want to know the file type later on.
Good catch. Agree. Fixed.
0021--INI-Avoid-double-free.patch <- patch related to 17 (missed check)
oops, so you can ignore my comment to 00017, let's see if there is also a patch for ini_config_file_destroy(). "I might squash this patch into one of the previous ones." Yes, please.
This one is merged now.
0022--INI-Function-to-check-for-changes.patch
This is now 20 and unchanged.
0023--INI-Tests-for-access-and-changes.patch
This is now 21.
Why do you need sleep(1) ?
Removed.
The man page of system() does not mention that system() sets errno, please check the return code instead.
Changed to use execlp().
0024--INI-Rename-error-print-function.patch <- rename error printing function for consistency with new interface
This is now 22.
Maybe ini_print_errors() should print a deprecated warning to make migrations easier.
As I mentioned above there is no impact on the existing interface. As you notice I made a clone of the existing function with a different name and made a comment to clean the old function when the interface is deprecated. The changes will be made later when we switch to new interface, so it is premature to print a warning as this function is still used.
0025--INI-Initialize-variables-in-loops.patch <- Coverity issue addressed. Related to patch 0001.
This is 23 and merged with another initialization one liner patch.
0026--INI-Exposing-functions.patch <- Make some internal functions reusable
This is 24 and unchanged.
There is also patch 27. It is a piece of new functionality. It is a preview. Please see the comment before reviewing it. Do I need to split it into multiple patches or it is Ok as is? It is pretty big but all changes are in one file and logically related. The UNIT test is missing so I am not claiming it actually works as expected.
I didn't had a look at 0027 so far.
I am going to hold to patch 27 yet. I have other higher priority issues to address.
Please review and nack/push this ASAP. I need to clean ding libs and elapi for the audit effort ASAP. There are too many patches piling to be able to move forward effectively. I am the bottleneck now and i need to bring all this into a usable state within a week or so. Please help!
One last thing. Should I switch to the format used in freeipa? https://fedorahosted.org/freeipa/wiki/PatchFormat It seems that SSSD/ding-libs does not follow this format. Should it? Not insisting, just asking.
bye, Sumit
-- Thank you, Dmitri Pal
Sr. Engineering Manager IPA project, Red Hat Inc.
Looking to carve out IT costs? www.redhat.com/carveoutcosts/
From 2cb4d6ad0bfad2170e09152379f29de2b9c29196 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Fri, 24 Dec 2010 00:38:48 -0500 Subject: [PATCH] [INI] Making Coverity happy
Coverity found issues 10078 & 10079. This patch should make it happy, however I think that Coverity is wrong unless I am missing something. If I am I hope that this patch would be able to reveal the real issue if any. For now just renaming a variable.
[INI] Added missing initialization
One liner to initialize a variable.
ini/ini_configobj.c | 2 +- ini/ini_valueobj_ut.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/ini/ini_configobj.c b/ini/ini_configobj.c index 3e5dec4733a49d03e44185637592f0efdbe7db3c..5e5e40b566abdf3ce2cbc225babe4b1e20c2dd47 100644 --- a/ini/ini_configobj.c +++ b/ini/ini_configobj.c @@ -215,7 +215,7 @@ int ini_config_copy(struct ini_cfgobj *ini_config, struct ini_cfgobj **ini_new) { int error = EOK;
- struct ini_cfgobj *new_co;
struct ini_cfgobj *new_co = NULL;
TRACE_FLOW_ENTRY();
diff --git a/ini/ini_valueobj_ut.c b/ini/ini_valueobj_ut.c index 767a64cc2fe624800bed7e9dc4b53a90fa2d59c2..af62c140d215f9298dd5671d8aa544a84ef254b1 100644 --- a/ini/ini_valueobj_ut.c +++ b/ini/ini_valueobj_ut.c @@ -378,6 +378,7 @@ int vo_basic_test(void) */
struct value_obj *vo = NULL;
- struct value_obj *other_vo = NULL; uint32_t wrap = 0; struct ini_comment *ic = NULL; FILE *ff = NULL;
@@ -429,7 +430,7 @@ int vo_basic_test(void) }
/* Run other create test here */
- error = other_create_test(ff, &vo);
- error = other_create_test(ff, &other_vo); if (error) { printf("Create test failed %d.\n", error); fclose(ff);
@@ -437,15 +438,15 @@ int vo_basic_test(void) }
/* Run modify test here */
- error = modify_test(ff, vo);
- error = modify_test(ff, other_vo); if (error) { printf("Modify test failed %d.\n", error); fclose(ff);
value_destroy(vo);
}value_destroy(other_vo); return error;
- value_destroy(vo);
value_destroy(other_vo);
ic = NULL;
-- 1.5.5.6
From 68ecd60fac51706c743a5c4a4cfe87ec6ca9d304 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Fri, 24 Dec 2010 21:27:24 -0500 Subject: [PATCH] [INI] Adding missing function declararion.
One-liner that eliminates compilation warning.
[INI] Include proper header
Value object needs its own header file.
ini/ini_valueobj.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/ini/ini_valueobj.c b/ini/ini_valueobj.c index a90fa451468aecc6c04f4411675ab67613a59cbe..f196c1ab3195db7cbe616e6e1275c656919fe156 100644 --- a/ini/ini_valueobj.c +++ b/ini/ini_valueobj.c @@ -29,6 +29,7 @@ #include "ini_comment.h" #include "ini_defines.h" #include "trace.h" +#include "ini_valueobj.h"
struct value_obj { struct ref_array *raw_lines; -- 1.5.5.6
From 574be6d8c0896c8bee0c16224f52c2dbea48a44e Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Fri, 24 Dec 2010 22:38:42 -0500 Subject: [PATCH] [BUILD] Allow trace per component
This patch add ability to build tracing for each component independently.
Makefile.am | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- configure.ac | 15 ++++++++++++++- 2 files changed, 60 insertions(+), 5 deletions(-)
diff --git a/Makefile.am b/Makefile.am index 0946169308bab6585c93cca36d45b360b565f6b5..1780e9b234e68006af910413b3e8312c9db72c7b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,7 @@ -TRACE_LEVEL=@TRACE_VAR@ +TRACE_INI=@TRACE_INI@ +TRACE_COLLECTION=@TRACE_COLLECTION@ +TRACE_REFARRAY=@TRACE_REFARRAY@ +TRACE_BASICOBJECTS=@TRACE_BASICOBJECTS@
RPMBUILD ?= $(PWD)/rpmbuild
@@ -28,8 +31,7 @@ AM_CPPFLAGS = \ -I$(srcdir)/ini \ -I$(srcdir)/basicobjects \ -I$(srcdir) \
- -I$(srcdir)/trace \
- $(TRACE_LEVEL)
- -I$(srcdir)/trace
ACLOCAL_AMFLAGS = -I m4
@@ -132,6 +134,10 @@ libcollection_la_SOURCES = \ libcollection_la_LDFLAGS = \ -version-info 3:0:0
+libcollection_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
check_PROGRAMS += \ collection_ut \ collection_stack_ut \ @@ -142,11 +148,21 @@ TESTS += \ collection_queue_ut
collection_ut_SOURCES = collection/collection_ut.c +collection_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
collection_ut_LDADD = libcollection.la collection_stack_ut_SOURCES = collection/collection_stack_ut.c collection_stack_ut_LDADD = libcollection.la +collection_stack_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
collection_queue_ut_SOURCES = collection/collection_queue_ut.c collection_queue_ut_LDADD = libcollection.la +collection_queue_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_COLLECTION)
collection-docs: if HAVE_DOXYGEN @@ -167,10 +183,15 @@ libref_array_la_SOURCES = \ trace/trace.h libref_array_la_LDFLAGS = \ -version-info 1:0:0
+libref_array_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_REFARRAY)
check_PROGRAMS += ref_array_ut TESTS += ref_array_ut ref_array_ut_SOURCES = refarray/ref_array_ut.c +ref_array_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_REFARRAY)
ref_array_ut_LDADD = libref_array.la
dist_doc_DATA += refarray/README.ref_array @@ -194,11 +215,17 @@ libbasicobjects_la_SOURCES = \ trace/trace.h libbasicobjects_la_LDFLAGS = \ -version-info 1:0:0 +libbasicobjects_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_BASICOBJECTS)
check_PROGRAMS += simplebuffer_ut TESTS += simplebuffer_ut simplebuffer_ut_SOURCES = basicobjects/simplebuffer_ut.c simplebuffer_ut_LDADD = libbasicobjects.la +simplebuffer_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_BASICOBJECTS)
basicobjects-docs: if HAVE_DOXYGEN @@ -243,6 +270,9 @@ libini_config_la_LIBADD = \ libbasicobjects.la libini_config_la_LDFLAGS = \ -version-info 3:0:0 +libini_config_la_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
dist_noinst_DATA += \ ini/ini.conf \ @@ -268,15 +298,27 @@ ini_config_ut_SOURCES = ini/ini_config_ut.c ini_config_ut_LDADD = \ libini_config.la \ libcollection.la +ini_config_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_comment_ut_SOURCES = ini/ini_comment_ut.c ini_comment_ut_LDADD = libini_config.la +ini_comment_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_valueobj_ut_SOURCES = ini/ini_valueobj_ut.c ini_valueobj_ut_LDADD = libini_config.la +ini_valueobj_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_parse_ut_SOURCES = ini/ini_parse_ut.c ini_parse_ut_LDADD = libini_config.la +ini_parse_ut_CFLAGS = \
- $(AM_CFLAGS) \
- $(TRACE_INI)
ini_config-docs: if HAVE_DOXYGEN diff --git a/configure.ac b/configure.ac index 2e22e8a6aaac271dfa4841c17f98411967e09fd9..d1b68f5fd76654e899738f6c8a29b516a23592c5 100644 --- a/configure.ac +++ b/configure.ac @@ -39,11 +39,24 @@ AC_PATH_PROG([DOXYGEN], [doxygen], [false]) AM_CONDITIONAL([HAVE_DOXYGEN], [test x$DOXYGEN != xfalse ])
# Enable trace build +# To turn on the tracing of one of the componenets one has not only +# to enable it with --enable-trace but to drop a file named "trace" +# into a corresponding directory. +# Tracing can be built for collection, ini, refarray or basicobjects. +# The approach allows building different libraries with trace +# independent of each other. AC_ARG_ENABLE([trace], [AS_HELP_STRING([--enable-trace[=LEVEL]],[build with low level tracing enabled])], [trace_level="$enableval"], [trace_level="0"]) -AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] ],[AC_SUBST([TRACE_VAR],["-DTRACE_LEVEL=$trace_level"])]) +AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/ini/trace] ],
[AC_SUBST([TRACE_INI],["-DTRACE_LEVEL=$trace_level"])])
+AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/collection/trace] ],
[AC_SUBST([TRACE_COLLECTION],["-DTRACE_LEVEL=$trace_level"])])
+AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/refarray/trace] ],
[AC_SUBST([TRACE_REFARRAY],["-DTRACE_LEVEL=$trace_level"])])
+AS_IF([test ["$trace_level" -gt "0"] -a ["$trace_level" -lt "8"] -a [ -e $srcdir/basicobjects/trace] ],
[AC_SUBST([TRACE_BASICOBJECTS],["-DTRACE_LEVEL=$trace_level"])])
AC_CHECK_SIZEOF([long]) AC_CHECK_SIZEOF([long long]) -- 1.5.5.6
From 6a66a986e962554b161ddb46f8b1e85a7c791e27 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:24:35 -0500 Subject: [PATCH] [INI] New error codes and messages
Patch consists of two parts:
- Adding new constants for error messages to ini_configobj.h file
- Making ini_print.c use this header file instead of the old one.
ini/ini_configobj.h | 12 ++++++---- ini/ini_print.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 9 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 88a8704277facb0f8883b2df28a709b26ae311f7..36558a701a86f6f656f2d0e3b155b9d901177fa7 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -72,13 +72,15 @@ #define ERR_READ 8 /** @brief Line starts with space when it should not (Error). */ #define ERR_SPACE 9 +/** @brief Duplicate key is not allowed (Error). */ +#define ERR_DUPKEY 10 +/** @brief Duplicate key is detected while merging sections (Error). */ +#define ERR_DUPKEYSEC 11 +/** @brief Duplicate section is not allowed (Error). */ +#define ERR_DUPSECTION 12
/** @brief Size of the error array. */ -#define ERR_MAXPARSE ERR_SPACE
-/**
- @}
- */
+#define ERR_MAXPARSE ERR_DUPSECTION
/** diff --git a/ini/ini_print.c b/ini/ini_print.c index 0430976cd56e89313cb386b99ad387263498c639..1dcfa54bfd72daf2c790d04c37ff2b3107eb7295 100644 --- a/ini/ini_print.c +++ b/ini/ini_print.c @@ -31,7 +31,8 @@ #include "collection.h" #include "collection_tools.h" #include "ini_defines.h" -#include "ini_config.h" +#include "ini_config_priv.h" +#include "ini_configobj.h"
/*============================================================*/ @@ -42,6 +43,16 @@
- check that the class IDs did not get reused over time by
- other classes.
*/ +/**
- @brief Collection of error collections.
- When multiple files are read during one call
- each file has its own set of parsing errors
- and warnings. This is the collection
- of such sets.
- */
+#define COL_CLASS_INI_PESET COL_CLASS_INI_BASE + 3
/** @brief Collection of grammar errors.
- Reserved for future use.
@@ -53,6 +64,37 @@ */ #define COL_CLASS_INI_VERROR COL_CLASS_INI_BASE + 6
+/**
- @}
- */
+/**
- @defgroup gramerr Grammar errors and warnings
- Placeholder for now. Reserved for future use.
- @{
- */
+#define ERR_MAXGRAMMAR 0 +/**
- @}
- */
+/**
- @defgroup valerr Validation errors and warnings
- Placeholder for now. Reserved for future use.
- @{
- */
+#define ERR_MAXVALID 0
+/**
- @}
- */
#ifdef HAVE_VALIDATION
/** @brief Collection of lines from the INI file. @@ -78,7 +120,11 @@ static const char *parsing_error_str(int parsing_error) _("Property name is too long."), _("Failed to read line."), _("Invalid space character at the "
"beginning of the line.")
"beginning of the line."),
_("Duplicate key is not allowed."),
_("Duplicate key is detected while "
"merging sections."),
_("Duplicate section is not allowed.")
};
/* Check the range */
@@ -208,7 +254,7 @@ static void print_error_list(FILE *file, struct collection_iterator *iterator; int error; struct collection_item *item = NULL;
- struct parse_error *pe;
struct ini_parse_error *pe; unsigned int count;
TRACE_FLOW_STRING("print_error_list", "Entry");
@@ -256,7 +302,7 @@ static void print_error_list(FILE *file, } else { /* Put error into provided format */
pe = (struct parse_error *)(col_get_item_data(item));
pe = (struct ini_parse_error *)(col_get_item_data(item)); fprintf(file, line_format, col_get_item_property(item, NULL), /* Error or warning */ pe->error, /* Error */
-- 1.5.5.6
From 2323da5507a13b5267152482a212442685cfcf05 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:29:05 -0500 Subject: [PATCH] [INI] New merge flags
Adding "DETECT" merge modes. These modes would be useable for dry run cases to detect if there are any potential merge conflicts. Patch just defines new constans and adds input checks.
ini/ini_configobj.h | 6 ++++++ ini/ini_fileobj.c | 9 ++++++--- 2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 36558a701a86f6f656f2d0e3b155b9d901177fa7..f0c6882dbb1e066972f98309bf78a99670b985c5 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -108,6 +108,8 @@ #define INI_MV1S_PRESERVE 0x0002 /** @brief Duplicates are allowed */ #define INI_MV1S_ALLOW 0x0003 +/** @brief Duplicates are allowed but errors are logged */ +#define INI_MV1S_DETECT 0x0004
/**
- @}
@@ -133,6 +135,8 @@ #define INI_MV2S_PRESERVE 0x0020 /** @brief Duplicates are allowed */ #define INI_MV2S_ALLOW 0x0030 +/** @brief Duplicates are allowed but errors are logged */ +#define INI_MV2S_DETECT 0x0040
/**
- @}
@@ -159,6 +163,8 @@ #define INI_MS_PRESERVE 0x0300 /** @brief Duplicates are allowed */ #define INI_MS_ALLOW 0x0400 +/** @brief Duplicates are allowed but errors are logged */ +#define INI_MS_DETECT 0x0500
/**
- @}
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 94494f78a41b6af5e44686134ab1e48290b9ab38..7bc599b948563964830f9ade75966cf4f9aa3018 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -44,7 +44,8 @@ static int valid_collision_flags(uint32_t collision_flags) if ((flag != INI_MV1S_OVERWRITE) && (flag != INI_MV1S_ERROR) && (flag != INI_MV1S_PRESERVE) &&
(flag != INI_MV1S_ALLOW)) {
(flag != INI_MV1S_ALLOW) &&
}(flag != INI_MV1S_DETECT)) { TRACE_ERROR_STRING("Invalid value collision flag",""); return 0;
@@ -53,7 +54,8 @@ static int valid_collision_flags(uint32_t collision_flags) if ((flag != INI_MV2S_OVERWRITE) && (flag != INI_MV2S_ERROR) && (flag != INI_MV2S_PRESERVE) &&
(flag != INI_MV2S_ALLOW)) {
(flag != INI_MV2S_ALLOW) &&
}(flag != INI_MV2S_DETECT)) { TRACE_ERROR_STRING("Invalid value cross-section collision flag",""); return 0;
@@ -63,7 +65,8 @@ static int valid_collision_flags(uint32_t collision_flags) (flag != INI_MS_OVERWRITE) && (flag != INI_MS_ERROR) && (flag != INI_MS_PRESERVE) &&
(flag != INI_MS_ALLOW)) {
(flag != INI_MS_ALLOW) &&
}(flag != INI_MS_DETECT)) { TRACE_ERROR_STRING("Invalid section collision flag",""); return 0;
-- 1.5.5.6
From 45efaa8dc8de649d4714066ccd3b8441dd55b0e6 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:36:06 -0500 Subject: [PATCH] [INI] Add new vars to parse structure
Adding new varibles to the internal parsing structure and initializing them.
ini/ini_parse.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 18edc629e90fe47597357b7953f06990ab5a48f0..9667a02926ef7d984886896b206997a841f04619 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -69,8 +69,11 @@ struct parser_obj { uint32_t linenum; /* Line number of the last found key */ uint32_t keylinenum;
- /* Line number of the last found section */
- uint32_t seclinenum; /* Internal variables */ struct collection_item *sec;
- struct collection_item *merge_sec; struct ini_comment *ic; char *last_read; uint32_t last_read_len;
@@ -78,12 +81,15 @@ struct parser_obj { uint32_t key_len; struct ref_array *raw_lines; struct ref_array *raw_lengths;
- char *merge_key;
- struct value_obj *merge_vo;
- /* Merge error */
- uint32_t merge_error; int ret;
};
typedef int (*action_fn)(struct parser_obj *);
#define PARSE_ACTION "action"
/* Actions */ @@ -181,9 +187,12 @@ static int parser_create(FILE *file,
/* Initialize internal varibles */ new_po->sec = NULL;
- new_po->merge_sec = NULL; new_po->ic = NULL; new_po->last_error = 0; new_po->linenum = 0;
- new_po->keylinenum = 0;
- new_po->seclinenum = 0; new_po->last_read = NULL; new_po->last_read_len = 0; new_po->key = NULL;
@@ -191,6 +200,9 @@ static int parser_create(FILE *file, new_po->raw_lines = NULL; new_po->raw_lengths = NULL; new_po->ret = EOK;
new_po->merge_key = NULL;
new_po->merge_vo = NULL;
new_po->merge_error = 0;
/* Create a queue */ new_po->queue = NULL;
-- 1.5.5.6
From 27cf7bc5c1089380cc7bc893deee8eb88db2d3d4 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:44:52 -0500 Subject: [PATCH] [INI] Add save_error function
Create a function to add error into error list.
ini/ini_parse.c | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 9667a02926ef7d984886896b206997a841f04619..a2e05f9311d38ff5904b016c5c8335d56b26a170 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -99,6 +99,13 @@ typedef int (*action_fn)(struct parser_obj *); #define PARSE_ERROR 3 /* Handle error */ #define PARSE_DONE 4 /* We are done */
+/* Declarations of the reusble functions: */ +static int complete_value_processing(struct parser_obj *po); +static int save_error(struct collection_item *el,
unsigned line,
int error,
int idx);
int is_just_spaces(const char *str, uint32_t len) { @@ -946,6 +953,28 @@ static int parser_post(struct parser_obj *po) return EOK; }
+static int save_error(struct collection_item *el,
unsigned line,
int inerr,
int idx)
+{
- int error = EOK;
- const char *errtxt[] = { ERROR_TXT, WARNING_TXT };
- struct ini_parse_error pe;
- TRACE_FLOW_ENTRY();
- /* Clear the warning bit */
- pe.error = inerr;
- pe.line = line;
- error = col_add_binary_property(el, NULL,
errtxt[idx], &pe, sizeof(pe));
- TRACE_FLOW_RETURN(error);
- return error;
+}
/* Error and warning processing */ static int parser_error(struct parser_obj *po) { -- 1.5.5.6
From e5a6bb7e8fab4b7e23f31ee1ab5ce10bf7dd33d5 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:48:35 -0500 Subject: [PATCH] [INI] Change parse_error to use save_error
- Changed parse_error to use save_error function created in previous commit.
- Fixed comment to be more clear.
ini/ini_parse.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index a2e05f9311d38ff5904b016c5c8335d56b26a170..e7eab28211655f7a225202552fd96b68c1e09450 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -981,19 +981,17 @@ static int parser_error(struct parser_obj *po) int error = EOK; uint32_t action; int idx = 0;
const char *errtxt[] = { ERROR_TXT, WARNING_TXT };
struct ini_parse_error pe;
TRACE_FLOW_ENTRY();
pe.line = po->linenum;
/* Clear the warning bit */
pe.error = po->last_error & ~INI_WARNING; if (po->last_error & INI_WARNING) idx = 1;
error = col_add_binary_property(po->el, NULL,
errtxt[idx], &pe, sizeof(pe));
- error = save_error(po->el,
po->linenum,
po->last_error & ~INI_WARNING,
if (error) {idx);
TRACE_ERROR_NUMBER("Failed to add error to collection",
}TRACE_ERROR_NUMBER("Failed to add error to error list", error); return error;
@@ -1043,7 +1041,9 @@ static int parser_error(struct parser_obj *po) /* If merging sections should produce error and we got error * or if we merge sections but dup values produce error and * we got error then it is not a fatal error so we need to handle
* it nicely. We check for reverse condition and return error,
* it nicely and suppress it here. We already in the procees
* of handling another error and merge error does not matter here.
* We check for reverse condition and return error, * otherwise fall through. */ if (!((((po->collision_flags & INI_MS_MASK) == INI_MS_ERROR) &&
-- 1.5.5.6
From 10610699c6db3d181011c85447073f5ee4a04153 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sat, 25 Dec 2010 23:56:51 -0500 Subject: [PATCH] [INI] Preparing for merging sections
Patch implements three functions:
- Function to detect a collision between two section names.
- Function to empty section from all its keys
- Function to add values one by one from one section to another.
ini/ini_parse.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 177 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index e7eab28211655f7a225202552fd96b68c1e09450..fc43cb06daca64309e47f43047263c5f066fc43e 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -318,6 +318,183 @@ static int parser_read(struct parser_obj *po) return EOK; }
+/* Find if there is a collistion */ +static int check_section_collision(struct parser_obj *po) +{
- int error = EOK;
- struct collection_item *item = NULL;
- TRACE_FLOW_ENTRY();
- TRACE_INFO_STRING("Searching for:", col_get_item_property(po->sec, NULL));
- error = col_get_item(po->top,
col_get_item_property(po->sec, NULL),
COL_TYPE_ANY,
COL_TRAVERSE_DEFAULT,
&item);
- if (error) {
TRACE_ERROR_NUMBER("Failed searching for dup", error);
return error;
- }
- /* Check if there is a dup */
- if (item) {
TRACE_INFO_STRING("Collision found:",
col_get_item_property(item, NULL));
/* Get the actual section collection instead of reference */
po->merge_sec = *((struct collection_item **)
(col_get_item_data(item)));
- }
- else {
TRACE_INFO_STRING("Collision not found.", "");
po->merge_sec = NULL;
- }
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Clean all items in the section */ +static int empty_section(struct collection_item *sec) +{
- int error = EOK;
- struct collection_item *item = NULL;
- struct collection_item *save_item = NULL;
- struct value_obj *vo = NULL;
- int work_to_do = 1;
- TRACE_FLOW_ENTRY();
- do {
item = NULL;
error = col_extract_item_from_current(sec,
COL_DSP_FRONT,
NULL,
0,
COL_TYPE_ANY,
&item);
if ((error) && (error != ENOENT)) {
TRACE_ERROR_NUMBER("Failed to extract item.", error);
return error;
}
if (item) {
TRACE_INFO_STRING("Item found:",
col_get_item_property(item, NULL));
if (strncmp(col_get_item_property(item, NULL),
INI_SECTION_KEY, 1) == 0) {
/* Just ignore the first item */
save_item = item;
continue;
}
vo = *((struct value_obj **)(col_get_item_data(item)));
value_destroy(vo);
col_delete_item(item);
}
else {
TRACE_INFO_STRING("No more items:", "");
/* Restore saved item */
error = col_insert_item(sec,
NULL,
save_item,
COL_DSP_END,
NULL,
0,
COL_INSERT_NOCHECK);
if (error) {
TRACE_ERROR_NUMBER("Failed to restore item.", error);
return error;
}
work_to_do = 0;
}
- }
- while (work_to_do);
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Merge contents of the section */ +static int merge_section(struct parser_obj *po) +{
- int error = EOK;
- struct collection_item *item = NULL;
- struct value_obj *vo = NULL;
- int work_to_do = 1;
- const char *key;
- TRACE_FLOW_ENTRY();
- do {
TRACE_INFO_STRING("Top of the merge loop", "");
item = NULL;
error = col_extract_item_from_current(po->sec,
COL_DSP_FRONT,
NULL,
0,
COL_TYPE_ANY,
&item);
if ((error) && (error != ENOENT)) {
TRACE_ERROR_NUMBER("Failed to extract item.", error);
return error;
}
if (item) {
TRACE_INFO_STRING("Item found:", col_get_item_property(item, NULL));
if (strncmp(col_get_item_property(item, NULL),
INI_SECTION_KEY, 1) == 0) {
/* Just ignore the first item */
vo = *((struct value_obj **)(col_get_item_data(item)));
value_destroy(vo);
col_delete_item(item);
continue;
}
po->merge_vo = *((struct value_obj **)(col_get_item_data(item)));
key = col_get_item_property(item, NULL);
/* To be able to use po->merge_key in the loop
* we have to overcome constraints imposed by
* the "const" declaration.
*/
memcpy(&(po->merge_key), &key, sizeof(char *));
/* Use the value processing function to inser the value */
error = complete_value_processing(po);
/* In case of error value is already cleaned */
po->merge_vo = NULL;
po->merge_key = NULL;
col_delete_item(item);
/* Now we can check the error */
if (error) {
TRACE_ERROR_NUMBER("Failed to merge item.", error);
return error;
}
}
else {
TRACE_INFO_STRING("No more items:", "");
work_to_do = 0;
}
- }
- while (work_to_do);
- /* If we reached this place the incoming section is empty.
* but just to be safe clean with callback. */
- col_destroy_collection_with_cb(po->sec, ini_cleanup_cb, NULL);
- po->sec = NULL;
- TRACE_FLOW_EXIT();
- return EOK;
+}
/* Function to read next line from the file */ static int parser_save_section(struct parser_obj *po) { -- 1.5.5.6
From aa35a75674482febe3f5f67b3e7c7c7faf507f05 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:03:33 -0500 Subject: [PATCH] [INI] Enhance value processing
This patch refactores the value processing function so that it can be used both in normal mode when velues need to be constrcuted and saved into the current section (po->sec) and in the merge mode when values are already constructed and need to be saved into a po->merge_sec.
ini/ini_parse.c | 165 ++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 116 insertions(+), 49 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index fc43cb06daca64309e47f43047263c5f066fc43e..5dd873a339e5fce36bc13ea8bde65dbefc5d617f 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -529,6 +529,7 @@ static int parser_save_section(struct parser_obj *po) static int complete_value_processing(struct parser_obj *po) { int error = EOK;
- int error2 = EOK; struct value_obj *vo = NULL; struct value_obj *vo_old = NULL; unsigned insertmode;
@@ -536,12 +537,19 @@ static int complete_value_processing(struct parser_obj *po) int suppress = 0; int doinsert = 0; struct collection_item *item = NULL;
struct collection_item *section = NULL;
int merging = 0;
TRACE_FLOW_ENTRY();
- /* If there is not open section create a default one */
- if(!(po->sec)) {
/* Create a new section */
- if (po->merge_sec) {
TRACE_INFO_STRING("Processing value in merge mode", "");
section = po->merge_sec;
merging = 1;
- }
- else if(!(po->sec)) {
TRACE_INFO_STRING("Creating default section", "");
/* If there is not open section create a default one */ error = col_create_collection(&po->sec, INI_DEFAULT_SECTION, COL_CLASS_INI_SECTION);
@@ -549,29 +557,44 @@ static int complete_value_processing(struct parser_obj *po) TRACE_ERROR_NUMBER("Failed to create default section", error); return error; }
}section = po->sec;
- /* Construct value object from what we have */
- error = value_create_from_refarray(po->raw_lines,
po->raw_lengths,
po->keylinenum,
INI_VALUE_READ,
po->key_len,
po->boundary,
po->ic,
&vo);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create value object", error);
return error;
- else {
TRACE_INFO_STRING("Processing value in normal mode", "");
}section = po->sec;
- /* Forget about the arrays. They are now owned by the value object */
- po->ic = NULL;
- po->raw_lines = NULL;
- po->raw_lengths = NULL;
- if (merging) {
TRACE_INFO_STRING("Using merge key:", po->merge_key);
vo = po->merge_vo;
/* We are adding to the merge section so use MV2S flags.
* But flags are done in such a way that deviding MV2S by MV1S mask
* will translate MV2S flags into MV1S so we can use
* MV1S constants. */
TRACE_INFO_NUMBER("Collisions flags:", po->collision_flags);
mergemode = (po->collision_flags & INI_MV2S_MASK) / INI_MV1S_MASK;
- }
- else {
/* Construct value object from what we have */
error = value_create_from_refarray(po->raw_lines,
po->raw_lengths,
po->keylinenum,
INI_VALUE_READ,
po->key_len,
po->boundary,
po->ic,
&vo);
- mergemode = po->collision_flags & INI_MV1S_MASK;
if (error) {
TRACE_ERROR_NUMBER("Failed to create value object", error);
return error;
}
/* Forget about the arrays. They are now owned by the value object */
po->ic = NULL;
po->raw_lines = NULL;
po->raw_lengths = NULL;
mergemode = po->collision_flags & INI_MV1S_MASK;
}
switch (mergemode) { case INI_MV1S_ERROR: insertmode = COL_INSERT_DUPERROR;
@@ -585,16 +608,18 @@ static int complete_value_processing(struct parser_obj *po) doinsert = 1; break; case INI_MV1S_OVERWRITE: /* Special handling */
case INI_MV1S_DETECT: default: break; }
/* Do not insert but search for dups first */ if (!doinsert) {
TRACE_INFO_STRING("Ovewrite mode. Lokking for:", po->key);
TRACE_INFO_STRING("Overwrite mode. Looking for:",
(char *)(merging ? po->merge_key : po->key));
error = col_get_item(po->sec,
po->key,
error = col_get_item(section,
merging ? po->merge_key : po->key, COL_TYPE_BINARY, COL_TRAVERSE_DEFAULT, &item);
@@ -607,21 +632,42 @@ static int complete_value_processing(struct parser_obj *po)
/* Check if there is a dup */ if (item) {
/* Dup exists - update it */
vo_old = *((struct value_obj **)(col_get_item_data(item)));
error = col_modify_binary_item(item,
NULL,
&vo,
sizeof(struct value_obj *));
if (error) {
TRACE_ERROR_NUMBER("Failed updating the value", error);
value_destroy(vo);
return error;
/* Check if we are in the detect mode */
if (mergemode == INI_MV1S_DETECT) {
po->merge_error = EEXIST;
/* There is a dup - inform user about it and continue */
error = save_error(po->el,
merging ? po->seclinenum : po->keylinenum,
merging ? ERR_DUPKEYSEC : ERR_DUPKEY,
0);
if (error) {
TRACE_ERROR_NUMBER("Failed to save error", error);
value_destroy(vo);
return error;
}
doinsert = 1;
insertmode = COL_INSERT_NOCHECK;
}
else {
/* Dup exists - update it */
vo_old = *((struct value_obj **)(col_get_item_data(item)));
error = col_modify_binary_item(item,
NULL,
&vo,
sizeof(struct value_obj *));
if (error) {
TRACE_ERROR_NUMBER("Failed updating the value", error);
value_destroy(vo);
return error;
}
/* If we failed to update it is better to leak then crash,
* so destroy original value only on the successful update.
*/
value_destroy(vo_old); }
/* If we failed to update it is better to leak then crash,
* so desctroy original value only on the successful update.
*/
value_destroy(vo_old); } else { /* No dup found so we can insert with no check */
@@ -632,31 +678,52 @@ static int complete_value_processing(struct parser_obj *po)
if (doinsert) { /* Add value to collection */
error = col_insert_binary_property(po->sec,
error = col_insert_binary_property(section, NULL, COL_DSP_END, NULL, 0, insertmode,
po->key,
merging ? po->merge_key : po->key, &vo, sizeof(struct value_obj *)); if (error) {
value_destroy(vo);
if ((suppress) && (error == EEXIST)) {
TRACE_INFO_STRING("Preseved exisitng value", po->key);
value_destroy(vo);
TRACE_INFO_STRING("Preseved exisitng value",
(char *)(merging ? po->merge_key : po->key)); } else {
TRACE_ERROR_NUMBER("Failed to add value object to the section", error);
value_destroy(vo);
return error;
/* Check if this is a critical error or not */
if ((mergemode == INI_MV1S_ERROR) && (error == EEXIST)) {
TRACE_ERROR_NUMBER("Failed to add value object "
"to the section", error);
error2 = save_error(po->el,
merging ? po->seclinenum : po->keylinenum,
merging ? ERR_DUPKEYSEC : ERR_DUPKEY,
0);
if (error2) {
TRACE_ERROR_NUMBER("Failed to save error", error2);
return error2;
}
return error;
}
else {
TRACE_ERROR_NUMBER("Failed to add value object"
" to the section", error);
return error;
}} } }
- free(po->key);
- po->key = NULL;
- po->key_len = 0;
- if (!merging) {
free(po->key);
po->key = NULL;
po->key_len = 0;
- }
- TRACE_FLOW_EXIT(); return EOK;
}
1.5.5.6
From f5e1f6494f6350d41fce3e063a8aebf72aa7c4ea Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:05:28 -0500 Subject: [PATCH] [INI] Use section line number
Use section line number for error reporting about the section collisions.
ini/ini_parse.c | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 5dd873a339e5fce36bc13ea8bde65dbefc5d617f..a1c3a26f0f88c80616bad5336be1126a1f9b99bf 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -1069,9 +1069,12 @@ static int handle_section(struct parser_obj *po, uint32_t *action) }
/* Save the line number of the last found key */
- po->keylinenum = po->linenum;
- po->seclinenum = po->linenum;
- /* Complete processing of this value */
- /* Complete processing of this value.
* A new section will be created inside and a special
* value will be added.
error = complete_value_processing(po); if (error) { TRACE_ERROR_NUMBER("Failed to complete value processing", error);*/
-- 1.5.5.6
From 6d4b2785106cd6614eedb62069da76ecc2e90457 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:08:19 -0500 Subject: [PATCH] [INI] Refactor section processing
This patch adds functionality to respect merge section flags and to process section collisions differently dpending on these flags.
ini/ini_parse.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 105 insertions(+), 9 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index a1c3a26f0f88c80616bad5336be1126a1f9b99bf..d9c6d0a9bc71f197eb4bf752fd56958ba6f64df2 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -499,25 +499,121 @@ static int merge_section(struct parser_obj *po) static int parser_save_section(struct parser_obj *po) { int error = EOK;
uint32_t mergemode;
int add = 0;
int merge = 0;
TRACE_FLOW_ENTRY();
if (po->sec) {
/* For now just add as we did.
* Add merge code here !!!!
*/
error = col_add_collection_to_collection(po->top,
NULL, NULL,
po->sec,
COL_ADD_MODE_EMBED);
TRACE_INFO_STRING("Section exists.", "");
/* First detect if we have collision */
error = check_section_collision(po); if (error) {
TRACE_ERROR_NUMBER("Failed to embed section", error);
TRACE_ERROR_NUMBER("Failed to check for collision", error); return error; }
po->sec = NULL;
if (po->merge_sec) {
TRACE_INFO_STRING("Merge collision detected", "");
mergemode = po->collision_flags & INI_MS_MASK;
switch (mergemode) {
case INI_MS_ERROR: /* Report error and return */
TRACE_INFO_STRING("Reporting error",
"duplicate section");
error = save_error(po->el,
po->seclinenum,
ERR_DUPSECTION,
0);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"save error",
error);
return error;
}
/* Return error */
TRACE_FLOW_RETURN(EEXIST);
return EEXIST;
case INI_MS_PRESERVE: /* Delete new section */
TRACE_INFO_STRING("Preserve mode", "");
col_destroy_collection_with_cb(
po->sec,
ini_cleanup_cb,
NULL);
po->sec = NULL;
break;
case INI_MS_ALLOW: TRACE_INFO_STRING("Allow mode", "");
add = 1;
break;
case INI_MS_OVERWRITE: /* Empty existing section */
TRACE_INFO_STRING("Ovewrite mode", "");
error = empty_section(po->merge_sec);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"empty section",
error);
return error;
}
merge = 1;
break;
case INI_MS_DETECT: /* Detect mode */
TRACE_INFO_STRING("Detect mode", "");
po->merge_error = EEXIST;
error = save_error(po->el,
po->seclinenum,
ERR_DUPSECTION,
0);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"save error",
error);
return error;
}
merge = 1;
break;
case INI_MS_MERGE: /* Merge */
default: TRACE_INFO_STRING("Merge mode", "");
merge = 1;
break;
}
if (merge) {
error = merge_section(po);
if (error) {
TRACE_ERROR_NUMBER("Failed to merge section", error);
return error;
}
}
po->merge_sec = NULL;
}
else add = 1;
if (add) {
/* Add section to configuration */
TRACE_INFO_STRING("Now adding collection", "");
error = col_add_collection_to_collection(po->top,
NULL, NULL,
po->sec,
COL_ADD_MODE_EMBED);
if (error) {
TRACE_ERROR_NUMBER("Failed to embed section", error);
return error;
}
po->sec = NULL;
}
}
TRACE_FLOW_EXIT();
-- 1.5.5.6
From 8fb3799dc674770bb622b630267a7a436449069e Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:10:23 -0500 Subject: [PATCH] [INI] Return error in DETECT mode
If in merge DETECT mode and there were no parsing errors return error if there were merge collisions.
ini/ini_parse.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index d9c6d0a9bc71f197eb4bf752fd56958ba6f64df2..3f45ac71ae46dff3413a6d4db5dd59a0838d078b 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -1441,7 +1441,18 @@ int parser_run(struct parser_obj *po) col_delete_item(item);
if (action == PARSE_DONE) {
TRACE_INFO_NUMBER("We are done", error);
/* Report merge error in detect mode
* if no other error was detected. */
if ((po->ret == 0) &&
(po->merge_error != 0) &&
((po->collision_flags & INI_MV1S_DETECT) ||
(po->collision_flags & INI_MV2S_DETECT) ||
(po->collision_flags & INI_MS_DETECT)))
po->ret = po->merge_error;
error = po->ret; break; }
-- 1.5.5.6
From 235393228925b4aee6138820276450c233853464 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:15:12 -0500 Subject: [PATCH] [INI] New test files for section merge
smerge.conf - test file sexpect.conf - file contains output of the smerge.conf processed in different merge modes for sections and values
Makefile.am | 4 +- ini/ini.d/sexpect.conf | 644 ++++++++++++++++++++++++++++++++++++++++++++++++ ini/ini.d/smerge.conf | 33 +++ 3 files changed, 680 insertions(+), 1 deletions(-) create mode 100644 ini/ini.d/sexpect.conf create mode 100644 ini/ini.d/smerge.conf
diff --git a/Makefile.am b/Makefile.am index 1780e9b234e68006af910413b3e8312c9db72c7b..4f9ab3427bb309b19ddec0da5e2125046d03babc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -280,7 +280,9 @@ dist_noinst_DATA += \ ini/ini.d/test.conf \ ini/ini.d/ipa.conf \ ini/ini.d/foo.conf \
- ini/ini.d/mysssd.conf
- ini/ini.d/mysssd.conf \
- ini/ini.d/smerge.conf \
- ini/ini.d/sexpect.conf
check_PROGRAMS += \ ini_config_ut \ diff --git a/ini/ini.d/sexpect.conf b/ini/ini.d/sexpect.conf new file mode 100644 index 0000000000000000000000000000000000000000..6a9222b0a9003ed1a6e9c10401573832980a3706 --- /dev/null +++ b/ini/ini.d/sexpect.conf @@ -0,0 +1,644 @@ +# Section mode: MERGE, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: MERGE, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: MERGE, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+#End of file +# Section mode: MERGE, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: MERGE, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ERROR, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ERROR, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: OVERWRITE, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: ERROR +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: ALLOW +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: OVERWRITE, value mode: DETECT +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: PRESERVE, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: PRESERVE, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: ALLOW, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: ALLOW, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: DETECT, value mode: OVERWRITE +[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: DETECT, value mode: ERROR +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Section mode: DETECT, value mode: PRESERVE +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+#End of file +# Section mode: DETECT, value mode: ALLOW +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file +# Section mode: DETECT, value mode: DETECT +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3 +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3 +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file diff --git a/ini/ini.d/smerge.conf b/ini/ini.d/smerge.conf new file mode 100644 index 0000000000000000000000000000000000000000..bdec46d86fb6ecd0d39f4b50aca01a53dabd9ebf --- /dev/null +++ b/ini/ini.d/smerge.conf @@ -0,0 +1,33 @@ +[section1] +# Key 1 +key1 = section1a Value 1 +# Key 2 +key2 = section1a Value 2 +# Key 3 +key3 = section1a Value 3
+[section2] +# Key 1 +key1 = section2a Value 1 +# Key 2 +key2 = section2a Value 2 +# Key 3 +key3 = section2a Value 3
+[section1] +# Key 1 +key1 = section1b Value 1 +# Key 2 +key2 = section1b Value 2 +# Key 3 +key3 = section1b Value 3
+[section2] +# Key 1 +key1 = section2b Value 1 +# Key 2 +key2 = section2b Value 2 +# Key 3 +key3 = section2b Value 3
+#End of file
1.5.5.6
From a2b8565c919f3b39e9d7eeef9baa29081bb80f43 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:18:48 -0500 Subject: [PATCH] [INI] Test DETECT mode and use new file
Patch adds smerge.conf file to the list of files to test and adds test for the DETECT mode for inidividual values.
ini/ini_parse_ut.c | 30 +++++++++++++++++++++++------- 1 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 9327ebaab2dc529b593e0b550011bbac6b949b94..40c64bb15c0535dd2e8f5e62129a31ae53c3f35f 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -173,6 +173,7 @@ int read_save_test(void) "mysssd", "ipa", "test",
"smerge", NULL };
@@ -203,6 +204,7 @@ int read_again_test(void) "mysssd", "ipa", "test",
"smerge", NULL };
@@ -279,14 +281,25 @@ int create_expect(const char *checkname) fprintf(ff,"#Second value\n"); fprintf(ff,"bar = second value\n"); fprintf(ff,"#End of section\n");
/* Detect */
fprintf(ff,"#Hoho section\n");
fprintf(ff,"[hoho]\n");
fprintf(ff,"#Hoho value\n");
fprintf(ff,"val = hoho\n");
fprintf(ff,"#End of hoho\n");
fprintf(ff,"#Start of section\n");
fprintf(ff,"[foo]\n");
fprintf(ff,"#First value\n");
fprintf(ff,"bar = first value\n");
fprintf(ff,"#Second value\n");
fprintf(ff,"bar = second value\n");
fprintf(ff,"#End of section\n");
fclose(ff);
return EOK;
}
/* Check merge modes */ int merge_values_test(void) { @@ -301,12 +314,14 @@ int merge_values_test(void) uint32_t mflags[] = { INI_MV1S_OVERWRITE, INI_MV1S_ERROR, INI_MV1S_PRESERVE,
INI_MV1S_ALLOW };
INI_MV1S_ALLOW,
INI_MV1S_DETECT };
const char *mstr[] = { "OVERWRITE", "ERROR", "PRESERVE",
"ALLOW" };
"ALLOW",
"DETECT" };
char filename[PATH_MAX]; const char *resname = "./merge.conf.out";
@@ -323,7 +338,7 @@ int merge_values_test(void) return error; }
- for (i = 0; i < 4; i++) {
for (i = 0; i < 5; i++) {
INIOUT(printf("<==== Testing mode %s ====>\n", mstr[i]));
@@ -360,8 +375,9 @@ int merge_values_test(void) ini_config_free_errors(error_list); }
if ((mflags[i] != INI_MV1S_ERROR) ||
((mflags[i] = INI_MV1S_ERROR) && (error != EEXIST))) {
if (((mflags[i] != INI_MV1S_ERROR) && (mflags[i]!= INI_MV1S_DETECT)) ||
((mflags[i] = INI_MV1S_ERROR) && (error != EEXIST)) ||
((mflags[i] = INI_MV1S_DETECT) && (error != EEXIST))) { printf("This is unexpected error %d in mode %d\n", error, mflags[i]); ini_config_destroy(ini_config); simplebuffer_free(sbobj);
-- 1.5.5.6
From 24241d6fa2aa0b7e1595f0600d28238945f647d3 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 00:20:54 -0500 Subject: [PATCH] [INI] Test for all section merge modes
New test reads smerge.conf in all possible modes and compares the combined result with the sexpect.conf function.
ini/ini_parse_ut.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 188 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 40c64bb15c0535dd2e8f5e62129a31ae53c3f35f..95793dc39cfa73966192802a12d9bdc54c5ec545 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -438,6 +438,193 @@ int merge_values_test(void) resname, checkname, error));
return error;
+}
+/* Check merge modes */ +int merge_section_test(void) +{
- int error = EOK;
- int i, j;
- struct ini_cfgfile *file_ctx = NULL;
- FILE *ff = NULL;
- struct ini_cfgobj *ini_config = NULL;
- char **error_list = NULL;
- struct simplebuffer *sbobj = NULL;
- uint32_t left = 0;
- uint32_t msecflags[] = { INI_MS_MERGE,
INI_MS_ERROR,
INI_MS_OVERWRITE,
INI_MS_PRESERVE,
INI_MS_ALLOW,
INI_MS_DETECT };
- uint32_t mflags[] = { INI_MV2S_OVERWRITE,
INI_MV2S_ERROR,
INI_MV2S_PRESERVE,
INI_MV2S_ALLOW,
INI_MV2S_DETECT };
- const char *secmstr[] = { "MERGE",
"ERROR",
"OVERWRITE",
"PRESERVE",
"ALLOW",
"DETECT" };
- const char *mstr[] = { "OVERWRITE",
"ERROR",
"PRESERVE",
"ALLOW",
"DETECT" };
- char filename[PATH_MAX];
- char checkname[PATH_MAX];
- const char *resname = "./smerge.conf.out";
- char command[PATH_MAX * 3];
- char mode[100];
- char *srcdir;
- srcdir = getenv("srcdir");
- sprintf(filename, "%s/ini/ini.d/smerge.conf",
(srcdir == NULL) ? "." : srcdir);
- sprintf(checkname, "%s/ini/ini.d/sexpect.conf",
(srcdir == NULL) ? "." : srcdir);
- error = simplebuffer_alloc(&sbobj);
- if (error) {
TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error);
return error;
- }
- for (i = 0; i < 6; i++) {
for (j = 0; j < 5; j++) {
INIOUT(printf("<==== Testing mode %s + %s ====>\n",
secmstr[i], mstr[j]));
sprintf(mode, "# Section mode: %s, value mode: %s\n",
secmstr[i], mstr[j]);
error = simplebuffer_add_str(sbobj,
mode,
strlen(mode),
100);
if (error) {
TRACE_ERROR_NUMBER("Failed to add string.",
error);
simplebuffer_free(sbobj);
return error;
}
/* Create config collection */
error = ini_config_create(&ini_config);
if (error) {
printf("Failed to create collection. "
"Error %d.\n", error);
simplebuffer_free(sbobj);
return error;
}
error = ini_config_file_open(filename,
INI_STOP_ON_ANY,
msecflags[i] | mflags[j],
0, /* TBD */
&file_ctx);
if (error) {
printf("Failed to open file for reading. "
"Error %d.\n", error);
ini_config_destroy(ini_config);
simplebuffer_free(sbobj);
return error;
}
error = ini_config_parse(file_ctx,
ini_config);
if (error) {
INIOUT(printf("Failed to parse configuration. "
"Error %d.\n", error));
if (ini_config_error_count(file_ctx)) {
INIOUT(printf("Errors detected while parsing: %s\n",
ini_config_get_filename(file_ctx)));
ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
ini_config_free_errors(error_list);
}
if (((msecflags[i] == INI_MS_ERROR) &&
(error == EEXIST)) ||
((msecflags[i] == INI_MS_DETECT) &&
(error == EEXIST)) ||
((msecflags[i] == INI_MS_MERGE) &&
((mflags[j] == INI_MV2S_ERROR) ||
(mflags[j] == INI_MV2S_DETECT)) &&
(error == EEXIST))) {
INIOUT(printf("This is an expected error "
"%d in mode %d + %d\n",
error,
msecflags[i],
mflags[j]));
/* We do not return here intentionally */
}
else {
printf("This is unexpected error %d in mode %d + %d\n",
error, msecflags[i], mflags[j]);
ini_config_destroy(ini_config);
simplebuffer_free(sbobj);
ini_config_file_close(file_ctx);
return error;
}
}
ini_config_file_close(file_ctx);
INIOUT(col_debug_collection(ini_config->cfg,
COL_TRAVERSE_DEFAULT));
error = ini_config_serialize(ini_config, sbobj);
if (error != EOK) {
printf("Failed to serialize configuration. "
"Error %d.\n", error);
ini_config_destroy(ini_config);
simplebuffer_free(sbobj);
return error;
}
ini_config_destroy(ini_config);
}
- }
- errno = 0;
- ff = fopen(resname, "w");
- if(!ff) {
error = errno;
printf("Failed to open file for writing. Error %d.\n", error);
simplebuffer_free(sbobj);
return error;
- }
- /* Save */
- left = simplebuffer_get_len(sbobj);
- while (left > 0) {
error = simplebuffer_write(fileno(ff), sbobj, &left);
if (error) {
printf("Failed to write back the configuration %d.\n", error);
simplebuffer_free(sbobj);
fclose(ff);
return error;
}
- }
- simplebuffer_free(sbobj);
- fclose(ff);
- sprintf(command,"diff -q %s %s", resname, checkname);
- error = system(command);
- INIOUT(printf("Comparison of %s %s returned: %d\n",
resname, checkname, error));
- return error;
} @@ -449,6 +636,7 @@ int main(int argc, char *argv[]) test_fn tests[] = { read_save_test, read_again_test, merge_values_test,
test_fn t; int i = 0;merge_section_test, NULL };
-- 1.5.5.6
From 8176dad24b0124a634450741f00b2d03c48ce437 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 18:08:27 -0500 Subject: [PATCH] [INI] Separate close and destroy
Allow closing file without destroying the context.
ini/ini_configobj.h | 5 ++++- ini/ini_fileobj.c | 25 +++++++++++++++++++------ ini/ini_parse_ut.c | 10 +++++----- 3 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index f0c6882dbb1e066972f98309bf78a99670b985c5..e728c2e3cbc787586a542a184a07593ad1e03331 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -213,9 +213,12 @@ int ini_config_file_open(const char *filename, uint32_t metadata_flags, struct ini_cfgfile **file_ctx);
-/* Close file context and destroy the object */ +/* Close file context */ void ini_config_file_close(struct ini_cfgfile *file_ctx);
+/* Close file context and destroy the object */ +void ini_config_file_destroy(struct ini_cfgfile *file_ctx);
/* How many errors do we have in the list ? */ unsigned ini_config_error_count(struct ini_cfgfile *file_ctx);
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 7bc599b948563964830f9ade75966cf4f9aa3018..f998eb09d1b5c271be9a316196a510bac39455c2 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -75,12 +75,25 @@ static int valid_collision_flags(uint32_t collision_flags) return 1; }
-/* Close file context and destroy the object */
+/* Close file but not destroy the object */ void ini_config_file_close(struct ini_cfgfile *file_ctx) { TRACE_FLOW_ENTRY();
if(file_ctx) {
if(file_ctx->file) fclose(file_ctx->file);
- }
- TRACE_FLOW_EXIT();
+}
+/* Close file context and destroy the object */ +void ini_config_file_destroy(struct ini_cfgfile *file_ctx) +{
- TRACE_FLOW_ENTRY();
- if(file_ctx) { free(file_ctx->filename); col_destroy_collection(file_ctx->error_list); col_destroy_collection(file_ctx->metadata);
@@ -144,7 +157,7 @@ int ini_config_file_open(const char *filename, new_ctx->filename = malloc(PATH_MAX + 1); if (!(new_ctx->filename)) { error = errno;
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); TRACE_ERROR_NUMBER("Failed to allocate memory for file path.", error); return error;
@@ -155,7 +168,7 @@ int ini_config_file_open(const char *filename, filename); if(error) { TRACE_ERROR_NUMBER("Failed to resolve path", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
@@ -166,7 +179,7 @@ int ini_config_file_open(const char *filename, if (!(new_ctx->file)) { error = errno; TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
@@ -176,7 +189,7 @@ int ini_config_file_open(const char *filename, COL_CLASS_INI_PERROR); if (error) { TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
@@ -185,7 +198,7 @@ int ini_config_file_open(const char *filename, COL_CLASS_INI_META); if (error) { TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
ini_config_file_close(new_ctx);
}ini_config_file_destroy(new_ctx); return error;
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 95793dc39cfa73966192802a12d9bdc54c5ec545..f0a95527aa315b559e5c6fa42740fe4a3ba4e4b3 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -91,7 +91,7 @@ int test_one_file(const char *in_filename, /* We do not return here intentionally */ }
- ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx);
INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
@@ -381,13 +381,13 @@ int merge_values_test(void) printf("This is unexpected error %d in mode %d\n", error, mflags[i]); ini_config_destroy(ini_config); simplebuffer_free(sbobj);
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); return error; } /* We do not return here intentionally */ }
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
@@ -572,12 +572,12 @@ int merge_section_test(void) error, msecflags[i], mflags[j]); ini_config_destroy(ini_config); simplebuffer_free(sbobj);
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); return error; } }
ini_config_file_close(file_ctx);
ini_config_file_destroy(file_ctx); INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
-- 1.5.5.6
From 29e4a0a028b802eaa3bb1dfbc7a9080fc7f21f4b Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 18:34:02 -0500 Subject: [PATCH] [INI] Function to reopen file
This patch would allow to reopen file and create a new context based on the old one.
ini/ini_configobj.h | 4 ++ ini/ini_fileobj.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 0 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index e728c2e3cbc787586a542a184a07593ad1e03331..3321bd3ea8985b9b12f04ab792fbcac307bbbe2e 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -213,6 +213,10 @@ int ini_config_file_open(const char *filename, uint32_t metadata_flags, struct ini_cfgfile **file_ctx);
+/* Create a file object from existing one */ +int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in,
struct ini_cfgfile **file_ctx_out);
/* Close file context */ void ini_config_file_close(struct ini_cfgfile *file_ctx);
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index f998eb09d1b5c271be9a316196a510bac39455c2..200c7af9de896c1abd26a57a508f9f540475b19d 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -210,6 +210,92 @@ int ini_config_file_open(const char *filename, return error; }
+/* Create a file object from existing one */ +int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in,
struct ini_cfgfile **file_ctx_out)
+{
- int error = EOK;
- struct ini_cfgfile *new_ctx = NULL;
- TRACE_FLOW_ENTRY();
- if ((!file_ctx_in) || (!file_ctx_out)) {
TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
return EINVAL;
- }
- /* Allocate structure */
- errno = 0;
- new_ctx = malloc(sizeof(struct ini_cfgfile));
- if (!new_ctx) {
error = errno;
TRACE_ERROR_NUMBER("Failed to allocate file ctx.", error);
return error;
- }
- new_ctx->filename = NULL;
- new_ctx->file = NULL;
- new_ctx->error_list = NULL;
- new_ctx->metadata = NULL;
- /* TBD - decide whether we actually need an FD.
It will be done when we move the metadata
processing into this function. */
- new_ctx->fd = -1;
- /* Store flags */
- new_ctx->error_level = file_ctx_in->error_level;
- new_ctx->collision_flags = file_ctx_in->collision_flags;
- new_ctx->metadata_flags = file_ctx_in->metadata_flags;
- new_ctx->count = 0;
- /* Copy full file path */
- errno = 0;
- new_ctx->filename = strndup(file_ctx_in->filename, PATH_MAX);
- if (!(new_ctx->filename)) {
error = errno;
ini_config_file_destroy(new_ctx);
TRACE_ERROR_NUMBER("Failed to allocate memory for file path.", error);
return error;
- }
- /* Open file */
- TRACE_INFO_STRING("File", new_ctx->filename);
- errno = 0;
- new_ctx->file = fopen(new_ctx->filename, "r");
- if (!(new_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(new_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_close(new_ctx);
return error;
- }
- error = col_create_collection(&(new_ctx->metadata),
INI_METADATA,
COL_CLASS_INI_META);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* TBD - Add metadata processing here */
- *file_ctx_out = new_ctx;
- TRACE_FLOW_EXIT();
- return error;
+}
/* How many errors do we have in the list ? */ unsigned ini_config_error_count(struct ini_cfgfile *file_ctx) -- 1.5.5.6
From 7030e51bb22e62e6f5d63b0faa923d2151336818 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 19:21:32 -0500 Subject: [PATCH] [INI] Metadata collection is gone
After some more thinking I decided not to use metadata collection. It seems to be an overhead. Patch does following:
- Replaces metadata collection in file context structure with standard file stats
- Removes all operations against old metadata collection
- Defines new flags for data to collect
- Creates a function that consolidates common operations between open and reopen functions.
ini/ini_config_priv.h | 11 +++-- ini/ini_configobj.h | 20 ++++++++ ini/ini_fileobj.c | 121 ++++++++++++++++++++----------------------------- 3 files changed, 75 insertions(+), 77 deletions(-)
diff --git a/ini/ini_config_priv.h b/ini/ini_config_priv.h index 1880c3ff4caa91e7ed3a37e445a20294e76d8037..84742c70ceeb5b493b935c635e81c57d5ef487ce 100644 --- a/ini/ini_config_priv.h +++ b/ini/ini_config_priv.h @@ -22,6 +22,9 @@ #ifndef INI_CONFIG_PRIV_H #define INI_CONFIG_PRIV_H
+#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include "collection.h"
/* Configuration object */ @@ -45,21 +48,19 @@ struct ini_cfgfile { char *filename; /* File stream */ FILE *file;
- /* File descriptor that is passed in */
- int fd; /* Error level */ int error_level; /* Collision flags - define how to merge things */ uint32_t collision_flags;
- /* Collision flags - define how to merge things */
- /* What meta data to collect */ uint32_t metadata_flags; /**********************/ /* Internal variables */ /**********************/ /* Collection of errors detected during parsing */ struct collection_item *error_list;
- /* Metadata about the file */
- struct collection_item *metadata;
- /* File stats */
- struct stat file_stats; /* Count of error lines */ unsigned count;
}; diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 3321bd3ea8985b9b12f04ab792fbcac307bbbe2e..898440252ef3a547566fe2b5e80753d7971a8e47 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -82,6 +82,26 @@ /** @brief Size of the error array. */ #define ERR_MAXPARSE ERR_DUPSECTION
+/**
- @}
- */
+/**
- @defgroup metacollect Constants that define what meta data to collect
- Constants in this section define what meta data to collect
- @{
- */
+/** @brief Do not collect any data. */ +#define INI_META_NONE 0 +/** @brief Collect file stats. */ +#define INI_META_STATS 1
+/**
- @}
- */
/**
- @defgroup collisionflags Flags that define collision resolution logic.
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 200c7af9de896c1abd26a57a508f9f540475b19d..c10b4bf954366ddae90f1d06c53acd0332968599 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -96,7 +96,6 @@ void ini_config_file_destroy(struct ini_cfgfile *file_ctx) if(file_ctx) { free(file_ctx->filename); col_destroy_collection(file_ctx->error_list);
}col_destroy_collection(file_ctx->metadata); if(file_ctx->file) fclose(file_ctx->file); free(file_ctx);
@@ -104,6 +103,47 @@ void ini_config_file_destroy(struct ini_cfgfile *file_ctx) TRACE_FLOW_EXIT(); }
+/* Internal common initialization part */ +static int common_file_init(struct ini_cfgfile *file_ctx) +{
- int error = EOK;
- TRACE_FLOW_ENTRY();
- /* Open file */
- TRACE_INFO_STRING("File", file_ctx->filename);
- errno = 0;
- file_ctx->file = fopen(file_ctx->filename, "r");
- if (!(file_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(file_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
return error;
- }
- /* Collect stats */
- if (file_ctx->metadata_flags & INI_META_STATS) {
errno = 0;
if (fstat(fileno(file_ctx->file),
&(file_ctx->file_stats)) < 0) {
error = errno;
TRACE_ERROR_NUMBER("Failed to get file stats.", error);
return error;
}
- }
- TRACE_FLOW_EXIT();
- return EOK;
+}
/* Create a file object for parsing a config file */ int ini_config_file_open(const char *filename, int error_level, @@ -135,16 +175,9 @@ int ini_config_file_open(const char *filename, return error; }
new_ctx->filename = NULL; new_ctx->file = NULL; new_ctx->error_list = NULL;
new_ctx->metadata = NULL;
/* TBD - decide whether we actually need an FD.
It will be done when we move the metadata
processing into this function. */
new_ctx->fd = -1;
/* Store flags */ new_ctx->error_level = error_level;
@@ -172,39 +205,14 @@ int ini_config_file_open(const char *filename, return error; }
- /* Open file */
- TRACE_INFO_STRING("File", new_ctx->filename);
- errno = 0;
- new_ctx->file = fopen(new_ctx->filename, "r");
- if (!(new_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(new_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- error = col_create_collection(&(new_ctx->metadata),
INI_METADATA,
COL_CLASS_INI_META);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
- /* Do common init */
- error = common_file_init(new_ctx);
- if(error) {
}TRACE_ERROR_NUMBER("Failed to do common init", error); ini_config_file_destroy(new_ctx); return error;
- /* TBD - Add metadata processing here */
- *file_ctx = new_ctx; TRACE_FLOW_EXIT(); return error;
@@ -236,12 +244,6 @@ int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in, new_ctx->filename = NULL; new_ctx->file = NULL; new_ctx->error_list = NULL;
new_ctx->metadata = NULL;
/* TBD - decide whether we actually need an FD.
It will be done when we move the metadata
processing into this function. */
new_ctx->fd = -1;
/* Store flags */ new_ctx->error_level = file_ctx_in->error_level;
@@ -259,39 +261,14 @@ int ini_config_file_reopen(struct ini_cfgfile *file_ctx_in, return error; }
- /* Open file */
- TRACE_INFO_STRING("File", new_ctx->filename);
- errno = 0;
- new_ctx->file = fopen(new_ctx->filename, "r");
- if (!(new_ctx->file)) {
error = errno;
TRACE_ERROR_NUMBER("Failed to open file", error);
ini_config_file_destroy(new_ctx);
return error;
- }
- /* Create internal collections */
- error = col_create_collection(&(new_ctx->error_list),
INI_ERROR,
COL_CLASS_INI_PERROR);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create error list", error);
ini_config_file_close(new_ctx);
return error;
- }
- error = col_create_collection(&(new_ctx->metadata),
INI_METADATA,
COL_CLASS_INI_META);
- if (error) {
TRACE_ERROR_NUMBER("Failed to create metadata collection", error);
- /* Do common init */
- error = common_file_init(new_ctx);
- if(error) {
}TRACE_ERROR_NUMBER("Failed to do common init", error); ini_config_file_destroy(new_ctx); return error;
- /* TBD - Add metadata processing here */
- *file_ctx_out = new_ctx; TRACE_FLOW_EXIT(); return error;
-- 1.5.5.6
From 87be7cfc4b8cc143a582a38a0d024e166d91df35 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 19:46:15 -0500 Subject: [PATCH] [INI] Check access function
Added check access constants and the check access function. The function is effectively copied from ini_metadata.c The flags are copied from ini_config.h
ini/ini_configobj.h | 35 +++++++++++++++++++++++ ini/ini_fileobj.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 898440252ef3a547566fe2b5e80753d7971a8e47..eccad71c7245f1d035c5133c13b6078fc3e3dc5b 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -104,6 +104,41 @@ */
/**
- @defgroup accesscheck Access control check flags
- @{
- */
+/**
- @brief Validate access mode
- If this flag is specified the mode parameter
- will be matched against the permissions set on the file
- using the provided mask.
- */
+#define INI_ACCESS_CHECK_MODE 0x00000001
+/**
- @brief Validate uid
- Provided uid will be checked against uid
- of the file.
- */
+#define INI_ACCESS_CHECK_UID 0x00000002
+/**
- @brief Validate gid
- Provided gid will be checked against gid
- of the file.
- */
+#define INI_ACCESS_CHECK_GID 0x00000004
+/**
- @}
- */
+/**
- @defgroup collisionflags Flags that define collision resolution logic.
- @{
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index c10b4bf954366ddae90f1d06c53acd0332968599..93a9372f3e37489862a33f1676ca68a532c62441 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -406,3 +406,78 @@ const char *ini_config_get_filename(struct ini_cfgfile *file_ctx) TRACE_FLOW_EXIT(); return ret; }
+/* Check access */ +int ini_config_access_check(struct ini_cfgfile *file_ctx,
uint32_t flags,
uid_t uid,
gid_t gid,
mode_t mode,
mode_t mask)
+{
- int error = EOK;
- TRACE_FLOW_ENTRY();
- flags &= INI_ACCESS_CHECK_MODE |
INI_ACCESS_CHECK_GID |
INI_ACCESS_CHECK_UID;
- if ((file_ctx == NULL) || (flags == 0)) {
TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
return EINVAL;
- }
- /* Check mode */
- if (flags & INI_ACCESS_CHECK_MODE) {
TRACE_INFO_NUMBER("File mode as saved.",
file_ctx->file_stats.st_mode);
file_ctx->file_stats.st_mode &= S_IRWXU | S_IRWXG | S_IRWXO;
TRACE_INFO_NUMBER("File mode adjusted.",
file_ctx->file_stats.st_mode);
TRACE_INFO_NUMBER("Mode as provided.", mode);
mode &= S_IRWXU | S_IRWXG | S_IRWXO;
TRACE_INFO_NUMBER("Mode adjusted.", mode);
/* Adjust mask */
if (mask == 0) mask = S_IRWXU | S_IRWXG | S_IRWXO;
else mask &= S_IRWXU | S_IRWXG | S_IRWXO;
if ((mode & mask) != (file_ctx->file_stats.st_mode & mask)) {
TRACE_INFO_NUMBER("File mode:", (mode & mask));
TRACE_INFO_NUMBER("Mode adjusted.",
(file_ctx->file_stats.st_mode & mask));
TRACE_ERROR_NUMBER("Access denied.", EACCES);
return EACCES;
}
- }
- /* Check uid */
- if (flags & INI_ACCESS_CHECK_UID) {
if (file_ctx->file_stats.st_uid != uid) {
TRACE_ERROR_NUMBER("GID:", file_ctx->file_stats.st_uid);
TRACE_ERROR_NUMBER("GID passed in.", uid);
TRACE_ERROR_NUMBER("Access denied.", EACCES);
return EACCES;
}
- }
- /* Check gid */
- if (flags & INI_ACCESS_CHECK_GID) {
if (file_ctx->file_stats.st_gid != gid) {
TRACE_ERROR_NUMBER("GID:", file_ctx->file_stats.st_gid);
TRACE_ERROR_NUMBER("GID passed in.", gid);
TRACE_ERROR_NUMBER("Access denied.", EACCES);
return EACCES;
}
- }
- TRACE_FLOW_EXIT();
- return error;
+}
1.5.5.6
From c4d2383282b898f4c5914bf720301cdcabf5eb51 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:24:08 -0500 Subject: [PATCH] [INI] Avoid double free
I might squash this patch into one of the previous ones.
ini/ini_fileobj.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 93a9372f3e37489862a33f1676ca68a532c62441..2d47c8ff1d1a613dfc5baa8efd00b05c368f8447 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -82,7 +82,10 @@ void ini_config_file_close(struct ini_cfgfile *file_ctx) TRACE_FLOW_ENTRY();
if(file_ctx) {
if(file_ctx->file) fclose(file_ctx->file);
if(file_ctx->file) {
fclose(file_ctx->file);
file_ctx->file = NULL;
}
}
TRACE_FLOW_EXIT();
-- 1.5.5.6
From 81e90b377b432ef874fda11b6e82f6f0eb894807 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:28:59 -0500 Subject: [PATCH] [INI] Function to check for changes
Added function to detect changes to the configuration file.
ini/ini_configobj.h | 4 ++-- ini/ini_fileobj.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index eccad71c7245f1d035c5133c13b6078fc3e3dc5b..913b91e6abed18d30ba256edc280a1d0aa9d76ef 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -335,8 +335,8 @@ int ini_config_access_check(struct ini_cfgfile *file_ctx,
- device ID
- i-node
*/ -int ini_config_changed(struct ini_cfgfile *file_ctx,
struct ini_cfgfile *file_ctx_saved,
+int ini_config_changed(struct ini_cfgfile *file_ctx1,
struct ini_cfgfile *file_ctx2, int *changed);
diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 2d47c8ff1d1a613dfc5baa8efd00b05c368f8447..6de963971a0e9501fb86c23ee5faf6bfb5824bf0 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -484,3 +484,40 @@ int ini_config_access_check(struct ini_cfgfile *file_ctx, return error;
}
+/* Determins if two file context different by comparing
- time stamp
- device ID
- i-node
- */
+int ini_config_changed(struct ini_cfgfile *file_ctx1,
struct ini_cfgfile *file_ctx2,
int *changed)
+{
- int error = EOK;
- TRACE_FLOW_ENTRY();
- if ((file_ctx1 == NULL) ||
(file_ctx2 == NULL) ||
(changed == NULL)) {
TRACE_ERROR_NUMBER("Invalid parameter.", EINVAL);
return EINVAL;
- }
- *changed = 0;
- if((file_ctx1->file_stats.st_mtime !=
file_ctx2->file_stats.st_mtime) ||
(file_ctx1->file_stats.st_dev !=
file_ctx2->file_stats.st_dev) ||
(file_ctx1->file_stats.st_ino !=
file_ctx2->file_stats.st_ino)) {
TRACE_INFO_STRING("File changed!", "");
*changed = 1;
- }
- TRACE_FLOW_EXIT();
- return error;
+}
1.5.5.6
From 2ec4163bcbbcfa6c025b32cdbdbd3adf8c7a84f2 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:31:33 -0500 Subject: [PATCH] [INI] Tests for access and changes
Patch adds two functions. One tests permissions, another validates if the file has changed or not.
ini/ini_parse_ut.c | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 248 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index f0a95527aa315b559e5c6fa42740fe4a3ba4e4b3..f5b1c2c5b4e82de2baf29955901da28afc082cbb 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -625,10 +625,256 @@ int merge_section_test(void) resname, checkname, error));
return error;
+}
+int startup_test(void) +{
- int error = EOK;
- struct ini_cfgfile *file_ctx = NULL;
- struct ini_cfgobj *ini_config = NULL;
- char **error_list = NULL;
- char filename[PATH_MAX];
- char *srcdir;
- srcdir = getenv("srcdir");
- sprintf(filename, "%s/ini/ini.d/foo.conf",
(srcdir == NULL) ? "." : srcdir);
- INIOUT(printf("<==== Startup test ====>\n"));
- /* Open config file */
- error = ini_config_file_open(filename,
INI_STOP_ON_NONE,
0,
INI_META_STATS,
&file_ctx);
- if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
return error;
- }
- /* We will check just permissions here. */
- error = ini_config_access_check(file_ctx,
INI_ACCESS_CHECK_MODE, /* add uid & gui flags
* in real case
*/
0, /* <- will be real uid in real case */
0, /* <- will be real gid in real case */
0440, /* Checking for r--r----- */
0);
- /* This check is expected to fail since
* the actual permissions on the test file are: rw-rw-r--
*/
- if (!error) {
printf("Expected error got success!\n");
ini_config_file_destroy(file_ctx);
return EACCES;
- }
- error = ini_config_access_check(
file_ctx,
INI_ACCESS_CHECK_MODE, /* add uid & gui flags
* in real case
*/
0, /* <- will be real uid in real case */
0, /* <- will be real gid in real case */
0664, /* Checkling for rw-rw-r-- */
0);
- if (error) {
printf("Access check failed %d!\n", error);
ini_config_file_destroy(file_ctx);
return EACCES;
- }
- /* Create config object */
- error = ini_config_create(&ini_config);
- if (error) {
printf("Failed to create collection. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
- }
- error = ini_config_parse(file_ctx,
ini_config);
- if (error) {
INIOUT(printf("Failed to parse configuration. Error %d.\n", error));
if (ini_config_error_count(file_ctx)) {
INIOUT(printf("Errors detected while parsing: %s\n",
ini_config_get_filename(file_ctx)));
ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
ini_config_free_errors(error_list);
}
/* We do not return here intentionally */
- }
- ini_config_file_destroy(file_ctx);
- INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
- ini_config_destroy(ini_config);
- return 0;
+}
+int reload_test(void) +{
int error = EOK;
struct ini_cfgfile *file_ctx = NULL;
struct ini_cfgfile *file_ctx_new = NULL;
char infile[PATH_MAX];
char outfile[PATH_MAX];
char command[PATH_MAX * 3];
char *srcdir;
char *builddir;
int changed = 0;
INIOUT(printf("<==== Reload test ====>\n"));
srcdir = getenv("srcdir");
sprintf(infile, "%s/ini/ini.d/foo.conf",
(srcdir == NULL) ? "." : srcdir);
builddir = getenv("builddir");
sprintf(outfile, "%s/foo.conf",
(builddir == NULL) ? "." : builddir);
sprintf(command, "cp %s %s", infile, outfile);
errno = 0;
if(system(command)) {
error = errno;
printf("Failed to run copy command %d.\n", error);
return error;
}
/* Open config file */
error = ini_config_file_open(outfile,
INI_STOP_ON_NONE,
0,
INI_META_STATS,
&file_ctx);
if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
return error;
}
error = ini_config_access_check(
file_ctx,
INI_ACCESS_CHECK_MODE, /* add uid & gui flags
* in real case
*/
0, /* <- will be real uid in real case */
0, /* <- will be real gid in real case */
0664, /* Checkling for rw-rw-r-- */
0);
if (error) {
printf("Access check failed %d!\n", error);
ini_config_file_destroy(file_ctx);
return EACCES;
}
/* ... Create config object and read configuration - not shown here.
* See other examples ... */
/* Now close file but leave the context around */
ini_config_file_close(file_ctx);
/* Some time passed and we received a signal to reload... */
error = ini_config_file_reopen(file_ctx, &file_ctx_new);
if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
changed = 0;
error = ini_config_changed(file_ctx,
file_ctx_new,
&changed);
if (error) {
printf("Failed to compare files. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return error;
}
/* Check if file changed */
if (changed) {
printf("File changed when it shouldn't. This is unexpected error.\n");
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return EINVAL;
}
/* Close file */
ini_config_file_destroy(file_ctx_new);
/* Emulate as if file changed */
errno = 0;
if (unlink(outfile)) {
error = errno;
printf("Failed to delete file %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
sleep(1);
errno = 0;
if (system(command)) {
error = errno;
printf("Failed to run copy command %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
/* Read again */
file_ctx_new = NULL;
error = ini_config_file_reopen(file_ctx, &file_ctx_new);
if (error) {
printf("Failed to open file for reading. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
return error;
}
changed = 0;
error = ini_config_changed(file_ctx,
file_ctx_new,
&changed);
if (error) {
printf("Failed to compare files. Error %d.\n", error);
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return error;
}
/* Check if file changed */
if (!changed) {
printf("File did not change when it should. This is an error.\n");
ini_config_file_destroy(file_ctx);
ini_config_file_destroy(file_ctx_new);
return EINVAL;
}
/* We do not need original context any more. */
ini_config_file_destroy(file_ctx);
/* New context is now original context */
file_ctx = file_ctx_new;
/* ... Create config object and read configuration - not shown here.
* See other examples ... */
ini_config_file_destroy(file_ctx);
return 0;
}
/* Main function of the unit test */ int main(int argc, char *argv[]) { @@ -637,6 +883,8 @@ int main(int argc, char *argv[]) read_again_test, merge_values_test, merge_section_test,
startup_test,
test_fn t; int i = 0;reload_test, NULL };
-- 1.5.5.6
From 8654e77c640ac19e6997542589fbd1500ae6532d Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:45:39 -0500 Subject: [PATCH] [INI] Rename error print function
All config file processing functions start with "ini_config". The only function that does not comply is ini_print_errors. We can't rename it since it is a part of the current active interface. I marked that function needs to be removed when we remove old interface and created a copy with the correct name. I also updated unit test accordingly.
ini/ini_configobj.h | 5 +---- ini/ini_parse_ut.c | 8 ++++---- ini/ini_print.c | 24 ++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h index 913b91e6abed18d30ba256edc280a1d0aa9d76ef..7089b62da31887e21eeffd6dceff76907ca9f1a6 100644 --- a/ini/ini_configobj.h +++ b/ini/ini_configobj.h @@ -300,10 +300,7 @@ int ini_config_copy(struct ini_cfgobj *ini_config, struct ini_cfgobj **ini_new);
/* Function to print errors from the list */ -void ini_print_errors(FILE *file, char **error_list);
+void ini_config_print_errors(FILE *file, char **error_list);
/* Merge two configurations together creating a new one */ int ini_config_merge(struct ini_cfgobj *first, diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index f5b1c2c5b4e82de2baf29955901da28afc082cbb..696735aacee25fc71f2b60708aaf3d0e14081f2c 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -85,7 +85,7 @@ int test_one_file(const char *in_filename, INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); } /* We do not return here intentionally */
@@ -371,7 +371,7 @@ int merge_values_test(void) INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); }
@@ -548,7 +548,7 @@ int merge_section_test(void) INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); }
@@ -706,7 +706,7 @@ int startup_test(void) INIOUT(printf("Errors detected while parsing: %s\n", ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list);
INIOUT(ini_print_errors(stdout, error_list));
INIOUT(ini_config_print_errors(stdout, error_list)); ini_config_free_errors(error_list); } /* We do not return here intentionally */
diff --git a/ini/ini_print.c b/ini/ini_print.c index 1dcfa54bfd72daf2c790d04c37ff2b3107eb7295..42bd6fc221c71bf4f390a79e02a4928ecf747bd9 100644 --- a/ini/ini_print.c +++ b/ini/ini_print.c @@ -461,6 +461,9 @@ void print_config_parsing_errors(FILE *file,
/* Function to print errors from the list */ +/* THIS FUNCTION SHOUD BE REMOVED WHEN
- OLD INTERFACE IS REMOVED - TBD.
- */
void ini_print_errors(FILE *file, char **error_list) { unsigned count = 0; @@ -480,3 +483,24 @@ void ini_print_errors(FILE *file, char **error_list) TRACE_FLOW_EXIT(); return; }
+/* Function to print errors from the list */ +void ini_config_print_errors(FILE *file, char **error_list) +{
- unsigned count = 0;
- TRACE_FLOW_ENTRY();
- if (!error_list) {
TRACE_FLOW_STRING("List is empty.", "");
return;
- }
- while (error_list[count]) {
fprintf(file, "%s\n", error_list[count]);
count++;
- }
- TRACE_FLOW_EXIT();
- return;
+}
1.5.5.6
From baa1b6eb9604729fa678a0988138a7aaa3f5c9c6 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Sun, 26 Dec 2010 21:58:24 -0500 Subject: [PATCH] [INI] Initialize variables in loops
It occured to me that one of the issues that Coverity did not like (and I could not understand what it is complaining about) is related to intializing the variables in the loop. This patch adds initialization in the loops.
ini/ini_parse_ut.c | 4 ++++ ini/ini_valueobj_ut.c | 3 +++ 2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c index 696735aacee25fc71f2b60708aaf3d0e14081f2c..5de79d954673a194bd080660f967c7b304dbdefe 100644 --- a/ini/ini_parse_ut.c +++ b/ini/ini_parse_ut.c @@ -343,6 +343,7 @@ int merge_values_test(void) INIOUT(printf("<==== Testing mode %s ====>\n", mstr[i]));
/* Create config collection */
ini_config = NULL; error = ini_config_create(&ini_config); if (error) { printf("Failed to create collection. Error %d.\n", error);
@@ -350,6 +351,7 @@ int merge_values_test(void) return error; }
file_ctx = NULL; error = ini_config_file_open(filename, INI_STOP_ON_ANY, mflags[i],
@@ -517,6 +519,7 @@ int merge_section_test(void) }
/* Create config collection */
ini_config = NULL; error = ini_config_create(&ini_config); if (error) { printf("Failed to create collection. "
@@ -525,6 +528,7 @@ int merge_section_test(void) return error; }
file_ctx = NULL; error = ini_config_file_open(filename, INI_STOP_ON_ANY, msecflags[i] | mflags[j],
diff --git a/ini/ini_valueobj_ut.c b/ini/ini_valueobj_ut.c index af62c140d215f9298dd5671d8aa544a84ef254b1..c07ec85772084f1fd6dd157a9befae26c9aa6806 100644 --- a/ini/ini_valueobj_ut.c +++ b/ini/ini_valueobj_ut.c @@ -404,6 +404,7 @@ int vo_basic_test(void) return error; }
vo = NULL; error = value_create_new(strvalue, strlen(strvalue), INI_VALUE_CREATED,
@@ -541,6 +542,7 @@ int vo_copy_test(void)
TRACE_INFO_NUMBER("Iteration:", wrap);
vo_copy = NULL; error = value_copy(vo, &vo_copy); if (error) { printf("Failed to create a new value object %d.\n", error);
@@ -559,6 +561,7 @@ int vo_copy_test(void) }
/* Get comment from the value */
ic = NULL; error = value_extract_comment(vo_copy, &ic); if (error) { printf("Failed to extract comment %d.\n", error);
-- 1.5.5.6
From f9f8998bef402648d2565ada6789305e0c0ad46e Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Mon, 3 Jan 2011 14:36:47 -0500 Subject: [PATCH] [INI] Exposing functions
This patch makes two internal functions resusable from different source modules.
ini/ini_config_priv.h | 8 ++++++++ ini/ini_fileobj.c | 2 +- ini/ini_parse.c | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/ini/ini_config_priv.h b/ini/ini_config_priv.h index 84742c70ceeb5b493b935c635e81c57d5ef487ce..e714774a68a5e16b7a221f712abe2ea9179e88c8 100644 --- a/ini/ini_config_priv.h +++ b/ini/ini_config_priv.h @@ -82,4 +82,12 @@ void ini_cleanup_cb(const char *property, /* Get parsing error */ const char *ini_get_error_str(int parsing_error, int family);
+/* Check if collision flags are valid */ +int valid_collision_flags(uint32_t collision_flags);
+/* Empty section */ +int empty_section(struct collection_item *sec);
#endif diff --git a/ini/ini_fileobj.c b/ini/ini_fileobj.c index 6de963971a0e9501fb86c23ee5faf6bfb5824bf0..30a2f1545d7b22dcab3bb4eccd53c91fe7edfd62 100644 --- a/ini/ini_fileobj.c +++ b/ini/ini_fileobj.c @@ -34,7 +34,7 @@
/* Check if collision flags are valid */ -static int valid_collision_flags(uint32_t collision_flags) +int valid_collision_flags(uint32_t collision_flags) { uint32_t flag;
diff --git a/ini/ini_parse.c b/ini/ini_parse.c index 3f45ac71ae46dff3413a6d4db5dd59a0838d078b..e3ae938847b867780cb0d0d60d12868826952a85 100644 --- a/ini/ini_parse.c +++ b/ini/ini_parse.c @@ -357,7 +357,7 @@ static int check_section_collision(struct parser_obj *po) }
/* Clean all items in the section */ -static int empty_section(struct collection_item *sec) +int empty_section(struct collection_item *sec) { int error = EOK; struct collection_item *item = NULL; -- 1.5.5.6
From 02c14799196cd1ffd0f53c6b2e995ac17a7f8917 Mon Sep 17 00:00:00 2001 From: Dmitri Pal dpal@redhat.com Date: Mon, 3 Jan 2011 14:41:03 -0500 Subject: [PATCH] [INI] Function to merge two configurations
This patch provides first draft of the implementation of the code to merge different configurations. It is similar to the merge code that is implemented inside the parser but different since it is not done during parsing of one file but addresses use case when the configuration is provided by different files that need to be merged together.
NOTE: It would make more sence to review function by function from bottom of the patch rather than from the top.
ini/ini_configobj.c | 456 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 456 insertions(+), 0 deletions(-)
diff --git a/ini/ini_configobj.c b/ini/ini_configobj.c index 5e5e40b566abdf3ce2cbc225babe4b1e20c2dd47..d8583a224e8eebc4365df3909b6bac7c98477dc5 100644 --- a/ini/ini_configobj.c +++ b/ini/ini_configobj.c @@ -30,11 +30,19 @@ #include "ini_config_priv.h" #include "ini_defines.h" #include "ini_valueobj.h" +#include "ini_configobj.h"
/* This constant belongs to ini_defines.h. Move from ini_config - TBD */ #define COL_CLASS_INI_BASE 20000 #define COL_CLASS_INI_CONFIG COL_CLASS_INI_BASE + 0
+struct merge_data {
- struct collection_item *ci;
- uint32_t flags;
- int error;
- int found;
+};
/* Callback */ void ini_cleanup_cb(const char *property, int property_len, @@ -254,3 +262,451 @@ int ini_config_copy(struct ini_cfgobj *ini_config, TRACE_FLOW_EXIT(); return error; }
+/* Callback to process merging of the sections */ +static int merge_section_handler(const char *property,
int property_len,
int type,
void *data,
int length,
void *custom_data,
int *dummy)
+{
- int error = EOK;
- struct value_obj *vo = NULL;
- struct value_obj *new_vo = NULL;
- struct value_obj *vo_old = NULL;
- struct merge_data *passed_data;
- struct collection_item *acceptor = NULL;
- struct collection_item *item = NULL;
- unsigned insertmode;
- uint32_t mergemode;
- int suppress = 0;
- int doinsert = 0;
- TRACE_FLOW_ENTRY();
- if ((type != COL_TYPE_BINARY) ||
((type == COL_TYPE_BINARY) &&
(strncmp(property, INI_SECTION_KEY,
sizeof(INI_SECTION_KEY)) == 0))) {
/* Skip items we do not care about */
TRACE_FLOW_EXIT();
return EOK;
- }
- /* Get value */
- vo = *((struct value_obj **)(data));
- /* Copy it */
- error = value_copy(vo, &new_vo);
- if (error) {
TRACE_ERROR_NUMBER("Failed to copy value", error);
return error;
- }
- passed_data = (struct merge_data *)(custom_data);
- acceptor = passed_data->ci;
- mergemode = passed_data->flags & INI_MV2S_MASK;
- switch (mergemode) {
- case INI_MV2S_ERROR: insertmode = COL_INSERT_DUPERROR;
doinsert = 1;
break;
- case INI_MV2S_PRESERVE: insertmode = COL_INSERT_DUPERROR;
doinsert = 1;
suppress = 1;
break;
- case INI_MV2S_ALLOW: insertmode = COL_INSERT_NOCHECK;
doinsert = 1;
break;
- case INI_MV2S_OVERWRITE: /* Special handling */
- case INI_MV2S_DETECT:
- default:
break;
- }
- /* Do not insert but search for dups first */
- if (!doinsert) {
TRACE_INFO_STRING("Overwrite mode. Looking for:",
property);
error = col_get_item(acceptor,
property,
COL_TYPE_BINARY,
COL_TRAVERSE_DEFAULT,
&item);
if (error) {
TRACE_ERROR_NUMBER("Failed searching for dup", error);
value_destroy(new_vo);
return error;
}
/* Check if there is a dup */
if (item) {
/* Check if we are in the detect mode */
if (mergemode == INI_MV2S_DETECT) {
passed_data->error = EEXIST;
doinsert = 1;
insertmode = COL_INSERT_NOCHECK;
}
else {
/* Dup exists - update it */
vo_old = *((struct value_obj **)(col_get_item_data(item)));
error = col_modify_binary_item(item,
NULL,
&new_vo,
sizeof(struct value_obj *));
if (error) {
TRACE_ERROR_NUMBER("Failed updating the value", error);
value_destroy(new_vo);
return error;
}
/* If we failed to update it is better to leak then crash,
* so destroy original value only on the successful update.
*/
value_destroy(vo_old);
}
}
else {
/* No dup found so we can insert with no check */
doinsert = 1;
insertmode = COL_INSERT_NOCHECK;
}
- }
- if (doinsert) {
/* Add value to collection */
error = col_insert_binary_property(acceptor,
NULL,
COL_DSP_END,
NULL,
0,
insertmode,
property,
&new_vo,
sizeof(struct value_obj *));
if (error) {
value_destroy(new_vo);
if ((suppress) && (error == EEXIST)) {
TRACE_INFO_STRING("Preseved exisitng value",
property);
}
else {
/* Check if this is a critical error or not */
if ((mergemode == INI_MV1S_ERROR) && (error == EEXIST)) {
TRACE_ERROR_NUMBER("Failed to add value object "
"to the section", error);
passed_data->error = EEXIST;
*dummy = 1;
}
else {
TRACE_ERROR_NUMBER("Failed to add value object"
" to the section", error);
return error;
}
}
}
- }
- TRACE_FLOW_EXIT();
- return error;
+}
+/* Internal function to merge two configs */ +static int merge_two_sections(struct collection_item *acceptor,
struct collection_item *donor,
uint32_t flags)
+{
- int error = EOK;
- struct merge_data data;
- TRACE_FLOW_ENTRY();
- data.ci = acceptor;
- data.flags = flags;
- data.error = 0;
- data.found = 0;
- error = col_traverse_collection(donor,
COL_TRAVERSE_ONELEVEL,
merge_section_handler,
(void *)(&data));
- if (error) {
TRACE_ERROR_NUMBER("Merge values failed", error);
return error;
- }
- TRACE_FLOW_EXIT();
- return data.error;
+}
+/* Callback to process the accepting config */ +static int acceptor_handler(const char *property,
int property_len,
int type,
void *data,
int length,
void *custom_data,
int *dummy)
+{
- int error = EOK;
- struct merge_data *passed_data;
- struct collection_item *acceptor = NULL;
- struct collection_item *donor = NULL;
- uint32_t mergemode;
- TRACE_FLOW_ENTRY();
- passed_data = (struct merge_data *)(custom_data);
- passed_data->found = 1;
- donor = passed_data->ci;
- acceptor = *((struct collection_item **)(data));
- mergemode = passed_data->flags & INI_MS_MASK;
- switch (mergemode) {
- case INI_MS_ERROR: /* Report error and return */
TRACE_INFO_STRING("Error ",
"duplicate section");
passed_data->error = EEXIST;
break;
- case INI_MS_PRESERVE: /* Preserve what we have */
TRACE_INFO_STRING("Preserve mode", "");
break;
- case INI_MS_OVERWRITE: /* Empty existing section */
TRACE_INFO_STRING("Ovewrite mode", "");
error = empty_section(acceptor);
if (error) {
TRACE_ERROR_NUMBER("Failed to "
"empty section",
error);
return error;
}
error = merge_two_sections(acceptor,
donor,
passed_data->flags);
if (error) {
TRACE_ERROR_NUMBER("Failed to merge "
"sections", error);
return error;
}
break;
- case INI_MS_DETECT: /* Detect mode */
TRACE_INFO_STRING("Detect mode", "");
passed_data->error = EEXIST;
passed_data->found = 0;
break;
- case INI_MS_MERGE: /* Merge */
- default: TRACE_INFO_STRING("Merge mode", "");
error = merge_two_sections(acceptor,
donor,
passed_data->flags);
if (error) {
if (error != EEXIST) {
TRACE_ERROR_NUMBER("Failed to merge "
"sections", error);
return error;
}
passed_data->error = error;
}
break;
- }
- *dummy = 1;
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Callback to process the donating config */ +static int donor_handler(const char *property,
int property_len,
int type,
void *data,
int length,
void *custom_data,
int *dummy)
+{
- int error = EOK;
- struct merge_data *passed_data;
- struct merge_data acceptor_data;
- struct collection_item *new_ci = NULL;
- TRACE_FLOW_ENTRY();
- passed_data = (struct merge_data *)(custom_data);
- /* All section are subcollections */
- if(type == COL_TYPE_COLLECTIONREF) {
acceptor_data.flags = passed_data->flags;
acceptor_data.ci = *((struct collection_item **)(data));
acceptor_data.error = 0;
acceptor_data.found = 0;
/* Try to resolve collision only non ALLOW modes */
if (!(acceptor_data.flags & INI_MS_ALLOW)) {
error = col_get_item_and_do(passed_data->ci,
property,
COL_TYPE_COLLECTIONREF,
COL_TRAVERSE_ONELEVEL,
acceptor_handler,
(void *)(&acceptor_data));
if (error) {
TRACE_ERROR_NUMBER("Critical error", error);
return error;
}
}
/* Was duplicate found ? */
if (acceptor_data.found) {
/* Check for logical error. It can be only EEXIST */
if (acceptor_data.error) {
/* Save error anyway */
passed_data->error = acceptor_data.error;
/* If it is section DETECT or MERGE+DETECT */
if ((passed_data->flags & INI_MS_DETECT) ||
((passed_data->flags & INI_MS_MERGE) &&
(passed_data->flags & INI_MV2S_DETECT))) {
TRACE_INFO_NUMBER("Non-critical error",
acceptor_data.error);
}
else {
/* In any other mode we need to stop */
TRACE_INFO_NUMBER("Merge error detected",
acceptor_data.error);
/* Force stop */
*dummy = 1;
}
}
}
else {
/* Not found? Then create a copy... */
error = col_copy_collection_with_cb(&new_ci,
acceptor_data.ci,
NULL,
COL_COPY_NORMAL,
ini_copy_cb,
NULL);
if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
return error;
}
/* ... and embed into the existing collection */
error = col_add_collection_to_collection(passed_data->ci,
NULL,
NULL,
new_ci,
COL_ADD_MODE_EMBED);
if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
col_destroy_collection(new_ci);
return error;
}
}
- }
- TRACE_FLOW_EXIT();
- return EOK;
+}
+/* Internal function to merge two configs */ +static int merge_configs(struct ini_cfgobj *first,
struct ini_cfgobj *second,
uint32_t collision_flags)
+{
- int error = EOK;
- struct merge_data data;
- TRACE_FLOW_ENTRY();
- data.ci = first->cfg;
- data.flags = collision_flags;
- data.error = 0;
- data.found = 0;
- error = col_traverse_collection(second->cfg,
COL_TRAVERSE_ONELEVEL,
donor_handler,
(void *)(&data));
- if (error) {
TRACE_ERROR_NUMBER("Merge failed", error);
return error;
- }
- /* If boundaries are different re-align the values */
- if (first->boundary != second->boundary) {
error = ini_config_set_wrap(first, first->boundary);
if (error) {
TRACE_ERROR_NUMBER("Failed to re-align", error);
return error;
}
- }
- TRACE_FLOW_EXIT();
- return error;
+}
+/* Merge two configurations together creating a new one */ +int ini_config_merge(struct ini_cfgobj *first,
struct ini_cfgobj *second,
uint32_t collision_flags,
struct ini_cfgobj **result)
+{
- int error = EOK;
- struct ini_cfgobj *new_co = NULL;
- TRACE_FLOW_ENTRY();
- /* Check input params */
- if ((!first) ||
(!second) ||
(!result)) {
TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
return EINVAL;
- }
- /* Check collision flags */
- if (!valid_collision_flags(collision_flags)) {
TRACE_ERROR_NUMBER("Invalid flags.", EINVAL);
return EINVAL;
- }
- /* Create a copy */
- /* TBD - create a COMPACT copy */
- error = ini_config_copy(first, &new_co);
- if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
return error;
- }
- /* Merge configs */
- error = merge_configs(new_co, second, collision_flags);
- if (error) {
TRACE_ERROR_NUMBER("Failed to copy collection", error);
ini_config_destroy(new_co);
return error;
- }
- *result = new_co;
- TRACE_FLOW_EXIT();
- return error;
+}
1.5.5.6
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
#0016: Ack
#0017: I'm not sure what's the point in checking errno when malloc fails. IIRC the errno will be always ENOMEM. The same applies to the strndup several lines below.
The initialization block (new_ctx->.... = NULL) is redundant, you set everything necessary later and in case of any error, uninitalized values won't make it out of the function anyway.
#0018: Ack
#0019: The return error at the end is misleading, please use return EOK instead (similar issue is in other patches as well, please change it when you see it).
#0020: Please change the comment to: Determines if two file contexts are different by comparing:
I don't like the prototype of ini_config_changed(). Is it necessary to return special error code? I would perform the check and in case of wrong input, I'd fall back to the safe option - return true (as in the config file has changed). In this case no special check is necessary and the code will be more readable.
#0021: Ack
#0022: I'm confused. In the patch comment you write that we can't remove it from the old interface but yet you remove it from the header file. I'd say it should remain there (and be marked) as well.
#0023: Ack
#0024: Ack
On 01/24/2011 12:27 PM, Sumit Bose wrote:
The numeration changed. But the ste is the same. The patches in this mail are dependent on the patches sent in the previous email on Friday.
Patches related porting of the meta data from old way of doing things to the new way of doing things: 0017--INI-Separate-close-and-destroy.patch
You should set file_ctx->file to NULL after fclose(file_ctx->file) to make the if(file_ctx->file) checks work in ini_config_file_close() and ini_config_file_destroy().
Yes it was fixed in a different patch. Now merged together.
There are tab indents in merge_values_test() and merge_section_test().
Fixed.
0018--INI-Function-to-reopen-file.patch
Unchanged
0019--INI-Metadata-collection-is-gone.patch
You remove metadata from struct ini_cfgfile without removing all references to metadata in the same patch. You should make clear that more patches are needed to create a buildable version of libini or remove all references in this patch.
This is not true. The buildable version is still preserved. All the code that I am building is not executed yet. It is a parallel interface. There are currently two interfaces: ini_config.h and ini_configobj.h The external code is still suing the ini_config.h. The new interface that the UT are executing is pointing to the interface growing in ini_configobj.h. This metadata functions of the existing ini_config interface are not affected. After some thinking I realized that there is too much overhead for doing the metadata handling the way I did it in the first implementation. The new interface corrects this but does not affect the old code yet. So the metadata collection is gone from the new interface not from the old one. The code compiles fine after this patch and the three patches right after it take advantage of this change. Patches 18-21 should be considered together as a block of related patches.
I wonder is the following is a change of defaults. With the patch the new file_ctx->file_stats are only set if INI_META_STATS is set while previously file-ctx>metadata was set unconditionally.
Fixed by memset.
0020--INI-Check-access-function.patch
This is now 19.
I wonder if it is necessary to return EINVAL if flags == 0. I would say in this case no checks are requested and EOK could be returned?
I disagree with this one. With flags 0 I think it is a noop and might lead to the wrong assumptions while no operation was actually performed. IMO passing flags=0 is a codding error in this case and thus should be reported as such.
I would prefer to copy file_ctx->file_stats.st_mode instead of modifying it, e.g. you might want to know the file type later on.
Good catch. Agree. Fixed.
0021--INI-Avoid-double-free.patch <- patch related to 17 (missed check)
oops, so you can ignore my comment to 00017, let's see if there is also a patch for ini_config_file_destroy(). "I might squash this patch into one of the previous ones." Yes, please.
This one is merged now.
0022--INI-Function-to-check-for-changes.patch
This is now 20 and unchanged.
0023--INI-Tests-for-access-and-changes.patch
This is now 21.
Why do you need sleep(1) ?
Removed.
The man page of system() does not mention that system() sets errno, please check the return code instead.
Changed to use execlp().
0024--INI-Rename-error-print-function.patch <- rename error printing function for consistency with new interface
This is now 22.
Maybe ini_print_errors() should print a deprecated warning to make migrations easier.
As I mentioned above there is no impact on the existing interface. As you notice I made a clone of the existing function with a different name and made a comment to clean the old function when the interface is deprecated. The changes will be made later when we switch to new interface, so it is premature to print a warning as this function is still used.
0025--INI-Initialize-variables-in-loops.patch <- Coverity issue addressed. Related to patch 0001.
This is 23 and merged with another initialization one liner patch.
0026--INI-Exposing-functions.patch <- Make some internal functions reusable
This is 24 and unchanged.
There is also patch 27. It is a piece of new functionality. It is a preview. Please see the comment before reviewing it. Do I need to split it into multiple patches or it is Ok as is? It is pretty big but all changes are in one file and logically related. The UNIT test is missing so I am not claiming it actually works as expected.
I didn't had a look at 0027 so far.
I am going to hold to patch 27 yet. I have other higher priority issues to address.
Please review and nack/push this ASAP. I need to clean ding libs and elapi for the audit effort ASAP. There are too many patches piling to be able to move forward effectively. I am the bottleneck now and i need to bring all this into a usable state within a week or so. Please help!
One last thing. Should I switch to the format used in freeipa? https://fedorahosted.org/freeipa/wiki/PatchFormat It seems that SSSD/ding-libs does not follow this format. Should it? Not insisting, just asking.
I'm already using it. I don't mind one way or the other.
Thanks Jan
On 03/26/2012 04:49 AM, Jan Zelený wrote:
#0016: Ack
#0017: I'm not sure what's the point in checking errno when malloc fails. IIRC the errno will be always ENOMEM. The same applies to the strndup several lines below.
The initialization block (new_ctx->.... = NULL) is redundant, you set everything necessary later and in case of any error, uninitalized values won't make it out of the function anyway.
#0018: Ack
#0019: The return error at the end is misleading, please use return EOK instead (similar issue is in other patches as well, please change it when you see it).
#0020: Please change the comment to: Determines if two file contexts are different by comparing:
I don't like the prototype of ini_config_changed(). Is it necessary to return special error code? I would perform the check and in case of wrong input, I'd fall back to the safe option - return true (as in the config file has changed). In this case no special check is necessary and the code will be more readable.
#0021: Ack
#0022: I'm confused. In the patch comment you write that we can't remove it from the old interface but yet you remove it from the header file. I'd say it should remain there (and be marked) as well.
#0023: Ack
#0024: Ack
I am re-sending the whole set.
In #0015 I removed the trailing spaces Stephen noted in the other mail. The rest 14 are the same.
#0017 - remove the initialization of the filename. Removing other initialization is unsafe. Agreed on IRC. Opened a ticket to do trust malloc to return ENOMEM. https://fedorahosted.org/sssd/ticket/1276 I was told that malloc() by standard must return ENOMEM. Doe this standard apply to all distros or just Linux?
#0019 Removed error variable and return EOK directly.
#0020 Changed comment. Removed error variable and return EOK directly. We agree on IRC that it is OK to keep function signature as is.
#0022 Unchanged. Explanation: Some time ago I started building a parallel interface in ini_configobj.h to the existing public interface that is in ini_config.h So we do not change the public existing one until the new one is ready and stabilized. As one of the steps to prepare the new interface I renamed the function in the new interface to be consistent with the naming convention. I might provide some compatibility layer when I am ready to switch from the old interface to the new interface but this is out of scope of the current patch set.
The rest are same.
On 03/26/2012 04:49 AM, Jan Zelený wrote:
#0016: Ack
#0017: I'm not sure what's the point in checking errno when malloc fails. IIRC the errno will be always ENOMEM. The same applies to the strndup several lines below.
The initialization block (new_ctx->.... = NULL) is redundant, you set everything necessary later and in case of any error, uninitalized values won't make it out of the function anyway.
#0018: Ack
#0019: The return error at the end is misleading, please use return EOK instead (similar issue is in other patches as well, please change it when you see it).
#0020: Please change the comment to: Determines if two file contexts are different by comparing:
I don't like the prototype of ini_config_changed(). Is it necessary to return special error code? I would perform the check and in case of wrong input, I'd fall back to the safe option - return true (as in the config file has changed). In this case no special check is necessary and the code will be more readable.
#0021: Ack
#0022: I'm confused. In the patch comment you write that we can't remove it from the old interface but yet you remove it from the header file. I'd say it should remain there (and be marked) as well.
#0023: Ack
#0024: Ack
I am re-sending the whole set.
In #0015 I removed the trailing spaces Stephen noted in the other mail. The rest 14 are the same.
#0017 - remove the initialization of the filename. Removing other initialization is unsafe. Agreed on IRC. Opened a ticket to do trust malloc to return ENOMEM. https://fedorahosted.org/sssd/ticket/1276 I was told that malloc() by standard must return ENOMEM. Doe this standard apply to all distros or just Linux?
Quoting malloc man page: The UNIX 98 standard requires malloc(), calloc(), and realloc() to set errno to ENOMEM upon failure.
Ack
#0019 Removed error variable and return EOK directly.
Ack
#0020 Changed comment. Removed error variable and return EOK directly. We agree on IRC that it is OK to keep function signature as is.
Ack
#0022 Unchanged. Explanation: Some time ago I started building a parallel interface in ini_configobj.h to the existing public interface that is in ini_config.h So we do not change the public existing one until the new one is ready and stabilized. As one of the steps to prepare the new interface I renamed the function in the new interface to be consistent with the naming convention. I might provide some compatibility layer when I am ready to switch from the old interface to the new interface but this is out of scope of the current patch set.
I think that my comment still stands. I understand your explanation but I still don't understand what's the point in keeping the function when you don't have its declaration in header file. ABI compatibility? This is the last question I have regarding the patch set, other than that it's ok.
Thanks Jan
On 03/26/2012 10:55 AM, Dmitri Pal wrote:
On 03/26/2012 04:49 AM, Jan Zelený wrote:
#0016: Ack
#0017: I'm not sure what's the point in checking errno when malloc fails. IIRC the errno will be always ENOMEM. The same applies to the strndup several lines below.
The initialization block (new_ctx->.... = NULL) is redundant, you set everything necessary later and in case of any error, uninitalized values won't make it out of the function anyway.
#0018: Ack
#0019: The return error at the end is misleading, please use return EOK instead (similar issue is in other patches as well, please change it when you see it).
#0020: Please change the comment to: Determines if two file contexts are different by comparing:
I don't like the prototype of ini_config_changed(). Is it necessary to return special error code? I would perform the check and in case of wrong input, I'd fall back to the safe option - return true (as in the config file has changed). In this case no special check is necessary and the code will be more readable.
#0021: Ack
#0022: I'm confused. In the patch comment you write that we can't remove it from the old interface but yet you remove it from the header file. I'd say it should remain there (and be marked) as well.
#0023: Ack
#0024: Ack
I am re-sending the whole set.
In #0015 I removed the trailing spaces Stephen noted in the other mail. The rest 14 are the same.
#0017 - remove the initialization of the filename. Removing other initialization is unsafe. Agreed on IRC. Opened a ticket to do trust malloc to return ENOMEM. https://fedorahosted.org/sssd/ticket/1276 I was told that malloc() by standard must return ENOMEM. Doe this standard apply to all distros or just Linux?
#0019 Removed error variable and return EOK directly.
#0020 Changed comment. Removed error variable and return EOK directly. We agree on IRC that it is OK to keep function signature as is.
#0022 Unchanged. Explanation: Some time ago I started building a parallel interface in ini_configobj.h to the existing public interface that is in ini_config.h So we do not change the public existing one until the new one is ready and stabilized. As one of the steps to prepare the new interface I renamed the function in the new interface to be consistent with the naming convention. I might provide some compatibility layer when I am ready to switch from the old interface to the new interface but this is out of scope of the current patch set.
Updated patch is attached.
The rest are same.
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
Ok the whole set once more:
1) Fixed the trailing spaces on patch 15 - they showed as warning when I applied the patch in a different repo 2) The problem with permissions that Jan have seen was caused by the fact that when the repo is created as root the permissions on the files that are used in tests are different. For now I added a different check. In future there might be a need for some improvement in this area. I created a task https://fedorahosted.org/sssd/ticket/1284 to track this effort. 3) Added two missing cleanup calls to patch 27 as Jan rightly indicated that they were missing
All the rest is the same.
Ok the whole set once more:
- Fixed the trailing spaces on patch 15 - they showed as warning when I
applied the patch in a different repo 2) The problem with permissions that Jan have seen was caused by the fact that when the repo is created as root the permissions on the files that are used in tests are different. For now I added a different check. In future there might be a need for some improvement in this area. I created a task https://fedorahosted.org/sssd/ticket/1284 to track this effort. 3) Added two missing cleanup calls to patch 27 as Jan rightly indicated that they were missing
All the rest is the same.
I'm not completely comfortable with your solution of the access check. You are just assuming in the comment that the file was created by root and has therefore different permissions. But what if it wasn't created by root and still has these different permissions? I think the test could then let an error in the code pass through. Please check that the file indeed belongs to root just to be sure. Also error2 is not necessary IMO, you can re-user error.
This is the last minor change I'm asking for. If you want, I'll do it for you. Other than that all patches are fine.
Jan
On Tue, 2012-04-03 at 10:08 +0200, Jan Zelený wrote:
Ok the whole set once more:
- Fixed the trailing spaces on patch 15 - they showed as warning when I
applied the patch in a different repo 2) The problem with permissions that Jan have seen was caused by the fact that when the repo is created as root the permissions on the files that are used in tests are different. For now I added a different check. In future there might be a need for some improvement in this area. I created a task https://fedorahosted.org/sssd/ticket/1284 to track this effort. 3) Added two missing cleanup calls to patch 27 as Jan rightly indicated that they were missing
All the rest is the same.
I'm not completely comfortable with your solution of the access check. You are just assuming in the comment that the file was created by root and has therefore different permissions. But what if it wasn't created by root and still has these different permissions? I think the test could then let an error in the code pass through. Please check that the file indeed belongs to root just to be sure. Also error2 is not necessary IMO, you can re-user error.
This is the last minor change I'm asking for. If you want, I'll do it for you. Other than that all patches are fine.
Actually, I think it's more likely that what's happening here is that root and a casual user have a different default umask on most systems. So this probably IS a bug in the code. You should be setting the umask before creating the file (and resetting the umask to its old value afterwards) in order to guarantee that it is always written with the proper permissions.
On 04/03/2012 08:01 AM, Stephen Gallagher wrote:
On Tue, 2012-04-03 at 10:08 +0200, Jan Zelený wrote:
Ok the whole set once more:
- Fixed the trailing spaces on patch 15 - they showed as warning when I
applied the patch in a different repo 2) The problem with permissions that Jan have seen was caused by the fact that when the repo is created as root the permissions on the files that are used in tests are different. For now I added a different check. In future there might be a need for some improvement in this area. I created a task https://fedorahosted.org/sssd/ticket/1284 to track this effort. 3) Added two missing cleanup calls to patch 27 as Jan rightly indicated that they were missing
All the rest is the same.
I'm not completely comfortable with your solution of the access check. You are just assuming in the comment that the file was created by root and has therefore different permissions. But what if it wasn't created by root and still has these different permissions? I think the test could then let an error in the code pass through. Please check that the file indeed belongs to root just to be sure. Also error2 is not necessary IMO, you can re-user error.
This is the last minor change I'm asking for. If you want, I'll do it for you. Other than that all patches are fine.
Actually, I think it's more likely that what's happening here is that root and a casual user have a different default umask on most systems. So this probably IS a bug in the code. You should be setting the umask before creating the file (and resetting the umask to its old value afterwards) in order to guarantee that it is always written with the proper permissions.
The file is a part of the repo. It is checked into the source control. I do not have control on its permissions. I think it is the umask but not during execution but rather during git clone.
Yes this area needs more thought but IMO in a separate patch. And may be done differently. For example create a file on the fly and make sure it has specific permissions. But this is way out of the scope of the current patch. This is why I opened a separate ticket to handle it.
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
On 04/03/2012 08:01 AM, Stephen Gallagher wrote:
On Tue, 2012-04-03 at 10:08 +0200, Jan Zelený wrote:
Ok the whole set once more:
- Fixed the trailing spaces on patch 15 - they showed as warning when
I applied the patch in a different repo 2) The problem with permissions that Jan have seen was caused by the fact that when the repo is created as root the permissions on the files that are used in tests are different. For now I added a different check. In future there might be a need for some improvement in this area. I created a task https://fedorahosted.org/sssd/ticket/1284 to track this effort. 3) Added two missing cleanup calls to patch 27 as Jan rightly indicated that they were missing
All the rest is the same.
I'm not completely comfortable with your solution of the access check. You are just assuming in the comment that the file was created by root and has therefore different permissions. But what if it wasn't created by root and still has these different permissions? I think the test could then let an error in the code pass through. Please check that the file indeed belongs to root just to be sure. Also error2 is not necessary IMO, you can re-user error.
This is the last minor change I'm asking for. If you want, I'll do it for you. Other than that all patches are fine.
Actually, I think it's more likely that what's happening here is that root and a casual user have a different default umask on most systems. So this probably IS a bug in the code. You should be setting the umask before creating the file (and resetting the umask to its old value afterwards) in order to guarantee that it is always written with the proper permissions.
The file is a part of the repo. It is checked into the source control. I do not have control on its permissions. I think it is the umask but not during execution but rather during git clone.
Yes this area needs more thought but IMO in a separate patch. And may be done differently. For example create a file on the fly and make sure it has specific permissions. But this is way out of the scope of the current patch. This is why I opened a separate ticket to handle it.
Ok, thanks for clarification. Since the issue is in the test suite and it has been worked around, I give these patches a green light.
Ack to all
Thanks Jan
On Thu, 2012-04-05 at 15:54 +0200, Jan Zelený wrote:
Ok, thanks for clarification. Since the issue is in the test suite and it has been worked around, I give these patches a green light.
Ack to all
All 28 patches pushed to ding-libs master.
If any of them should also be pushed to the stable branch, please provide guidance.
On 04/05/2012 02:21 PM, Stephen Gallagher wrote:
On Thu, 2012-04-05 at 15:54 +0200, Jan Zelený wrote:
Ok, thanks for clarification. Since the issue is in the test suite and it has been worked around, I give these patches a green light.
Ack to all
All 28 patches pushed to ding-libs master.
If any of them should also be pushed to the stable branch, please provide guidance.
No not to stable yet. But soon.
sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/sssd-devel
sssd-devel@lists.fedorahosted.org