Compare commits
453 Commits
private-mf
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
61f15e90bc | ||
|
6129ad64d4 | ||
|
1fa217076e | ||
|
5846004b81 | ||
|
7e6e06c36d | ||
|
72195d4485 | ||
|
77335ae30e | ||
|
76ac51ab78 | ||
|
293db26d85 | ||
|
525a40ce11 | ||
|
1ff5b17afe | ||
|
a4d24cbe45 | ||
|
b3c6eb0e4c | ||
|
6144405435 | ||
|
c96359dd1c | ||
|
8797f87802 | ||
|
5f0fe918a5 | ||
|
c098079671 | ||
|
4a003b4922 | ||
|
ca11f82b69 | ||
|
b21f47f287 | ||
|
d53844dd72 | ||
|
134a36d7f8 | ||
|
a464847a25 | ||
|
9c5a4265d8 | ||
|
bd8d2430b4 | ||
|
819bb4065c | ||
|
3aed6a961c | ||
|
34927af202 | ||
|
fcb4083893 | ||
|
50bcae98df | ||
|
74725dd94e | ||
|
9701fdade7 | ||
|
6666c40188 | ||
|
4124e42f39 | ||
|
d9394d9d7e | ||
|
47192f413e | ||
|
448365c7f7 | ||
|
a54853472d | ||
|
dcaaa78467 | ||
|
7b77f1b10f | ||
|
b797613532 | ||
|
e4dacdad3d | ||
|
539fe8abbd | ||
|
7b2061df55 | ||
|
bfa3999fdd | ||
|
82a97343d6 | ||
|
a84cd6b530 | ||
|
fdf2115d36 | ||
|
4d79a1a6dd | ||
|
70ec0cd8b9 | ||
|
97506ad65a | ||
|
5b4007bb56 | ||
|
9f81c9aa6e | ||
|
2300402532 | ||
|
8a209c638d | ||
|
047399b0d0 | ||
|
1c5b89063f | ||
|
b82e3b3f85 | ||
|
8e6306e004 | ||
|
5fff012634 | ||
|
123aebc7d4 | ||
|
109c797f85 | ||
|
0ba614c06d | ||
|
de5b416635 | ||
|
b4e36d719d | ||
|
e7b9f886b0 | ||
|
5d5d75dce2 | ||
|
88850a88bb | ||
|
657df54449 | ||
|
1ebcbd5e46 | ||
|
70a46f30e1 | ||
|
7c5e863b5b | ||
|
133c946b2f | ||
|
ec674e19b8 | ||
|
4265b0b8f6 | ||
|
062fb704db | ||
|
1aba59b258 | ||
|
650d554f72 | ||
|
60935671c3 | ||
|
7a4d7ca184 | ||
|
1d88b65b1d | ||
|
b8873c0d8b | ||
|
afea822158 | ||
|
173c24248d | ||
|
5ce3b68016 | ||
|
fdcac6f8f4 | ||
|
2f22666a8b | ||
|
16caa0b760 | ||
|
81ee17d92e | ||
|
36c64b8ffa | ||
|
5ca0400677 | ||
|
4232176d25 | ||
|
c42d98baca | ||
|
383945e966 | ||
|
a5ad6ecfc9 | ||
|
6287bab02b | ||
|
8e5fc280df | ||
|
3b14ffff2a | ||
|
447d75c71c | ||
|
a63c0b6456 | ||
|
c63972c3a9 | ||
|
9588eec39f | ||
|
723de53164 | ||
|
fde5e92317 | ||
|
02e1d4ee3e | ||
|
60efd153e5 | ||
|
bebdebbdc3 | ||
|
08e1b1ab33 | ||
|
fa1678e1c0 | ||
|
b0deb573ed | ||
|
fb1f848c19 | ||
|
304fcdff50 | ||
|
56a02fe6e3 | ||
|
a4a5659439 | ||
|
ad93166294 | ||
|
092cf93daa | ||
|
6f4d10f912 | ||
|
e4aafbc505 | ||
|
559f435759 | ||
|
3bef91d75e | ||
|
e75713e5c1 | ||
|
6404b25896 | ||
|
6a43999c13 | ||
|
28cb5d31fc | ||
|
126ab296ea | ||
|
589518d1c8 | ||
|
04e38e02b7 | ||
|
8a71833984 | ||
|
43a21403fe | ||
|
a50cd9a587 | ||
|
2074a352da | ||
|
4adfefae5a | ||
|
145da19e2e | ||
|
58f5912619 | ||
|
c8098b86f8 | ||
|
a6144b701a | ||
|
4343a2408a | ||
|
2b743b9fd1 | ||
|
9007def666 | ||
|
4283de10b6 | ||
|
84981f566e | ||
|
e4a1cf14e0 | ||
|
94a7268e0b | ||
|
9f8b04ee49 | ||
|
a747c093bb | ||
|
f21f7f7c7f | ||
|
13e87ddfb5 | ||
|
bfa9f404d2 | ||
|
7e87eb005e | ||
|
57b8f5c277 | ||
|
c9ce3549e4 | ||
|
0e59699b4c | ||
|
8ed5487f77 | ||
|
189f35b396 | ||
|
890019ecf2 | ||
|
2fcfa6890c | ||
|
d591927700 | ||
|
71cb283b66 | ||
|
c491e21bc7 | ||
|
7c1047805b | ||
|
098d568ec0 | ||
|
5603627552 | ||
|
0e17ea22c1 | ||
|
7e28f1b6ad | ||
|
ec52db3a46 | ||
|
52fc655c6c | ||
|
e0b0cbbd50 | ||
|
cee352f95d | ||
|
a928b2e6c1 | ||
|
9be86f04b3 | ||
|
90b56a7d0c | ||
|
af386eee0d | ||
|
1bbd25fcbf | ||
|
890cc4ed1d | ||
|
0e84fd763d | ||
|
d92633e7a9 | ||
|
081ef32d63 | ||
|
ee109af432 | ||
|
16398fcbfd | ||
|
4c06a879a9 | ||
|
29d10047e2 | ||
|
5a04553bf2 | ||
|
7f4ea1188a | ||
|
1dbdd9fef3 | ||
|
c57221cc4f | ||
|
28e47feb91 | ||
|
c09c66271e | ||
|
55adfecd0c | ||
|
eff52e3518 | ||
|
cefed5d027 | ||
|
587bed9b2f | ||
|
72c4f88cc6 | ||
|
f80578dc89 | ||
|
6ff958f2aa | ||
|
48a71633e6 | ||
|
1f24fb0da2 | ||
|
6777c3ed80 | ||
|
a4166cd2cf | ||
|
58e6c2560b | ||
|
92867018b5 | ||
|
cd5e5a1117 | ||
|
6815071d4a | ||
|
b8b7388beb | ||
|
c758358a31 | ||
|
2687b3c78b | ||
|
6a5972a529 | ||
|
36e8658036 | ||
|
fac98a7443 | ||
|
a071c6801c | ||
|
cc5db6cdfd | ||
|
737f7e8513 | ||
|
34f077631c | ||
|
707a1e8f87 | ||
|
e33b0e3197 | ||
|
365663e72b | ||
|
91ed2dbf62 | ||
|
0f4d3ed14d | ||
|
5c2fe5cfb3 | ||
|
5163dbee45 | ||
|
dc905411d5 | ||
|
90612b2709 | ||
|
d7ce5d4634 | ||
|
d84b03df97 | ||
|
684ac6eb78 | ||
|
538e3ea7c8 | ||
|
b8bc11a834 | ||
|
6e8a4e351b | ||
|
8544d3ab89 | ||
|
9e28c4292e | ||
|
e15a68193c | ||
|
cad9c65e11 | ||
|
a281128660 | ||
|
1042b5d52a | ||
|
cf072ec21a | ||
|
bf6952b9c9 | ||
|
23177e46b4 | ||
|
d62730de90 | ||
|
95cc2e8d4c | ||
|
d8e1573f9c | ||
|
39b4cfbcf1 | ||
|
a5a7506242 | ||
|
08930d16b5 | ||
|
29bd4db4f5 | ||
|
ac67247def | ||
|
94e38e4e87 | ||
|
9d8de720dd | ||
|
3c78a51385 | ||
|
d19bd27c2f | ||
|
bb83f920be | ||
|
00b734f530 | ||
|
db77ecebac | ||
|
776ca08599 | ||
|
71d4a02e14 | ||
|
10c1baf354 | ||
|
df547679fd | ||
|
35726c325a | ||
|
0980ba190b | ||
|
e74f2b3bdb | ||
|
5188e8569e | ||
|
e098446236 | ||
|
277dd05ebd | ||
|
7bdfe15464 | ||
|
adefe4d265 | ||
|
3bd5cf3d29 | ||
|
d4b46d7258 | ||
|
7fbb58cf62 | ||
|
6c2a58dc61 | ||
|
b1ee1018fc | ||
|
d3da0e913a | ||
|
988ba6d3d1 | ||
|
746617ce7d | ||
|
b586203c24 | ||
|
2235ae530d | ||
|
67108a5592 | ||
|
edbe539deb | ||
|
f7f03039dd | ||
|
d61c107a04 | ||
|
253d1d9c66 | ||
|
8ca6f66f20 | ||
|
0e45e4de58 | ||
|
e79ddddf67 | ||
|
21cf167acc | ||
|
284746122d | ||
|
b45bb05263 | ||
|
05146e37a4 | ||
|
76dd91f117 | ||
|
7df3e02388 | ||
|
d0c57f678a | ||
|
a6b9bec157 | ||
|
beff5c2326 | ||
|
238627a99e | ||
|
6a6f54375a | ||
|
a60d22cda6 | ||
|
0ab5fbb2e4 | ||
|
2f246edc9d | ||
|
5bc208c4f5 | ||
|
a4f378196e | ||
|
eb3d3880c8 | ||
|
c6d0720817 | ||
|
976a6ca3e4 | ||
|
8c898cdc11 | ||
|
051a34bb83 | ||
|
08d81d7330 | ||
|
c6e992763d | ||
|
66a1c9c9cb | ||
|
27727bd4a9 | ||
|
5ca19238f5 | ||
|
6cb5e06b89 | ||
|
2620469c94 | ||
|
fce95492bd | ||
|
9df65054b7 | ||
|
d8b4ab633b | ||
|
6e6bd41f5e | ||
|
ad9d2e17df | ||
|
fdd439f8b7 | ||
|
8742b0f949 | ||
|
4786e3be95 | ||
|
8b0d66e92b | ||
|
7e4694d522 | ||
|
d04b9b7840 | ||
|
887799236c | ||
|
f271045ada | ||
|
37c3363a24 | ||
|
e0954fe0fe | ||
|
c5379cd829 | ||
|
6702ca3c64 | ||
|
705ca30d3e | ||
|
44f4cf77e9 | ||
|
32049f182f | ||
|
4e3d1d3a47 | ||
|
419878ed02 | ||
|
4caf18bfe4 | ||
|
d40c9fdc13 | ||
|
d538c7cc53 | ||
|
4597e723d0 | ||
|
667333c331 | ||
|
84baf402f0 | ||
|
44e7da869e | ||
|
8ed8731099 | ||
|
dcf3eeb5c0 | ||
|
093184feca | ||
|
9a4cee58e4 | ||
|
2660abb9bb | ||
|
9d8ea8c478 | ||
|
aae7c7249a | ||
|
10e4623a27 | ||
|
6e985d0a59 | ||
|
8a569a02e8 | ||
|
6a3a1d1575 | ||
|
fda3e070a7 | ||
|
87bc7c9489 | ||
|
f35d7503ab | ||
|
7f4621301d | ||
|
c769a3ef7a | ||
|
4014d6f877 | ||
|
c2f6995570 | ||
|
056f48952a | ||
|
2999128764 | ||
|
04b4101e8f | ||
|
305fa9fb57 | ||
|
5bc3170c40 | ||
|
aa4db12ee0 | ||
|
ad7685d113 | ||
|
7061f72715 | ||
|
7463f6a220 | ||
|
574cbae985 | ||
|
edb6156880 | ||
|
41c1b49335 | ||
|
c659285752 | ||
|
e9dcd51d77 | ||
|
4570c40835 | ||
|
a681b7b4e2 | ||
|
ace066ccd1 | ||
|
5617e2c469 | ||
|
8076ad58d9 | ||
|
b766add297 | ||
|
fbd985bf72 | ||
|
eaa5674199 | ||
|
93ddbf99ee | ||
|
434cf9e2e2 | ||
|
b587bccfe7 | ||
|
c9a1e5c935 | ||
|
835049c53c | ||
|
573bcacc8f | ||
|
55bd1b5cdd | ||
|
762e747b11 | ||
|
9d7b7a7a04 | ||
|
83e5c415da | ||
|
4f53fe474e | ||
|
0b05408588 | ||
|
0adb9076a4 | ||
|
66afdc6140 | ||
|
36702a1359 | ||
|
77d2ac8e00 | ||
|
c097c5b5f7 | ||
|
82db94894e | ||
|
90f786e56b | ||
|
548cf89fd5 | ||
|
f6288a0045 | ||
|
5344dc60e9 | ||
|
4c8a26717a | ||
|
b8b6a436e9 | ||
|
2c005c98da | ||
|
7ad97baa4f | ||
|
87b6ed77db | ||
|
9d1bb0abc3 | ||
|
d1929c8ddb | ||
|
d5e9ea2361 | ||
|
1ca5ccee9c | ||
|
8d10e61144 | ||
|
5c031d86de | ||
|
0f28e7559e | ||
|
9a78be1808 | ||
|
0ce3b29d56 | ||
|
22e8257c2d | ||
|
d21f299cb3 | ||
|
1bbad64354 | ||
|
c27c24530c | ||
|
cb62ee1f81 | ||
|
34a28994be | ||
|
c8064eb721 | ||
|
1aca2e1ec1 | ||
|
d3f78ebc81 | ||
|
d4be8589c3 | ||
|
5872287fa1 | ||
|
db9848cdc3 | ||
|
15922d5c07 | ||
|
6a2d7264b4 | ||
|
a92e3b7488 | ||
|
48c31c2f62 | ||
|
3585735339 | ||
|
f3507c9c60 | ||
|
43e96b9dec | ||
|
ddd7733205 | ||
|
4f51555190 | ||
|
790a04974b | ||
|
fe4ad2a06e | ||
|
cfdb093a22 | ||
|
256beb3f45 | ||
|
4ac7c7b403 | ||
|
85759f3e8d | ||
|
34d510b5de | ||
|
ec0dd75135 | ||
|
887080ee79 | ||
|
1ffb3d6c4c | ||
|
e5c3314947 | ||
|
99a6d4df1b | ||
|
9fce0748c4 | ||
|
f2d40207ea | ||
|
9edc2b688b | ||
|
b359bd04bb | ||
|
dd72bee11f |
7
.gitignore
vendored
7
.gitignore
vendored
@ -1 +1,6 @@
|
||||
/glibc-2.22-719-g1233be7.tar.gz
|
||||
# Release tarballs.
|
||||
/glibc-*.tar.[gx]z
|
||||
# Generated (source) RPMs.
|
||||
/*.rpm
|
||||
# Expanded source trees.
|
||||
/glibc-*/
|
||||
|
1054
ChangeLog.old
1054
ChangeLog.old
File diff suppressed because it is too large
Load Diff
2
README.scripts
Normal file
2
README.scripts
Normal file
@ -0,0 +1,2 @@
|
||||
All of the useful glibc maintainer scripts are located at:
|
||||
https://pagure.io/glibc-maintainer-scripts
|
494
SUPPORTED
Normal file
494
SUPPORTED
Normal file
@ -0,0 +1,494 @@
|
||||
# This file names the currently supported and somewhat tested locales.
|
||||
# If you have any additions please file a glibc bug report.
|
||||
SUPPORTED-LOCALES=\
|
||||
C.UTF-8/UTF-8 \
|
||||
aa_DJ.UTF-8/UTF-8 \
|
||||
aa_DJ/ISO-8859-1 \
|
||||
aa_ER/UTF-8 \
|
||||
aa_ER@saaho/UTF-8 \
|
||||
aa_ET/UTF-8 \
|
||||
af_ZA.UTF-8/UTF-8 \
|
||||
af_ZA/ISO-8859-1 \
|
||||
agr_PE/UTF-8 \
|
||||
ak_GH/UTF-8 \
|
||||
am_ET/UTF-8 \
|
||||
an_ES.UTF-8/UTF-8 \
|
||||
an_ES/ISO-8859-15 \
|
||||
anp_IN/UTF-8 \
|
||||
ar_AE.UTF-8/UTF-8 \
|
||||
ar_AE/ISO-8859-6 \
|
||||
ar_BH.UTF-8/UTF-8 \
|
||||
ar_BH/ISO-8859-6 \
|
||||
ar_DZ.UTF-8/UTF-8 \
|
||||
ar_DZ/ISO-8859-6 \
|
||||
ar_EG.UTF-8/UTF-8 \
|
||||
ar_EG/ISO-8859-6 \
|
||||
ar_IN/UTF-8 \
|
||||
ar_IQ.UTF-8/UTF-8 \
|
||||
ar_IQ/ISO-8859-6 \
|
||||
ar_JO.UTF-8/UTF-8 \
|
||||
ar_JO/ISO-8859-6 \
|
||||
ar_KW.UTF-8/UTF-8 \
|
||||
ar_KW/ISO-8859-6 \
|
||||
ar_LB.UTF-8/UTF-8 \
|
||||
ar_LB/ISO-8859-6 \
|
||||
ar_LY.UTF-8/UTF-8 \
|
||||
ar_LY/ISO-8859-6 \
|
||||
ar_MA.UTF-8/UTF-8 \
|
||||
ar_MA/ISO-8859-6 \
|
||||
ar_OM.UTF-8/UTF-8 \
|
||||
ar_OM/ISO-8859-6 \
|
||||
ar_QA.UTF-8/UTF-8 \
|
||||
ar_QA/ISO-8859-6 \
|
||||
ar_SA.UTF-8/UTF-8 \
|
||||
ar_SA/ISO-8859-6 \
|
||||
ar_SD.UTF-8/UTF-8 \
|
||||
ar_SD/ISO-8859-6 \
|
||||
ar_SS/UTF-8 \
|
||||
ar_SY.UTF-8/UTF-8 \
|
||||
ar_SY/ISO-8859-6 \
|
||||
ar_TN.UTF-8/UTF-8 \
|
||||
ar_TN/ISO-8859-6 \
|
||||
ar_YE.UTF-8/UTF-8 \
|
||||
ar_YE/ISO-8859-6 \
|
||||
ayc_PE/UTF-8 \
|
||||
az_AZ/UTF-8 \
|
||||
az_IR/UTF-8 \
|
||||
as_IN/UTF-8 \
|
||||
ast_ES.UTF-8/UTF-8 \
|
||||
ast_ES/ISO-8859-15 \
|
||||
be_BY.UTF-8/UTF-8 \
|
||||
be_BY/CP1251 \
|
||||
be_BY@latin/UTF-8 \
|
||||
bem_ZM/UTF-8 \
|
||||
ber_DZ/UTF-8 \
|
||||
ber_MA/UTF-8 \
|
||||
bg_BG.UTF-8/UTF-8 \
|
||||
bg_BG/CP1251 \
|
||||
bhb_IN.UTF-8/UTF-8 \
|
||||
bho_IN/UTF-8 \
|
||||
bho_NP/UTF-8 \
|
||||
bi_VU/UTF-8 \
|
||||
bn_BD/UTF-8 \
|
||||
bn_IN/UTF-8 \
|
||||
bo_CN/UTF-8 \
|
||||
bo_IN/UTF-8 \
|
||||
br_FR.UTF-8/UTF-8 \
|
||||
br_FR/ISO-8859-1 \
|
||||
br_FR@euro/ISO-8859-15 \
|
||||
brx_IN/UTF-8 \
|
||||
bs_BA.UTF-8/UTF-8 \
|
||||
bs_BA/ISO-8859-2 \
|
||||
byn_ER/UTF-8 \
|
||||
ca_AD.UTF-8/UTF-8 \
|
||||
ca_AD/ISO-8859-15 \
|
||||
ca_ES.UTF-8/UTF-8 \
|
||||
ca_ES/ISO-8859-1 \
|
||||
ca_ES@euro/ISO-8859-15 \
|
||||
ca_ES@valencia/UTF-8 \
|
||||
ca_FR.UTF-8/UTF-8 \
|
||||
ca_FR/ISO-8859-15 \
|
||||
ca_IT.UTF-8/UTF-8 \
|
||||
ca_IT/ISO-8859-15 \
|
||||
ce_RU/UTF-8 \
|
||||
chr_US/UTF-8 \
|
||||
cmn_TW/UTF-8 \
|
||||
crh_UA/UTF-8 \
|
||||
cs_CZ.UTF-8/UTF-8 \
|
||||
cs_CZ/ISO-8859-2 \
|
||||
csb_PL/UTF-8 \
|
||||
cv_RU/UTF-8 \
|
||||
cy_GB.UTF-8/UTF-8 \
|
||||
cy_GB/ISO-8859-14 \
|
||||
da_DK.UTF-8/UTF-8 \
|
||||
da_DK/ISO-8859-1 \
|
||||
da_DK.ISO-8859-15/ISO-8859-15 \
|
||||
de_AT.UTF-8/UTF-8 \
|
||||
de_AT/ISO-8859-1 \
|
||||
de_AT@euro/ISO-8859-15 \
|
||||
de_BE.UTF-8/UTF-8 \
|
||||
de_BE/ISO-8859-1 \
|
||||
de_BE@euro/ISO-8859-15 \
|
||||
de_CH.UTF-8/UTF-8 \
|
||||
de_CH/ISO-8859-1 \
|
||||
de_DE.UTF-8/UTF-8 \
|
||||
de_DE/ISO-8859-1 \
|
||||
de_DE@euro/ISO-8859-15 \
|
||||
de_IT.UTF-8/UTF-8 \
|
||||
de_IT/ISO-8859-1 \
|
||||
de_LI.UTF-8/UTF-8 \
|
||||
de_LU.UTF-8/UTF-8 \
|
||||
de_LU/ISO-8859-1 \
|
||||
de_LU@euro/ISO-8859-15 \
|
||||
doi_IN/UTF-8 \
|
||||
dsb_DE/UTF-8 \
|
||||
dv_MV/UTF-8 \
|
||||
dz_BT/UTF-8 \
|
||||
el_GR.UTF-8/UTF-8 \
|
||||
el_GR/ISO-8859-7 \
|
||||
el_GR@euro/ISO-8859-7 \
|
||||
el_CY.UTF-8/UTF-8 \
|
||||
el_CY/ISO-8859-7 \
|
||||
en_AG/UTF-8 \
|
||||
en_AU.UTF-8/UTF-8 \
|
||||
en_AU/ISO-8859-1 \
|
||||
en_BW.UTF-8/UTF-8 \
|
||||
en_BW/ISO-8859-1 \
|
||||
en_CA.UTF-8/UTF-8 \
|
||||
en_CA/ISO-8859-1 \
|
||||
en_DK.UTF-8/UTF-8 \
|
||||
en_DK/ISO-8859-1 \
|
||||
en_GB.UTF-8/UTF-8 \
|
||||
en_GB/ISO-8859-1 \
|
||||
en_GB.ISO-8859-15/ISO-8859-15 \
|
||||
en_HK.UTF-8/UTF-8 \
|
||||
en_HK/ISO-8859-1 \
|
||||
en_IE.UTF-8/UTF-8 \
|
||||
en_IE/ISO-8859-1 \
|
||||
en_IE@euro/ISO-8859-15 \
|
||||
en_IL/UTF-8 \
|
||||
en_IN/UTF-8 \
|
||||
en_NG/UTF-8 \
|
||||
en_NZ.UTF-8/UTF-8 \
|
||||
en_NZ/ISO-8859-1 \
|
||||
en_PH.UTF-8/UTF-8 \
|
||||
en_PH/ISO-8859-1 \
|
||||
en_SC.UTF-8/UTF-8 \
|
||||
en_SG.UTF-8/UTF-8 \
|
||||
en_SG/ISO-8859-1 \
|
||||
en_US.UTF-8/UTF-8 \
|
||||
en_US/ISO-8859-1 \
|
||||
en_US.ISO-8859-15/ISO-8859-15 \
|
||||
en_ZA.UTF-8/UTF-8 \
|
||||
en_ZA/ISO-8859-1 \
|
||||
en_ZM/UTF-8 \
|
||||
en_ZW.UTF-8/UTF-8 \
|
||||
en_ZW/ISO-8859-1 \
|
||||
eo/UTF-8 \
|
||||
es_AR.UTF-8/UTF-8 \
|
||||
es_AR/ISO-8859-1 \
|
||||
es_BO.UTF-8/UTF-8 \
|
||||
es_BO/ISO-8859-1 \
|
||||
es_CL.UTF-8/UTF-8 \
|
||||
es_CL/ISO-8859-1 \
|
||||
es_CO.UTF-8/UTF-8 \
|
||||
es_CO/ISO-8859-1 \
|
||||
es_CR.UTF-8/UTF-8 \
|
||||
es_CR/ISO-8859-1 \
|
||||
es_CU/UTF-8 \
|
||||
es_DO.UTF-8/UTF-8 \
|
||||
es_DO/ISO-8859-1 \
|
||||
es_EC.UTF-8/UTF-8 \
|
||||
es_EC/ISO-8859-1 \
|
||||
es_ES.UTF-8/UTF-8 \
|
||||
es_ES/ISO-8859-1 \
|
||||
es_ES@euro/ISO-8859-15 \
|
||||
es_GT.UTF-8/UTF-8 \
|
||||
es_GT/ISO-8859-1 \
|
||||
es_HN.UTF-8/UTF-8 \
|
||||
es_HN/ISO-8859-1 \
|
||||
es_MX.UTF-8/UTF-8 \
|
||||
es_MX/ISO-8859-1 \
|
||||
es_NI.UTF-8/UTF-8 \
|
||||
es_NI/ISO-8859-1 \
|
||||
es_PA.UTF-8/UTF-8 \
|
||||
es_PA/ISO-8859-1 \
|
||||
es_PE.UTF-8/UTF-8 \
|
||||
es_PE/ISO-8859-1 \
|
||||
es_PR.UTF-8/UTF-8 \
|
||||
es_PR/ISO-8859-1 \
|
||||
es_PY.UTF-8/UTF-8 \
|
||||
es_PY/ISO-8859-1 \
|
||||
es_SV.UTF-8/UTF-8 \
|
||||
es_SV/ISO-8859-1 \
|
||||
es_US.UTF-8/UTF-8 \
|
||||
es_US/ISO-8859-1 \
|
||||
es_UY.UTF-8/UTF-8 \
|
||||
es_UY/ISO-8859-1 \
|
||||
es_VE.UTF-8/UTF-8 \
|
||||
es_VE/ISO-8859-1 \
|
||||
et_EE.UTF-8/UTF-8 \
|
||||
et_EE/ISO-8859-1 \
|
||||
et_EE.ISO-8859-15/ISO-8859-15 \
|
||||
eu_ES.UTF-8/UTF-8 \
|
||||
eu_ES/ISO-8859-1 \
|
||||
eu_ES@euro/ISO-8859-15 \
|
||||
fa_IR/UTF-8 \
|
||||
ff_SN/UTF-8 \
|
||||
fi_FI.UTF-8/UTF-8 \
|
||||
fi_FI/ISO-8859-1 \
|
||||
fi_FI@euro/ISO-8859-15 \
|
||||
fil_PH/UTF-8 \
|
||||
fo_FO.UTF-8/UTF-8 \
|
||||
fo_FO/ISO-8859-1 \
|
||||
fr_BE.UTF-8/UTF-8 \
|
||||
fr_BE/ISO-8859-1 \
|
||||
fr_BE@euro/ISO-8859-15 \
|
||||
fr_CA.UTF-8/UTF-8 \
|
||||
fr_CA/ISO-8859-1 \
|
||||
fr_CH.UTF-8/UTF-8 \
|
||||
fr_CH/ISO-8859-1 \
|
||||
fr_FR.UTF-8/UTF-8 \
|
||||
fr_FR/ISO-8859-1 \
|
||||
fr_FR@euro/ISO-8859-15 \
|
||||
fr_LU.UTF-8/UTF-8 \
|
||||
fr_LU/ISO-8859-1 \
|
||||
fr_LU@euro/ISO-8859-15 \
|
||||
fur_IT/UTF-8 \
|
||||
fy_NL/UTF-8 \
|
||||
fy_DE/UTF-8 \
|
||||
ga_IE.UTF-8/UTF-8 \
|
||||
ga_IE/ISO-8859-1 \
|
||||
ga_IE@euro/ISO-8859-15 \
|
||||
gd_GB.UTF-8/UTF-8 \
|
||||
gd_GB/ISO-8859-15 \
|
||||
gez_ER/UTF-8 \
|
||||
gez_ER@abegede/UTF-8 \
|
||||
gez_ET/UTF-8 \
|
||||
gez_ET@abegede/UTF-8 \
|
||||
gl_ES.UTF-8/UTF-8 \
|
||||
gl_ES/ISO-8859-1 \
|
||||
gl_ES@euro/ISO-8859-15 \
|
||||
gu_IN/UTF-8 \
|
||||
gv_GB.UTF-8/UTF-8 \
|
||||
gv_GB/ISO-8859-1 \
|
||||
ha_NG/UTF-8 \
|
||||
hak_TW/UTF-8 \
|
||||
he_IL.UTF-8/UTF-8 \
|
||||
he_IL/ISO-8859-8 \
|
||||
hi_IN/UTF-8 \
|
||||
hif_FJ/UTF-8 \
|
||||
hne_IN/UTF-8 \
|
||||
hr_HR.UTF-8/UTF-8 \
|
||||
hr_HR/ISO-8859-2 \
|
||||
hsb_DE/ISO-8859-2 \
|
||||
hsb_DE.UTF-8/UTF-8 \
|
||||
ht_HT/UTF-8 \
|
||||
hu_HU.UTF-8/UTF-8 \
|
||||
hu_HU/ISO-8859-2 \
|
||||
hy_AM/UTF-8 \
|
||||
hy_AM.ARMSCII-8/ARMSCII-8 \
|
||||
ia_FR/UTF-8 \
|
||||
id_ID.UTF-8/UTF-8 \
|
||||
id_ID/ISO-8859-1 \
|
||||
ig_NG/UTF-8 \
|
||||
ik_CA/UTF-8 \
|
||||
is_IS.UTF-8/UTF-8 \
|
||||
is_IS/ISO-8859-1 \
|
||||
it_CH.UTF-8/UTF-8 \
|
||||
it_CH/ISO-8859-1 \
|
||||
it_IT.UTF-8/UTF-8 \
|
||||
it_IT/ISO-8859-1 \
|
||||
it_IT@euro/ISO-8859-15 \
|
||||
iu_CA/UTF-8 \
|
||||
ja_JP.EUC-JP/EUC-JP \
|
||||
ja_JP.UTF-8/UTF-8 \
|
||||
ka_GE.UTF-8/UTF-8 \
|
||||
ka_GE/GEORGIAN-PS \
|
||||
kab_DZ/UTF-8 \
|
||||
kk_KZ.UTF-8/UTF-8 \
|
||||
kk_KZ/PT154 \
|
||||
kl_GL.UTF-8/UTF-8 \
|
||||
kl_GL/ISO-8859-1 \
|
||||
km_KH/UTF-8 \
|
||||
kn_IN/UTF-8 \
|
||||
ko_KR.EUC-KR/EUC-KR \
|
||||
ko_KR.UTF-8/UTF-8 \
|
||||
kok_IN/UTF-8 \
|
||||
ks_IN/UTF-8 \
|
||||
ks_IN@devanagari/UTF-8 \
|
||||
ku_TR.UTF-8/UTF-8 \
|
||||
ku_TR/ISO-8859-9 \
|
||||
kw_GB.UTF-8/UTF-8 \
|
||||
kw_GB/ISO-8859-1 \
|
||||
ky_KG/UTF-8 \
|
||||
lb_LU/UTF-8 \
|
||||
lg_UG.UTF-8/UTF-8 \
|
||||
lg_UG/ISO-8859-10 \
|
||||
li_BE/UTF-8 \
|
||||
li_NL/UTF-8 \
|
||||
lij_IT/UTF-8 \
|
||||
ln_CD/UTF-8 \
|
||||
lo_LA/UTF-8 \
|
||||
lt_LT.UTF-8/UTF-8 \
|
||||
lt_LT/ISO-8859-13 \
|
||||
lv_LV.UTF-8/UTF-8 \
|
||||
lv_LV/ISO-8859-13 \
|
||||
lzh_TW/UTF-8 \
|
||||
mag_IN/UTF-8 \
|
||||
mai_IN/UTF-8 \
|
||||
mai_NP/UTF-8 \
|
||||
mfe_MU/UTF-8 \
|
||||
mg_MG.UTF-8/UTF-8 \
|
||||
mg_MG/ISO-8859-15 \
|
||||
mhr_RU/UTF-8 \
|
||||
mi_NZ.UTF-8/UTF-8 \
|
||||
mi_NZ/ISO-8859-13 \
|
||||
miq_NI/UTF-8 \
|
||||
mjw_IN/UTF-8 \
|
||||
mk_MK.UTF-8/UTF-8 \
|
||||
mk_MK/ISO-8859-5 \
|
||||
ml_IN/UTF-8 \
|
||||
mn_MN/UTF-8 \
|
||||
mni_IN/UTF-8 \
|
||||
mr_IN/UTF-8 \
|
||||
ms_MY.UTF-8/UTF-8 \
|
||||
ms_MY/ISO-8859-1 \
|
||||
mt_MT.UTF-8/UTF-8 \
|
||||
mt_MT/ISO-8859-3 \
|
||||
my_MM/UTF-8 \
|
||||
nan_TW/UTF-8 \
|
||||
nan_TW@latin/UTF-8 \
|
||||
nb_NO.UTF-8/UTF-8 \
|
||||
nb_NO/ISO-8859-1 \
|
||||
nds_DE/UTF-8 \
|
||||
nds_NL/UTF-8 \
|
||||
ne_NP/UTF-8 \
|
||||
nhn_MX/UTF-8 \
|
||||
niu_NU/UTF-8 \
|
||||
niu_NZ/UTF-8 \
|
||||
nl_AW/UTF-8 \
|
||||
nl_BE.UTF-8/UTF-8 \
|
||||
nl_BE/ISO-8859-1 \
|
||||
nl_BE@euro/ISO-8859-15 \
|
||||
nl_NL.UTF-8/UTF-8 \
|
||||
nl_NL/ISO-8859-1 \
|
||||
nl_NL@euro/ISO-8859-15 \
|
||||
nn_NO.UTF-8/UTF-8 \
|
||||
nn_NO/ISO-8859-1 \
|
||||
nr_ZA/UTF-8 \
|
||||
nso_ZA/UTF-8 \
|
||||
oc_FR.UTF-8/UTF-8 \
|
||||
oc_FR/ISO-8859-1 \
|
||||
om_ET/UTF-8 \
|
||||
om_KE.UTF-8/UTF-8 \
|
||||
om_KE/ISO-8859-1 \
|
||||
or_IN/UTF-8 \
|
||||
os_RU/UTF-8 \
|
||||
pa_IN/UTF-8 \
|
||||
pa_PK/UTF-8 \
|
||||
pap_AW/UTF-8 \
|
||||
pap_CW/UTF-8 \
|
||||
pl_PL.UTF-8/UTF-8 \
|
||||
pl_PL/ISO-8859-2 \
|
||||
ps_AF/UTF-8 \
|
||||
pt_BR.UTF-8/UTF-8 \
|
||||
pt_BR/ISO-8859-1 \
|
||||
pt_PT.UTF-8/UTF-8 \
|
||||
pt_PT/ISO-8859-1 \
|
||||
pt_PT@euro/ISO-8859-15 \
|
||||
quz_PE/UTF-8 \
|
||||
raj_IN/UTF-8 \
|
||||
ro_RO.UTF-8/UTF-8 \
|
||||
ro_RO/ISO-8859-2 \
|
||||
ru_RU.KOI8-R/KOI8-R \
|
||||
ru_RU.UTF-8/UTF-8 \
|
||||
ru_RU/ISO-8859-5 \
|
||||
ru_UA.UTF-8/UTF-8 \
|
||||
ru_UA/KOI8-U \
|
||||
rw_RW/UTF-8 \
|
||||
sa_IN/UTF-8 \
|
||||
sah_RU/UTF-8 \
|
||||
sat_IN/UTF-8 \
|
||||
sc_IT/UTF-8 \
|
||||
sd_IN/UTF-8 \
|
||||
sd_IN@devanagari/UTF-8 \
|
||||
se_NO/UTF-8 \
|
||||
sgs_LT/UTF-8 \
|
||||
shn_MM/UTF-8 \
|
||||
shs_CA/UTF-8 \
|
||||
si_LK/UTF-8 \
|
||||
sid_ET/UTF-8 \
|
||||
sk_SK.UTF-8/UTF-8 \
|
||||
sk_SK/ISO-8859-2 \
|
||||
sl_SI.UTF-8/UTF-8 \
|
||||
sl_SI/ISO-8859-2 \
|
||||
sm_WS/UTF-8 \
|
||||
so_DJ.UTF-8/UTF-8 \
|
||||
so_DJ/ISO-8859-1 \
|
||||
so_ET/UTF-8 \
|
||||
so_KE.UTF-8/UTF-8 \
|
||||
so_KE/ISO-8859-1 \
|
||||
so_SO.UTF-8/UTF-8 \
|
||||
so_SO/ISO-8859-1 \
|
||||
sq_AL.UTF-8/UTF-8 \
|
||||
sq_AL/ISO-8859-1 \
|
||||
sq_MK/UTF-8 \
|
||||
sr_ME/UTF-8 \
|
||||
sr_RS/UTF-8 \
|
||||
sr_RS@latin/UTF-8 \
|
||||
ss_ZA/UTF-8 \
|
||||
st_ZA.UTF-8/UTF-8 \
|
||||
st_ZA/ISO-8859-1 \
|
||||
sv_FI.UTF-8/UTF-8 \
|
||||
sv_FI/ISO-8859-1 \
|
||||
sv_FI@euro/ISO-8859-15 \
|
||||
sv_SE.UTF-8/UTF-8 \
|
||||
sv_SE/ISO-8859-1 \
|
||||
sv_SE.ISO-8859-15/ISO-8859-15 \
|
||||
sw_KE/UTF-8 \
|
||||
sw_TZ/UTF-8 \
|
||||
szl_PL/UTF-8 \
|
||||
ta_IN/UTF-8 \
|
||||
ta_LK/UTF-8 \
|
||||
tcy_IN.UTF-8/UTF-8 \
|
||||
te_IN/UTF-8 \
|
||||
tg_TJ.UTF-8/UTF-8 \
|
||||
tg_TJ/KOI8-T \
|
||||
th_TH.UTF-8/UTF-8 \
|
||||
th_TH/TIS-620 \
|
||||
the_NP/UTF-8 \
|
||||
ti_ER/UTF-8 \
|
||||
ti_ET/UTF-8 \
|
||||
tig_ER/UTF-8 \
|
||||
tk_TM/UTF-8 \
|
||||
tl_PH.UTF-8/UTF-8 \
|
||||
tl_PH/ISO-8859-1 \
|
||||
tn_ZA/UTF-8 \
|
||||
to_TO/UTF-8 \
|
||||
tpi_PG/UTF-8 \
|
||||
tr_CY.UTF-8/UTF-8 \
|
||||
tr_CY/ISO-8859-9 \
|
||||
tr_TR.UTF-8/UTF-8 \
|
||||
tr_TR/ISO-8859-9 \
|
||||
ts_ZA/UTF-8 \
|
||||
tt_RU/UTF-8 \
|
||||
tt_RU@iqtelif/UTF-8 \
|
||||
ug_CN/UTF-8 \
|
||||
uk_UA.UTF-8/UTF-8 \
|
||||
uk_UA/KOI8-U \
|
||||
unm_US/UTF-8 \
|
||||
ur_IN/UTF-8 \
|
||||
ur_PK/UTF-8 \
|
||||
uz_UZ.UTF-8/UTF-8 \
|
||||
uz_UZ/ISO-8859-1 \
|
||||
uz_UZ@cyrillic/UTF-8 \
|
||||
ve_ZA/UTF-8 \
|
||||
vi_VN/UTF-8 \
|
||||
wa_BE/ISO-8859-1 \
|
||||
wa_BE@euro/ISO-8859-15 \
|
||||
wa_BE.UTF-8/UTF-8 \
|
||||
wae_CH/UTF-8 \
|
||||
wal_ET/UTF-8 \
|
||||
wo_SN/UTF-8 \
|
||||
xh_ZA.UTF-8/UTF-8 \
|
||||
xh_ZA/ISO-8859-1 \
|
||||
yi_US.UTF-8/UTF-8 \
|
||||
yi_US/CP1255 \
|
||||
yo_NG/UTF-8 \
|
||||
yue_HK/UTF-8 \
|
||||
yuw_PG/UTF-8 \
|
||||
zh_CN.GB18030/GB18030 \
|
||||
zh_CN.GBK/GBK \
|
||||
zh_CN.UTF-8/UTF-8 \
|
||||
zh_CN/GB2312 \
|
||||
zh_HK.UTF-8/UTF-8 \
|
||||
zh_HK/BIG5-HKSCS \
|
||||
zh_SG.UTF-8/UTF-8 \
|
||||
zh_SG.GBK/GBK \
|
||||
zh_SG/GB2312 \
|
||||
zh_TW.EUC-TW/EUC-TW \
|
||||
zh_TW.UTF-8/UTF-8 \
|
||||
zh_TW/BIG5 \
|
||||
zu_ZA.UTF-8/UTF-8 \
|
||||
zu_ZA/ISO-8859-1 \
|
@ -1,857 +0,0 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include "../locale/hashval.h"
|
||||
#define __LC_LAST 13
|
||||
#include "../locale/locarchive.h"
|
||||
#include "../crypt/md5.h"
|
||||
|
||||
const char *alias_file = DATADIR "/locale/locale.alias";
|
||||
const char *locar_file = PREFIX "/lib/locale/locale-archive";
|
||||
const char *tmpl_file = PREFIX "/lib/locale/locale-archive.tmpl";
|
||||
const char *loc_path = PREFIX "/lib/locale/";
|
||||
/* Flags set by `--verbose` option. */
|
||||
int be_quiet = 1;
|
||||
int verbose = 0;
|
||||
int max_locarchive_open_retry = 10;
|
||||
const char *output_prefix;
|
||||
|
||||
/* Endianness should have been taken care of by localedef. We don't need to do
|
||||
additional swapping. We need this variable exported however, since
|
||||
locarchive.c uses it to determine if it needs to swap endianness of a value
|
||||
before writing to or reading from the archive. */
|
||||
bool swap_endianness_p = false;
|
||||
|
||||
static const char *locnames[] =
|
||||
{
|
||||
#define DEFINE_CATEGORY(category, category_name, items, a) \
|
||||
[category] = category_name,
|
||||
#include "../locale/categories.def"
|
||||
#undef DEFINE_CATEGORY
|
||||
};
|
||||
|
||||
static int
|
||||
is_prime (unsigned long candidate)
|
||||
{
|
||||
/* No even number and none less than 10 will be passed here. */
|
||||
unsigned long int divn = 3;
|
||||
unsigned long int sq = divn * divn;
|
||||
|
||||
while (sq < candidate && candidate % divn != 0)
|
||||
{
|
||||
++divn;
|
||||
sq += 4 * divn;
|
||||
++divn;
|
||||
}
|
||||
|
||||
return candidate % divn != 0;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
next_prime (unsigned long seed)
|
||||
{
|
||||
/* Make it definitely odd. */
|
||||
seed |= 1;
|
||||
|
||||
while (!is_prime (seed))
|
||||
seed += 2;
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
void
|
||||
error (int status, int errnum, const char *message, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, message);
|
||||
fflush (stdout);
|
||||
fprintf (stderr, "%s: ", program_invocation_name);
|
||||
vfprintf (stderr, message, args);
|
||||
va_end (args);
|
||||
if (errnum)
|
||||
fprintf (stderr, ": %s", strerror (errnum));
|
||||
putc ('\n', stderr);
|
||||
fflush (stderr);
|
||||
if (status)
|
||||
exit (errnum == EROFS ? 0 : status);
|
||||
}
|
||||
|
||||
void *
|
||||
xmalloc (size_t size)
|
||||
{
|
||||
void *p = malloc (size);
|
||||
if (p == NULL)
|
||||
error (EXIT_FAILURE, errno, "could not allocate %zd bytes of memory", size);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
open_tmpl_archive (struct locarhandle *ah)
|
||||
{
|
||||
struct stat64 st;
|
||||
int fd;
|
||||
struct locarhead head;
|
||||
const char *archivefname = ah->fname == NULL ? tmpl_file : ah->fname;
|
||||
|
||||
/* Open the archive. We must have exclusive write access. */
|
||||
fd = open64 (archivefname, O_RDONLY);
|
||||
if (fd == -1)
|
||||
error (EXIT_FAILURE, errno, "cannot open locale archive template file \"%s\"",
|
||||
archivefname);
|
||||
|
||||
if (fstat64 (fd, &st) < 0)
|
||||
error (EXIT_FAILURE, errno, "cannot stat locale archive template file \"%s\"",
|
||||
archivefname);
|
||||
|
||||
/* Read the header. */
|
||||
if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head))
|
||||
error (EXIT_FAILURE, errno, "cannot read archive header");
|
||||
|
||||
ah->fd = fd;
|
||||
ah->mmaped = (head.sumhash_offset
|
||||
+ head.sumhash_size * sizeof (struct sumhashent));
|
||||
if (ah->mmaped > (unsigned long) st.st_size)
|
||||
error (EXIT_FAILURE, 0, "locale archive template file truncated");
|
||||
ah->mmaped = st.st_size;
|
||||
ah->reserved = st.st_size;
|
||||
|
||||
/* Now we know how large the administrative information part is.
|
||||
Map all of it. */
|
||||
ah->addr = mmap64 (NULL, ah->mmaped, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (ah->addr == MAP_FAILED)
|
||||
error (EXIT_FAILURE, errno, "cannot map archive header");
|
||||
}
|
||||
|
||||
/* Open the locale archive. */
|
||||
extern void open_archive (struct locarhandle *ah, bool readonly);
|
||||
|
||||
/* Close the locale archive. */
|
||||
extern void close_archive (struct locarhandle *ah);
|
||||
|
||||
/* Add given locale data to the archive. */
|
||||
extern int add_locale_to_archive (struct locarhandle *ah, const char *name,
|
||||
locale_data_t data, bool replace);
|
||||
|
||||
extern void add_alias (struct locarhandle *ah, const char *alias,
|
||||
bool replace, const char *oldname,
|
||||
uint32_t *locrec_offset_p);
|
||||
|
||||
extern struct namehashent *
|
||||
insert_name (struct locarhandle *ah,
|
||||
const char *name, size_t name_len, bool replace);
|
||||
|
||||
struct nameent
|
||||
{
|
||||
char *name;
|
||||
struct locrecent *locrec;
|
||||
};
|
||||
|
||||
struct dataent
|
||||
{
|
||||
const unsigned char *sum;
|
||||
uint32_t file_offset;
|
||||
};
|
||||
|
||||
static int
|
||||
nameentcmp (const void *a, const void *b)
|
||||
{
|
||||
struct locrecent *la = ((const struct nameent *) a)->locrec;
|
||||
struct locrecent *lb = ((const struct nameent *) b)->locrec;
|
||||
uint32_t start_a = -1, end_a = 0;
|
||||
uint32_t start_b = -1, end_b = 0;
|
||||
int cnt;
|
||||
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
if (la->record[cnt].offset < start_a)
|
||||
start_a = la->record[cnt].offset;
|
||||
if (la->record[cnt].offset + la->record[cnt].len > end_a)
|
||||
end_a = la->record[cnt].offset + la->record[cnt].len;
|
||||
}
|
||||
assert (start_a != (uint32_t)-1);
|
||||
assert (end_a != 0);
|
||||
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
if (lb->record[cnt].offset < start_b)
|
||||
start_b = lb->record[cnt].offset;
|
||||
if (lb->record[cnt].offset + lb->record[cnt].len > end_b)
|
||||
end_b = lb->record[cnt].offset + lb->record[cnt].len;
|
||||
}
|
||||
assert (start_b != (uint32_t)-1);
|
||||
assert (end_b != 0);
|
||||
|
||||
if (start_a != start_b)
|
||||
return (int)start_a - (int)start_b;
|
||||
return (int)end_a - (int)end_b;
|
||||
}
|
||||
|
||||
static int
|
||||
dataentcmp (const void *a, const void *b)
|
||||
{
|
||||
if (((const struct dataent *) a)->file_offset
|
||||
< ((const struct dataent *) b)->file_offset)
|
||||
return -1;
|
||||
|
||||
if (((const struct dataent *) a)->file_offset
|
||||
> ((const struct dataent *) b)->file_offset)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sumsearchfn (const void *key, const void *ent)
|
||||
{
|
||||
uint32_t keyn = *(uint32_t *)key;
|
||||
uint32_t entn = ((struct dataent *)ent)->file_offset;
|
||||
|
||||
if (keyn < entn)
|
||||
return -1;
|
||||
if (keyn > entn)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
compute_data (struct locarhandle *ah, struct nameent *name, size_t sumused,
|
||||
struct dataent *files, locale_data_t data)
|
||||
{
|
||||
int cnt;
|
||||
struct locrecent *locrec = name->locrec;
|
||||
struct dataent *file;
|
||||
data[LC_ALL].addr = ((char *) ah->addr) + locrec->record[LC_ALL].offset;
|
||||
data[LC_ALL].size = locrec->record[LC_ALL].len;
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
data[cnt].addr = ((char *) ah->addr) + locrec->record[cnt].offset;
|
||||
data[cnt].size = locrec->record[cnt].len;
|
||||
if (data[cnt].addr >= data[LC_ALL].addr
|
||||
&& data[cnt].addr + data[cnt].size
|
||||
<= data[LC_ALL].addr + data[LC_ALL].size)
|
||||
__md5_buffer (data[cnt].addr, data[cnt].size, data[cnt].sum);
|
||||
else
|
||||
{
|
||||
file = bsearch (&locrec->record[cnt].offset, files, sumused,
|
||||
sizeof (*files), sumsearchfn);
|
||||
if (file == NULL)
|
||||
error (EXIT_FAILURE, 0, "inconsistent template file");
|
||||
memcpy (data[cnt].sum, file->sum, sizeof (data[cnt].sum));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
fill_archive (struct locarhandle *tmpl_ah,
|
||||
const char *fname,
|
||||
size_t install_langs_count, char *install_langs_list[],
|
||||
size_t nlist, char *list[],
|
||||
const char *primary)
|
||||
{
|
||||
struct locarhandle ah;
|
||||
struct locarhead *head;
|
||||
int result = 0;
|
||||
struct nameent *names;
|
||||
struct namehashent *namehashtab;
|
||||
size_t cnt, used;
|
||||
struct dataent *files;
|
||||
struct sumhashent *sumhashtab;
|
||||
size_t sumused;
|
||||
struct locrecent *primary_locrec = NULL;
|
||||
struct nameent *primary_nameent = NULL;
|
||||
|
||||
head = tmpl_ah->addr;
|
||||
names = (struct nameent *) malloc (head->namehash_used
|
||||
* sizeof (struct nameent));
|
||||
files = (struct dataent *) malloc (head->sumhash_used
|
||||
* sizeof (struct dataent));
|
||||
if (names == NULL || files == NULL)
|
||||
error (EXIT_FAILURE, errno, "could not allocate tables");
|
||||
|
||||
namehashtab = (struct namehashent *) ((char *) tmpl_ah->addr
|
||||
+ head->namehash_offset);
|
||||
sumhashtab = (struct sumhashent *) ((char *) tmpl_ah->addr
|
||||
+ head->sumhash_offset);
|
||||
|
||||
for (cnt = used = 0; cnt < head->namehash_size; ++cnt)
|
||||
if (namehashtab[cnt].locrec_offset != 0)
|
||||
{
|
||||
char * name;
|
||||
int i;
|
||||
assert (used < head->namehash_used);
|
||||
name = tmpl_ah->addr + namehashtab[cnt].name_offset;
|
||||
if (install_langs_count == 0)
|
||||
{
|
||||
/* Always intstall the entry. */
|
||||
names[used].name = name;
|
||||
names[used++].locrec
|
||||
= (struct locrecent *) ((char *) tmpl_ah->addr +
|
||||
namehashtab[cnt].locrec_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only install the entry if the user asked for it via
|
||||
--install-langs. */
|
||||
for (i = 0; i < install_langs_count; i++)
|
||||
{
|
||||
/* Add one for "_" and one for the null terminator. */
|
||||
size_t len = strlen (install_langs_list[i]) + 2;
|
||||
char *install_lang = (char *)xmalloc (len);
|
||||
strcpy (install_lang, install_langs_list[i]);
|
||||
if (strchr (install_lang, '_') == NULL)
|
||||
strcat (install_lang, "_");
|
||||
if (strncmp (name, install_lang, strlen (install_lang)) == 0)
|
||||
{
|
||||
names[used].name = name;
|
||||
names[used++].locrec
|
||||
= (struct locrecent *) ((char *)tmpl_ah->addr
|
||||
+ namehashtab[cnt].locrec_offset);
|
||||
}
|
||||
free (install_lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort the names. */
|
||||
qsort (names, used, sizeof (struct nameent), nameentcmp);
|
||||
|
||||
for (cnt = sumused = 0; cnt < head->sumhash_size; ++cnt)
|
||||
if (sumhashtab[cnt].file_offset != 0)
|
||||
{
|
||||
assert (sumused < head->sumhash_used);
|
||||
files[sumused].sum = (const unsigned char *) sumhashtab[cnt].sum;
|
||||
files[sumused++].file_offset = sumhashtab[cnt].file_offset;
|
||||
}
|
||||
|
||||
/* Sort by file locations. */
|
||||
qsort (files, sumused, sizeof (struct dataent), dataentcmp);
|
||||
|
||||
/* Open the archive. This call never returns if we cannot
|
||||
successfully open the archive. */
|
||||
ah.fname = NULL;
|
||||
if (fname != NULL)
|
||||
ah.fname = fname;
|
||||
open_archive (&ah, false);
|
||||
|
||||
if (primary != NULL)
|
||||
{
|
||||
for (cnt = 0; cnt < used; ++cnt)
|
||||
if (strcmp (names[cnt].name, primary) == 0)
|
||||
break;
|
||||
if (cnt < used)
|
||||
{
|
||||
locale_data_t data;
|
||||
|
||||
compute_data (tmpl_ah, &names[cnt], sumused, files, data);
|
||||
result |= add_locale_to_archive (&ah, primary, data, 0);
|
||||
primary_locrec = names[cnt].locrec;
|
||||
primary_nameent = &names[cnt];
|
||||
}
|
||||
}
|
||||
|
||||
for (cnt = 0; cnt < used; ++cnt)
|
||||
if (&names[cnt] == primary_nameent)
|
||||
continue;
|
||||
else if ((cnt > 0 && names[cnt - 1].locrec == names[cnt].locrec)
|
||||
|| names[cnt].locrec == primary_locrec)
|
||||
{
|
||||
const char *oldname;
|
||||
struct namehashent *namehashent;
|
||||
uint32_t locrec_offset;
|
||||
|
||||
if (names[cnt].locrec == primary_locrec)
|
||||
oldname = primary;
|
||||
else
|
||||
oldname = names[cnt - 1].name;
|
||||
namehashent = insert_name (&ah, oldname, strlen (oldname), true);
|
||||
assert (namehashent->name_offset != 0);
|
||||
assert (namehashent->locrec_offset != 0);
|
||||
locrec_offset = namehashent->locrec_offset;
|
||||
add_alias (&ah, names[cnt].name, 0, oldname, &locrec_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
locale_data_t data;
|
||||
|
||||
compute_data (tmpl_ah, &names[cnt], sumused, files, data);
|
||||
result |= add_locale_to_archive (&ah, names[cnt].name, data, 0);
|
||||
}
|
||||
|
||||
while (nlist-- > 0)
|
||||
{
|
||||
const char *fname = *list++;
|
||||
size_t fnamelen = strlen (fname);
|
||||
struct stat64 st;
|
||||
DIR *dirp;
|
||||
struct dirent64 *d;
|
||||
int seen;
|
||||
locale_data_t data;
|
||||
int cnt;
|
||||
|
||||
/* First see whether this really is a directory and whether it
|
||||
contains all the require locale category files. */
|
||||
if (stat64 (fname, &st) < 0)
|
||||
{
|
||||
error (0, 0, "stat of \"%s\" failed: %s: ignored", fname,
|
||||
strerror (errno));
|
||||
continue;
|
||||
}
|
||||
if (!S_ISDIR (st.st_mode))
|
||||
{
|
||||
error (0, 0, "\"%s\" is no directory; ignored", fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
dirp = opendir (fname);
|
||||
if (dirp == NULL)
|
||||
{
|
||||
error (0, 0, "cannot open directory \"%s\": %s: ignored",
|
||||
fname, strerror (errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
seen = 0;
|
||||
while ((d = readdir64 (dirp)) != NULL)
|
||||
{
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
if (strcmp (d->d_name, locnames[cnt]) == 0)
|
||||
{
|
||||
unsigned char d_type;
|
||||
|
||||
/* We have an object of the required name. If it's
|
||||
a directory we have to look at a file with the
|
||||
prefix "SYS_". Otherwise we have found what we
|
||||
are looking for. */
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
d_type = d->d_type;
|
||||
|
||||
if (d_type != DT_REG)
|
||||
#endif
|
||||
{
|
||||
char fullname[fnamelen + 2 * strlen (d->d_name) + 7];
|
||||
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
if (d_type == DT_UNKNOWN)
|
||||
#endif
|
||||
{
|
||||
strcpy (stpcpy (stpcpy (fullname, fname), "/"),
|
||||
d->d_name);
|
||||
|
||||
if (stat64 (fullname, &st) == -1)
|
||||
/* We cannot stat the file, ignore it. */
|
||||
break;
|
||||
|
||||
d_type = IFTODT (st.st_mode);
|
||||
}
|
||||
|
||||
if (d_type == DT_DIR)
|
||||
{
|
||||
/* We have to do more tests. The file is a
|
||||
directory and it therefore must contain a
|
||||
regular file with the same name except a
|
||||
"SYS_" prefix. */
|
||||
char *t = stpcpy (stpcpy (fullname, fname), "/");
|
||||
strcpy (stpcpy (stpcpy (t, d->d_name), "/SYS_"),
|
||||
d->d_name);
|
||||
|
||||
if (stat64 (fullname, &st) == -1)
|
||||
/* There is no SYS_* file or we cannot
|
||||
access it. */
|
||||
break;
|
||||
|
||||
d_type = IFTODT (st.st_mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we found a regular file (eventually after
|
||||
following a symlink) we are successful. */
|
||||
if (d_type == DT_REG)
|
||||
++seen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir (dirp);
|
||||
|
||||
if (seen != __LC_LAST - 1)
|
||||
{
|
||||
/* We don't have all locale category files. Ignore the name. */
|
||||
error (0, 0, "incomplete set of locale files in \"%s\"",
|
||||
fname);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add the files to the archive. To do this we first compute
|
||||
sizes and the MD5 sums of all the files. */
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
{
|
||||
char fullname[fnamelen + 2 * strlen (locnames[cnt]) + 7];
|
||||
int fd;
|
||||
|
||||
strcpy (stpcpy (stpcpy (fullname, fname), "/"), locnames[cnt]);
|
||||
fd = open64 (fullname, O_RDONLY);
|
||||
if (fd == -1 || fstat64 (fd, &st) == -1)
|
||||
{
|
||||
/* Cannot read the file. */
|
||||
if (fd != -1)
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
|
||||
if (S_ISDIR (st.st_mode))
|
||||
{
|
||||
char *t;
|
||||
close (fd);
|
||||
t = stpcpy (stpcpy (fullname, fname), "/");
|
||||
strcpy (stpcpy (stpcpy (t, locnames[cnt]), "/SYS_"),
|
||||
locnames[cnt]);
|
||||
|
||||
fd = open64 (fullname, O_RDONLY);
|
||||
if (fd == -1 || fstat64 (fd, &st) == -1
|
||||
|| !S_ISREG (st.st_mode))
|
||||
{
|
||||
if (fd != -1)
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Map the file. */
|
||||
data[cnt].addr = mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED,
|
||||
fd, 0);
|
||||
if (data[cnt].addr == MAP_FAILED)
|
||||
{
|
||||
/* Cannot map it. */
|
||||
close (fd);
|
||||
break;
|
||||
}
|
||||
|
||||
data[cnt].size = st.st_size;
|
||||
__md5_buffer (data[cnt].addr, st.st_size, data[cnt].sum);
|
||||
|
||||
/* We don't need the file descriptor anymore. */
|
||||
close (fd);
|
||||
}
|
||||
|
||||
if (cnt != __LC_LAST)
|
||||
{
|
||||
while (cnt-- > 0)
|
||||
if (cnt != LC_ALL)
|
||||
munmap (data[cnt].addr, data[cnt].size);
|
||||
|
||||
error (0, 0, "cannot read all files in \"%s\": ignored", fname);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
result |= add_locale_to_archive (&ah, basename (fname), data, 0);
|
||||
|
||||
for (cnt = 0; cnt < __LC_LAST; ++cnt)
|
||||
if (cnt != LC_ALL)
|
||||
munmap (data[cnt].addr, data[cnt].size);
|
||||
}
|
||||
|
||||
/* We are done. */
|
||||
close_archive (&ah);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
printf ("\
|
||||
Usage: build-locale-archive [OPTION]... [TEMPLATE-FILE] [ARCHIVE-FILE]\n\
|
||||
Builds a locale archive from a template file.\n\
|
||||
Options:\n\
|
||||
-h, --help Print this usage message.\n\
|
||||
-v, --verbose Verbose execution.\n\
|
||||
-l, --install-langs=LIST Only include locales given in LIST into the \n\
|
||||
locale archive. LIST is a colon separated list\n\
|
||||
of locale prefixes, for example \"de:en:ja\".\n\
|
||||
The special argument \"all\" means to install\n\
|
||||
all languages and it must be present by itself.\n\
|
||||
If \"all\" is present with any other language it\n\
|
||||
will be treated as the name of a locale.\n\
|
||||
If the --install-langs option is missing, all\n\
|
||||
locales are installed. The colon separated list\n\
|
||||
can contain any strings matching the beginning of\n\
|
||||
locale names.\n\
|
||||
If a string does not contain a \"_\", it is added.\n\
|
||||
Examples:\n\
|
||||
--install-langs=\"en\"\n\
|
||||
installs en_US, en_US.iso88591,\n\
|
||||
en_US.iso885915, en_US.utf8,\n\
|
||||
en_GB ...\n\
|
||||
--install-langs=\"en_US.utf8\"\n\
|
||||
installs only en_US.utf8.\n\
|
||||
--install-langs=\"ko\"\n\
|
||||
installs ko_KR, ko_KR.euckr,\n\
|
||||
ko_KR.utf8 but *not* kok_IN\n\
|
||||
because \"ko\" does not contain\n\
|
||||
\"_\" and it is silently added\n\
|
||||
--install-langs\"ko:kok\"\n\
|
||||
installs ko_KR, ko_KR.euckr,\n\
|
||||
ko_KR.utf8, kok_IN, and\n\
|
||||
kok_IN.utf8.\n\
|
||||
--install-langs=\"POSIX\" will\n\
|
||||
installs *no* locales at all\n\
|
||||
because POSIX matches none of\n\
|
||||
the locales. Actually, any string\n\
|
||||
matching nothing will do that.\n\
|
||||
POSIX and C will always be\n\
|
||||
available because they are\n\
|
||||
builtin.\n\
|
||||
Aliases are installed as well,\n\
|
||||
i.e. --install-langs=\"de\"\n\
|
||||
will install not only every locale starting with\n\
|
||||
\"de\" but also the aliases \"deutsch\"\n\
|
||||
and and \"german\" although the latter does not\n\
|
||||
start with \"de\".\n\
|
||||
\n\
|
||||
If the arguments TEMPLATE-FILE and ARCHIVE-FILE are not given the locations\n\
|
||||
where the glibc used expects these files are used by default.\n\
|
||||
");
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
char path[4096];
|
||||
DIR *dirp;
|
||||
struct dirent64 *d;
|
||||
struct stat64 st;
|
||||
char *list[16384], *primary;
|
||||
char *lang;
|
||||
int install_langs_count = 0;
|
||||
int i;
|
||||
char *install_langs_arg, *ila_start;
|
||||
char **install_langs_list;
|
||||
unsigned int cnt = 0;
|
||||
struct locarhandle tmpl_ah;
|
||||
char *new_locar_fname = NULL;
|
||||
size_t loc_path_len = strlen (loc_path);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int c;
|
||||
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{"install-langs", required_argument, 0, 'l'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
/* getopt_long stores the option index here. */
|
||||
int option_index = 0;
|
||||
|
||||
c = getopt_long (argc, argv, "vhl:",
|
||||
long_options, &option_index);
|
||||
|
||||
/* Detect the end of the options. */
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
printf ("unknown option %s", long_options[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
usage ();
|
||||
exit (1);
|
||||
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
be_quiet = 0;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
usage ();
|
||||
exit (0);
|
||||
|
||||
case 'l':
|
||||
install_langs_arg = ila_start = strdup (optarg);
|
||||
/* If the argument to --install-lang is "all", do
|
||||
not limit the list of languages to install and install
|
||||
them all. We do not support installing a single locale
|
||||
called "all". */
|
||||
#define MAGIC_INSTALL_ALL "all"
|
||||
if (install_langs_arg != NULL
|
||||
&& install_langs_arg[0] != '\0'
|
||||
&& !(strncmp(install_langs_arg, MAGIC_INSTALL_ALL,
|
||||
strlen(MAGIC_INSTALL_ALL)) == 0
|
||||
&& strlen (install_langs_arg) == 3))
|
||||
{
|
||||
/* Count the number of languages we will install. */
|
||||
while (true)
|
||||
{
|
||||
lang = strtok(install_langs_arg, ":;,");
|
||||
if (lang == NULL)
|
||||
break;
|
||||
install_langs_count++;
|
||||
install_langs_arg = NULL;
|
||||
}
|
||||
free (ila_start);
|
||||
/* Copy the list. */
|
||||
install_langs_list = (char **)xmalloc (sizeof(char *) * install_langs_count);
|
||||
install_langs_arg = ila_start = strdup (optarg);
|
||||
install_langs_count = 0;
|
||||
while (true)
|
||||
{
|
||||
lang = strtok(install_langs_arg, ":;,");
|
||||
if (lang == NULL)
|
||||
break;
|
||||
install_langs_list[install_langs_count] = lang;
|
||||
install_langs_count++;
|
||||
install_langs_arg = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
/* getopt_long already printed an error message. */
|
||||
usage ();
|
||||
exit (0);
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
tmpl_ah.fname = NULL;
|
||||
if (optind < argc)
|
||||
tmpl_ah.fname = argv[optind];
|
||||
if (optind + 1 < argc)
|
||||
new_locar_fname = argv[optind + 1];
|
||||
if (verbose)
|
||||
{
|
||||
if (tmpl_ah.fname)
|
||||
printf("input archive file specified on command line: %s\n",
|
||||
tmpl_ah.fname);
|
||||
else
|
||||
printf("using default input archive file.\n");
|
||||
if (new_locar_fname)
|
||||
printf("output archive file specified on command line: %s\n",
|
||||
new_locar_fname);
|
||||
else
|
||||
printf("using default output archive file.\n");
|
||||
}
|
||||
|
||||
dirp = opendir (loc_path);
|
||||
if (dirp == NULL)
|
||||
error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path);
|
||||
|
||||
open_tmpl_archive (&tmpl_ah);
|
||||
|
||||
if (new_locar_fname)
|
||||
unlink (new_locar_fname);
|
||||
else
|
||||
unlink (locar_file);
|
||||
primary = getenv ("LC_ALL");
|
||||
if (primary == NULL)
|
||||
primary = getenv ("LANG");
|
||||
if (primary != NULL)
|
||||
{
|
||||
if (strncmp (primary, "ja", 2) != 0
|
||||
&& strncmp (primary, "ko", 2) != 0
|
||||
&& strncmp (primary, "zh", 2) != 0)
|
||||
{
|
||||
char *ptr = malloc (strlen (primary) + strlen (".utf8") + 1), *p, *q;
|
||||
/* This leads to invalid locales sometimes:
|
||||
de_DE.iso885915@euro -> de_DE.utf8@euro */
|
||||
if (ptr != NULL)
|
||||
{
|
||||
p = ptr;
|
||||
q = primary;
|
||||
while (*q && *q != '.' && *q != '@')
|
||||
*p++ = *q++;
|
||||
if (*q == '.')
|
||||
while (*q && *q != '@')
|
||||
q++;
|
||||
p = stpcpy (p, ".utf8");
|
||||
strcpy (p, q);
|
||||
primary = ptr;
|
||||
}
|
||||
else
|
||||
primary = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy (path, loc_path, loc_path_len);
|
||||
|
||||
while ((d = readdir64 (dirp)) != NULL)
|
||||
{
|
||||
if (strcmp (d->d_name, ".") == 0 || strcmp (d->d_name, "..") == 0)
|
||||
continue;
|
||||
if (strchr (d->d_name, '_') == NULL)
|
||||
continue;
|
||||
|
||||
size_t d_name_len = strlen (d->d_name);
|
||||
if (loc_path_len + d_name_len + 1 > sizeof (path))
|
||||
{
|
||||
error (0, 0, "too long filename \"%s\"", d->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy (path + loc_path_len, d->d_name, d_name_len + 1);
|
||||
if (stat64 (path, &st) < 0)
|
||||
{
|
||||
error (0, errno, "cannot stat \"%s\"", path);
|
||||
continue;
|
||||
}
|
||||
if (! S_ISDIR (st.st_mode))
|
||||
continue;
|
||||
if (cnt == 16384)
|
||||
{
|
||||
error (0, 0, "too many directories in \"%s\"", loc_path);
|
||||
break;
|
||||
}
|
||||
list[cnt] = strdup (path);
|
||||
if (list[cnt] == NULL)
|
||||
{
|
||||
error (0, errno, "cannot add file to list \"%s\"", path);
|
||||
continue;
|
||||
}
|
||||
if (primary != NULL && cnt > 0 && strcmp (primary, d->d_name) == 0)
|
||||
{
|
||||
char *p = list[0];
|
||||
list[0] = list[cnt];
|
||||
list[cnt] = p;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
closedir (dirp);
|
||||
/* Store the archive to the file specified as the second argument on the
|
||||
command line or the default locale archive. */
|
||||
fill_archive (&tmpl_ah, new_locar_fname,
|
||||
install_langs_count, install_langs_list,
|
||||
cnt, list, primary);
|
||||
close_archive (&tmpl_ah);
|
||||
truncate (tmpl_file, 0);
|
||||
if (install_langs_count > 0)
|
||||
{
|
||||
free (ila_start);
|
||||
free (install_langs_list);
|
||||
}
|
||||
char *tz_argv[] = { "/usr/sbin/tzdata-update", NULL };
|
||||
execve (tz_argv[0], (char *const *)tz_argv, (char *const *)&tz_argv[1]);
|
||||
exit (0);
|
||||
}
|
@ -5,30 +5,10 @@ component="glibc"
|
||||
rm -f series.new
|
||||
extra_args="--fuzz=0"
|
||||
count=0
|
||||
# Filter out the patches, and use `_` as our pseudo-IFS to prevent expansion.
|
||||
for i in `grep '^%patch' glibc.spec | sed -e 's,%patch,,g' -e 's, ,_,g'`; do
|
||||
# Split the patch into number and arguments.
|
||||
# 1 - Patch number.
|
||||
# 2-N - Patch arguments.
|
||||
# Get back our elements by undoing pseudo-IFS change.
|
||||
elements=(`echo $i | sed -e 's,_, ,g'`)
|
||||
num=${elements[0]}
|
||||
args=${elements[@]:1}
|
||||
# Find the next patch that applies in order and write it out.
|
||||
# This way we transform the patch # list into a patch file list in order.
|
||||
grep "Patch${num}: " glibc.spec \
|
||||
| sed -e 's,Patch.*: ,,g' -e "s,\$, ${args[@]} ${extra_args},g" \
|
||||
| sed -e "s,%{name},${component},g" \
|
||||
>> series.new
|
||||
((count++))
|
||||
done
|
||||
# Double check we processed the correct number of patches.
|
||||
fcount=`wc -l series.new | sed -e 's, .*$,,g'`
|
||||
if [ $fcount -ne $count ]; then
|
||||
echo "Error! Processed patch count doesn't match spec file count ($fcount != $count)."
|
||||
exit 1
|
||||
fi
|
||||
# Transform patches into series file.
|
||||
grep '^Patch.*:' glibc.spec | sed -e 's,Patch.*: ,,g' > series.new
|
||||
count=`wc -l series.new | sed -e 's, .*$,,g'`
|
||||
echo "Processed $count patches."
|
||||
mv series.new series
|
||||
echo "Generated quilt ./series file, please commit."
|
||||
echo "Generated quilt ./series file. Please do not commit."
|
||||
exit 0
|
||||
|
@ -1,567 +0,0 @@
|
||||
CVE-2015-7547
|
||||
|
||||
2016-02-15 Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
[BZ #18665]
|
||||
* resolv/nss_dns/dns-host.c (gaih_getanswer_slice): Always set
|
||||
*herrno_p.
|
||||
(gaih_getanswer): Document functional behviour. Return tryagain
|
||||
if any result is tryagain.
|
||||
* resolv/res_query.c (__libc_res_nsearch): Set buffer size to zero
|
||||
when freed.
|
||||
* resolv/res_send.c: Add copyright text.
|
||||
(__libc_res_nsend): Document that MAXPACKET is expected.
|
||||
(send_vc): Document. Remove buffer reuse.
|
||||
(send_dg): Document. Remove buffer reuse. Set *thisanssizp to set the
|
||||
size of the buffer. Add Dprint for truncated UDP buffer.
|
||||
|
||||
Index: glibc-2.22-719-g1233be7/resolv/nss_dns/dns-host.c
|
||||
===================================================================
|
||||
--- glibc-2.22-719-g1233be7.orig/resolv/nss_dns/dns-host.c
|
||||
+++ glibc-2.22-719-g1233be7/resolv/nss_dns/dns-host.c
|
||||
@@ -1041,7 +1041,10 @@ gaih_getanswer_slice (const querybuf *an
|
||||
int h_namelen = 0;
|
||||
|
||||
if (ancount == 0)
|
||||
- return NSS_STATUS_NOTFOUND;
|
||||
+ {
|
||||
+ *h_errnop = HOST_NOT_FOUND;
|
||||
+ return NSS_STATUS_NOTFOUND;
|
||||
+ }
|
||||
|
||||
while (ancount-- > 0 && cp < end_of_message && had_error == 0)
|
||||
{
|
||||
@@ -1218,7 +1221,14 @@ gaih_getanswer_slice (const querybuf *an
|
||||
/* Special case here: if the resolver sent a result but it only
|
||||
contains a CNAME while we are looking for a T_A or T_AAAA record,
|
||||
we fail with NOTFOUND instead of TRYAGAIN. */
|
||||
- return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
|
||||
+ if (canon != NULL)
|
||||
+ {
|
||||
+ *h_errnop = HOST_NOT_FOUND;
|
||||
+ return NSS_STATUS_NOTFOUND;
|
||||
+ }
|
||||
+
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
|
||||
@@ -1232,11 +1242,101 @@ gaih_getanswer (const querybuf *answer1,
|
||||
|
||||
enum nss_status status = NSS_STATUS_NOTFOUND;
|
||||
|
||||
+ /* Combining the NSS status of two distinct queries requires some
|
||||
+ compromise and attention to symmetry (A or AAAA queries can be
|
||||
+ returned in any order). What follows is a breakdown of how this
|
||||
+ code is expected to work and why. We discuss only SUCCESS,
|
||||
+ TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
|
||||
+ that apply (though RETURN and MERGE exist). We make a distinction
|
||||
+ between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
|
||||
+ A recoverable TRYAGAIN is almost always due to buffer size issues
|
||||
+ and returns ERANGE in errno and the caller is expected to retry
|
||||
+ with a larger buffer.
|
||||
+
|
||||
+ Lastly, you may be tempted to make significant changes to the
|
||||
+ conditions in this code to bring about symmetry between responses.
|
||||
+ Please don't change anything without due consideration for
|
||||
+ expected application behaviour. Some of the synthesized responses
|
||||
+ aren't very well thought out and sometimes appear to imply that
|
||||
+ IPv4 responses are always answer 1, and IPv6 responses are always
|
||||
+ answer 2, but that's not true (see the implemetnation of send_dg
|
||||
+ and send_vc to see response can arrive in any order, particlarly
|
||||
+ for UDP). However, we expect it holds roughly enough of the time
|
||||
+ that this code works, but certainly needs to be fixed to make this
|
||||
+ a more robust implementation.
|
||||
+
|
||||
+ ----------------------------------------------
|
||||
+ | Answer 1 Status / | Synthesized | Reason |
|
||||
+ | Answer 2 Status | Status | |
|
||||
+ |--------------------------------------------|
|
||||
+ | SUCCESS/SUCCESS | SUCCESS | [1] |
|
||||
+ | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
|
||||
+ | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
|
||||
+ | SUCCESS/NOTFOUND | SUCCESS | [1] |
|
||||
+ | SUCCESS/UNAVAIL | SUCCESS | [1] |
|
||||
+ | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
|
||||
+ | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
|
||||
+ | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
|
||||
+ | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
|
||||
+ | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
|
||||
+ | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
|
||||
+ | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
|
||||
+ | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
|
||||
+ | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
|
||||
+ | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
|
||||
+ | NOTFOUND/SUCCESS | SUCCESS | [3] |
|
||||
+ | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
|
||||
+ | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
|
||||
+ | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
|
||||
+ | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
|
||||
+ | UNAVAIL/SUCCESS | UNAVAIL | [4] |
|
||||
+ | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
|
||||
+ | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
|
||||
+ | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
|
||||
+ | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
|
||||
+ ----------------------------------------------
|
||||
+
|
||||
+ [1] If the first response is a success we return success.
|
||||
+ This ignores the state of the second answer and in fact
|
||||
+ incorrectly sets errno and h_errno to that of the second
|
||||
+ answer. However because the response is a success we ignore
|
||||
+ *errnop and *h_errnop (though that means you touched errno on
|
||||
+ success). We are being conservative here and returning the
|
||||
+ likely IPv4 response in the first answer as a success.
|
||||
+
|
||||
+ [2] If the first response is a recoverable TRYAGAIN we return
|
||||
+ that instead of looking at the second response. The
|
||||
+ expectation here is that we have failed to get an IPv4 response
|
||||
+ and should retry both queries.
|
||||
+
|
||||
+ [3] If the first response was not a SUCCESS and the second
|
||||
+ response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
|
||||
+ or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
|
||||
+ result from the second response, otherwise the first responses
|
||||
+ status is used. Again we have some odd side-effects when the
|
||||
+ second response is NOTFOUND because we overwrite *errnop and
|
||||
+ *h_errnop that means that a first answer of NOTFOUND might see
|
||||
+ its *errnop and *h_errnop values altered. Whether it matters
|
||||
+ in practice that a first response NOTFOUND has the wrong
|
||||
+ *errnop and *h_errnop is undecided.
|
||||
+
|
||||
+ [4] If the first response is UNAVAIL we return that instead of
|
||||
+ looking at the second response. The expectation here is that
|
||||
+ it will have failed similarly e.g. configuration failure.
|
||||
+
|
||||
+ [5] Testing this code is complicated by the fact that truncated
|
||||
+ second response buffers might be returned as SUCCESS if the
|
||||
+ first answer is a SUCCESS. To fix this we add symmetry to
|
||||
+ TRYAGAIN with the second response. If the second response
|
||||
+ is a recoverable error we now return TRYAGIN even if the first
|
||||
+ response was SUCCESS. */
|
||||
+
|
||||
if (anslen1 > 0)
|
||||
status = gaih_getanswer_slice(answer1, anslen1, qname,
|
||||
&pat, &buffer, &buflen,
|
||||
errnop, h_errnop, ttlp,
|
||||
&first);
|
||||
+
|
||||
if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
|
||||
|| (status == NSS_STATUS_TRYAGAIN
|
||||
/* We want to look at the second answer in case of an
|
||||
@@ -1252,8 +1352,15 @@ gaih_getanswer (const querybuf *answer1,
|
||||
&pat, &buffer, &buflen,
|
||||
errnop, h_errnop, ttlp,
|
||||
&first);
|
||||
+ /* Use the second response status in some cases. */
|
||||
if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
|
||||
status = status2;
|
||||
+ /* Do not return a truncated second response (unless it was
|
||||
+ unavoidable e.g. unrecoverable TRYAGAIN). */
|
||||
+ if (status == NSS_STATUS_SUCCESS
|
||||
+ && (status2 == NSS_STATUS_TRYAGAIN
|
||||
+ && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
|
||||
+ status = NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
return status;
|
||||
Index: glibc-2.22-719-g1233be7/resolv/res_query.c
|
||||
===================================================================
|
||||
--- glibc-2.22-719-g1233be7.orig/resolv/res_query.c
|
||||
+++ glibc-2.22-719-g1233be7/resolv/res_query.c
|
||||
@@ -396,6 +396,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
+ *nanswerp2 = 0;
|
||||
*answerp2_malloced = 0;
|
||||
}
|
||||
}
|
||||
@@ -447,6 +448,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
+ *nanswerp2 = 0;
|
||||
*answerp2_malloced = 0;
|
||||
}
|
||||
|
||||
@@ -521,6 +523,7 @@ __libc_res_nsearch(res_state statp,
|
||||
{
|
||||
free (*answerp2);
|
||||
*answerp2 = NULL;
|
||||
+ *nanswerp2 = 0;
|
||||
*answerp2_malloced = 0;
|
||||
}
|
||||
if (saved_herrno != -1)
|
||||
Index: glibc-2.22-719-g1233be7/resolv/res_send.c
|
||||
===================================================================
|
||||
--- glibc-2.22-719-g1233be7.orig/resolv/res_send.c
|
||||
+++ glibc-2.22-719-g1233be7/resolv/res_send.c
|
||||
@@ -1,3 +1,20 @@
|
||||
+/* Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
/*
|
||||
* Copyright (c) 1985, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
@@ -353,6 +370,8 @@ __libc_res_nsend(res_state statp, const
|
||||
#ifdef USE_HOOKS
|
||||
if (__glibc_unlikely (statp->qhook || statp->rhook)) {
|
||||
if (anssiz < MAXPACKET && ansp) {
|
||||
+ /* Always allocate MAXPACKET, callers expect
|
||||
+ this specific size. */
|
||||
u_char *buf = malloc (MAXPACKET);
|
||||
if (buf == NULL)
|
||||
return (-1);
|
||||
@@ -652,6 +671,77 @@ libresolv_hidden_def (res_nsend)
|
||||
|
||||
/* Private */
|
||||
|
||||
+/* The send_vc function is responsible for sending a DNS query over TCP
|
||||
+ to the nameserver numbered NS from the res_state STATP i.e.
|
||||
+ EXT(statp).nssocks[ns]. The function supports sending both IPv4 and
|
||||
+ IPv6 queries at the same serially on the same socket.
|
||||
+
|
||||
+ Please note that for TCP there is no way to disable sending both
|
||||
+ queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP
|
||||
+ and sends the queries serially and waits for the result after each
|
||||
+ sent query. This implemetnation should be corrected to honour these
|
||||
+ options.
|
||||
+
|
||||
+ Please also note that for TCP we send both queries over the same
|
||||
+ socket one after another. This technically violates best practice
|
||||
+ since the server is allowed to read the first query, respond, and
|
||||
+ then close the socket (to service another client). If the server
|
||||
+ does this, then the remaining second query in the socket data buffer
|
||||
+ will cause the server to send the client an RST which will arrive
|
||||
+ asynchronously and the client's OS will likely tear down the socket
|
||||
+ receive buffer resulting in a potentially short read and lost
|
||||
+ response data. This will force the client to retry the query again,
|
||||
+ and this process may repeat until all servers and connection resets
|
||||
+ are exhausted and then the query will fail. It's not known if this
|
||||
+ happens with any frequency in real DNS server implementations. This
|
||||
+ implementation should be corrected to use two sockets by default for
|
||||
+ parallel queries.
|
||||
+
|
||||
+ The query stored in BUF of BUFLEN length is sent first followed by
|
||||
+ the query stored in BUF2 of BUFLEN2 length. Queries are sent
|
||||
+ serially on the same socket.
|
||||
+
|
||||
+ Answers to the query are stored firstly in *ANSP up to a max of
|
||||
+ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
|
||||
+ is non-NULL (to indicate that modifying the answer buffer is allowed)
|
||||
+ then malloc is used to allocate a new response buffer and ANSCP and
|
||||
+ ANSP will both point to the new buffer. If more than *ANSSIZP bytes
|
||||
+ are needed but ANSCP is NULL, then as much of the response as
|
||||
+ possible is read into the buffer, but the results will be truncated.
|
||||
+ When truncation happens because of a small answer buffer the DNS
|
||||
+ packets header feild TC will bet set to 1, indicating a truncated
|
||||
+ message and the rest of the socket data will be read and discarded.
|
||||
+
|
||||
+ Answers to the query are stored secondly in *ANSP2 up to a max of
|
||||
+ *ANSSIZP2 bytes, with the actual response length stored in
|
||||
+ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
|
||||
+ is non-NULL (required for a second query) then malloc is used to
|
||||
+ allocate a new response buffer, *ANSSIZP2 is set to the new buffer
|
||||
+ size and *ANSP2_MALLOCED is set to 1.
|
||||
+
|
||||
+ The ANSP2_MALLOCED argument will eventually be removed as the
|
||||
+ change in buffer pointer can be used to detect the buffer has
|
||||
+ changed and that the caller should use free on the new buffer.
|
||||
+
|
||||
+ Note that the answers may arrive in any order from the server and
|
||||
+ therefore the first and second answer buffers may not correspond to
|
||||
+ the first and second queries.
|
||||
+
|
||||
+ It is not supported to call this function with a non-NULL ANSP2
|
||||
+ but a NULL ANSCP. Put another way, you can call send_vc with a
|
||||
+ single unmodifiable buffer or two modifiable buffers, but no other
|
||||
+ combination is supported.
|
||||
+
|
||||
+ It is the caller's responsibility to free the malloc allocated
|
||||
+ buffers by detecting that the pointers have changed from their
|
||||
+ original values i.e. *ANSCP or *ANSP2 has changed.
|
||||
+
|
||||
+ If errors are encountered then *TERRNO is set to an appropriate
|
||||
+ errno value and a zero result is returned for a recoverable error,
|
||||
+ and a less-than zero result is returned for a non-recoverable error.
|
||||
+
|
||||
+ If no errors are encountered then *TERRNO is left unmodified and
|
||||
+ a the length of the first response in bytes is returned. */
|
||||
static int
|
||||
send_vc(res_state statp,
|
||||
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
|
||||
@@ -661,11 +751,7 @@ send_vc(res_state statp,
|
||||
{
|
||||
const HEADER *hp = (HEADER *) buf;
|
||||
const HEADER *hp2 = (HEADER *) buf2;
|
||||
- u_char *ans = *ansp;
|
||||
- int orig_anssizp = *anssizp;
|
||||
- // XXX REMOVE
|
||||
- // int anssiz = *anssizp;
|
||||
- HEADER *anhp = (HEADER *) ans;
|
||||
+ HEADER *anhp = (HEADER *) *ansp;
|
||||
struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
|
||||
int truncating, connreset, n;
|
||||
/* On some architectures compiler might emit a warning indicating
|
||||
@@ -754,6 +840,8 @@ send_vc(res_state statp,
|
||||
* Receive length & response
|
||||
*/
|
||||
int recvresp1 = 0;
|
||||
+ /* Skip the second response if there is no second query.
|
||||
+ To do that we mark the second response as received. */
|
||||
int recvresp2 = buf2 == NULL;
|
||||
uint16_t rlen16;
|
||||
read_len:
|
||||
@@ -790,36 +878,14 @@ send_vc(res_state statp,
|
||||
u_char **thisansp;
|
||||
int *thisresplenp;
|
||||
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
|
||||
+ /* We have not received any responses
|
||||
+ yet or we only have one response to
|
||||
+ receive. */
|
||||
thisanssizp = anssizp;
|
||||
thisansp = anscp ?: ansp;
|
||||
assert (anscp != NULL || ansp2 == NULL);
|
||||
thisresplenp = &resplen;
|
||||
} else {
|
||||
- if (*anssizp != MAXPACKET) {
|
||||
- /* No buffer allocated for the first
|
||||
- reply. We can try to use the rest
|
||||
- of the user-provided buffer. */
|
||||
- DIAG_PUSH_NEEDS_COMMENT;
|
||||
- DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
|
||||
-#if _STRING_ARCH_unaligned
|
||||
- *anssizp2 = orig_anssizp - resplen;
|
||||
- *ansp2 = *ansp + resplen;
|
||||
-#else
|
||||
- int aligned_resplen
|
||||
- = ((resplen + __alignof__ (HEADER) - 1)
|
||||
- & ~(__alignof__ (HEADER) - 1));
|
||||
- *anssizp2 = orig_anssizp - aligned_resplen;
|
||||
- *ansp2 = *ansp + aligned_resplen;
|
||||
-#endif
|
||||
- DIAG_POP_NEEDS_COMMENT;
|
||||
- } else {
|
||||
- /* The first reply did not fit into the
|
||||
- user-provided buffer. Maybe the second
|
||||
- answer will. */
|
||||
- *anssizp2 = orig_anssizp;
|
||||
- *ansp2 = *ansp;
|
||||
- }
|
||||
-
|
||||
thisanssizp = anssizp2;
|
||||
thisansp = ansp2;
|
||||
thisresplenp = resplen2;
|
||||
@@ -827,10 +893,14 @@ send_vc(res_state statp,
|
||||
anhp = (HEADER *) *thisansp;
|
||||
|
||||
*thisresplenp = rlen;
|
||||
- if (rlen > *thisanssizp) {
|
||||
- /* Yes, we test ANSCP here. If we have two buffers
|
||||
- both will be allocatable. */
|
||||
- if (__glibc_likely (anscp != NULL)) {
|
||||
+ /* Is the answer buffer too small? */
|
||||
+ if (*thisanssizp < rlen) {
|
||||
+ /* If the current buffer is not the the static
|
||||
+ user-supplied buffer then we can reallocate
|
||||
+ it. */
|
||||
+ if (thisansp != NULL && thisansp != ansp) {
|
||||
+ /* Always allocate MAXPACKET, callers expect
|
||||
+ this specific size. */
|
||||
u_char *newp = malloc (MAXPACKET);
|
||||
if (newp == NULL) {
|
||||
*terrno = ENOMEM;
|
||||
@@ -842,6 +912,9 @@ send_vc(res_state statp,
|
||||
if (thisansp == ansp2)
|
||||
*ansp2_malloced = 1;
|
||||
anhp = (HEADER *) newp;
|
||||
+ /* A uint16_t can't be larger than MAXPACKET
|
||||
+ thus it's safe to allocate MAXPACKET but
|
||||
+ read RLEN bytes instead. */
|
||||
len = rlen;
|
||||
} else {
|
||||
Dprint(statp->options & RES_DEBUG,
|
||||
@@ -972,6 +1045,66 @@ reopen (res_state statp, int *terrno, in
|
||||
return 1;
|
||||
}
|
||||
|
||||
+/* The send_dg function is responsible for sending a DNS query over UDP
|
||||
+ to the nameserver numbered NS from the res_state STATP i.e.
|
||||
+ EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries
|
||||
+ along with the ability to send the query in parallel for both stacks
|
||||
+ (default) or serially (RES_SINGLKUP). It also supports serial lookup
|
||||
+ with a close and reopen of the socket used to talk to the server
|
||||
+ (RES_SNGLKUPREOP) to work around broken name servers.
|
||||
+
|
||||
+ The query stored in BUF of BUFLEN length is sent first followed by
|
||||
+ the query stored in BUF2 of BUFLEN2 length. Queries are sent
|
||||
+ in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP).
|
||||
+
|
||||
+ Answers to the query are stored firstly in *ANSP up to a max of
|
||||
+ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
|
||||
+ is non-NULL (to indicate that modifying the answer buffer is allowed)
|
||||
+ then malloc is used to allocate a new response buffer and ANSCP and
|
||||
+ ANSP will both point to the new buffer. If more than *ANSSIZP bytes
|
||||
+ are needed but ANSCP is NULL, then as much of the response as
|
||||
+ possible is read into the buffer, but the results will be truncated.
|
||||
+ When truncation happens because of a small answer buffer the DNS
|
||||
+ packets header feild TC will bet set to 1, indicating a truncated
|
||||
+ message, while the rest of the UDP packet is discarded.
|
||||
+
|
||||
+ Answers to the query are stored secondly in *ANSP2 up to a max of
|
||||
+ *ANSSIZP2 bytes, with the actual response length stored in
|
||||
+ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
|
||||
+ is non-NULL (required for a second query) then malloc is used to
|
||||
+ allocate a new response buffer, *ANSSIZP2 is set to the new buffer
|
||||
+ size and *ANSP2_MALLOCED is set to 1.
|
||||
+
|
||||
+ The ANSP2_MALLOCED argument will eventually be removed as the
|
||||
+ change in buffer pointer can be used to detect the buffer has
|
||||
+ changed and that the caller should use free on the new buffer.
|
||||
+
|
||||
+ Note that the answers may arrive in any order from the server and
|
||||
+ therefore the first and second answer buffers may not correspond to
|
||||
+ the first and second queries.
|
||||
+
|
||||
+ It is not supported to call this function with a non-NULL ANSP2
|
||||
+ but a NULL ANSCP. Put another way, you can call send_vc with a
|
||||
+ single unmodifiable buffer or two modifiable buffers, but no other
|
||||
+ combination is supported.
|
||||
+
|
||||
+ It is the caller's responsibility to free the malloc allocated
|
||||
+ buffers by detecting that the pointers have changed from their
|
||||
+ original values i.e. *ANSCP or *ANSP2 has changed.
|
||||
+
|
||||
+ If an answer is truncated because of UDP datagram DNS limits then
|
||||
+ *V_CIRCUIT is set to 1 and the return value non-zero to indicate to
|
||||
+ the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1
|
||||
+ if any progress was made reading a response from the nameserver and
|
||||
+ is used by the caller to distinguish between ECONNREFUSED and
|
||||
+ ETIMEDOUT (the latter if *GOTSOMEWHERE is 1).
|
||||
+
|
||||
+ If errors are encountered then *TERRNO is set to an appropriate
|
||||
+ errno value and a zero result is returned for a recoverable error,
|
||||
+ and a less-than zero result is returned for a non-recoverable error.
|
||||
+
|
||||
+ If no errors are encountered then *TERRNO is left unmodified and
|
||||
+ a the length of the first response in bytes is returned. */
|
||||
static int
|
||||
send_dg(res_state statp,
|
||||
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
|
||||
@@ -981,8 +1114,6 @@ send_dg(res_state statp,
|
||||
{
|
||||
const HEADER *hp = (HEADER *) buf;
|
||||
const HEADER *hp2 = (HEADER *) buf2;
|
||||
- u_char *ans = *ansp;
|
||||
- int orig_anssizp = *anssizp;
|
||||
struct timespec now, timeout, finish;
|
||||
struct pollfd pfd[1];
|
||||
int ptimeout;
|
||||
@@ -1015,6 +1146,8 @@ send_dg(res_state statp,
|
||||
int need_recompute = 0;
|
||||
int nwritten = 0;
|
||||
int recvresp1 = 0;
|
||||
+ /* Skip the second response if there is no second query.
|
||||
+ To do that we mark the second response as received. */
|
||||
int recvresp2 = buf2 == NULL;
|
||||
pfd[0].fd = EXT(statp).nssocks[ns];
|
||||
pfd[0].events = POLLOUT;
|
||||
@@ -1178,55 +1311,56 @@ send_dg(res_state statp,
|
||||
int *thisresplenp;
|
||||
|
||||
if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
|
||||
+ /* We have not received any responses
|
||||
+ yet or we only have one response to
|
||||
+ receive. */
|
||||
thisanssizp = anssizp;
|
||||
thisansp = anscp ?: ansp;
|
||||
assert (anscp != NULL || ansp2 == NULL);
|
||||
thisresplenp = &resplen;
|
||||
} else {
|
||||
- if (*anssizp != MAXPACKET) {
|
||||
- /* No buffer allocated for the first
|
||||
- reply. We can try to use the rest
|
||||
- of the user-provided buffer. */
|
||||
-#if _STRING_ARCH_unaligned
|
||||
- *anssizp2 = orig_anssizp - resplen;
|
||||
- *ansp2 = *ansp + resplen;
|
||||
-#else
|
||||
- int aligned_resplen
|
||||
- = ((resplen + __alignof__ (HEADER) - 1)
|
||||
- & ~(__alignof__ (HEADER) - 1));
|
||||
- *anssizp2 = orig_anssizp - aligned_resplen;
|
||||
- *ansp2 = *ansp + aligned_resplen;
|
||||
-#endif
|
||||
- } else {
|
||||
- /* The first reply did not fit into the
|
||||
- user-provided buffer. Maybe the second
|
||||
- answer will. */
|
||||
- *anssizp2 = orig_anssizp;
|
||||
- *ansp2 = *ansp;
|
||||
- }
|
||||
-
|
||||
thisanssizp = anssizp2;
|
||||
thisansp = ansp2;
|
||||
thisresplenp = resplen2;
|
||||
}
|
||||
|
||||
if (*thisanssizp < MAXPACKET
|
||||
- /* Yes, we test ANSCP here. If we have two buffers
|
||||
- both will be allocatable. */
|
||||
- && anscp
|
||||
+ /* If the current buffer is not the the static
|
||||
+ user-supplied buffer then we can reallocate
|
||||
+ it. */
|
||||
+ && (thisansp != NULL && thisansp != ansp)
|
||||
#ifdef FIONREAD
|
||||
+ /* Is the size too small? */
|
||||
&& (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
|
||||
|| *thisanssizp < *thisresplenp)
|
||||
#endif
|
||||
) {
|
||||
+ /* Always allocate MAXPACKET, callers expect
|
||||
+ this specific size. */
|
||||
u_char *newp = malloc (MAXPACKET);
|
||||
if (newp != NULL) {
|
||||
- *anssizp = MAXPACKET;
|
||||
- *thisansp = ans = newp;
|
||||
+ *thisanssizp = MAXPACKET;
|
||||
+ *thisansp = newp;
|
||||
if (thisansp == ansp2)
|
||||
*ansp2_malloced = 1;
|
||||
}
|
||||
}
|
||||
+ /* We could end up with truncation if anscp was NULL
|
||||
+ (not allowed to change caller's buffer) and the
|
||||
+ response buffer size is too small. This isn't a
|
||||
+ reliable way to detect truncation because the ioctl
|
||||
+ may be an inaccurate report of the UDP message size.
|
||||
+ Therefore we use this only to issue debug output.
|
||||
+ To do truncation accurately with UDP we need
|
||||
+ MSG_TRUNC which is only available on Linux. We
|
||||
+ can abstract out the Linux-specific feature in the
|
||||
+ future to detect truncation. */
|
||||
+ if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
|
||||
+ Dprint(statp->options & RES_DEBUG,
|
||||
+ (stdout, ";; response may be truncated (UDP)\n")
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
HEADER *anhp = (HEADER *) *thisansp;
|
||||
socklen_t fromlen = sizeof(struct sockaddr_in6);
|
||||
assert (sizeof(from) <= fromlen);
|
@ -1,13 +0,0 @@
|
||||
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
|
||||
index 997c860..50b37b0 100644
|
||||
--- a/sysdeps/aarch64/dl-machine.h
|
||||
+++ b/sysdeps/aarch64/dl-machine.h
|
||||
@@ -295,7 +295,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
|
||||
# ifndef SHARED
|
||||
CHECK_STATIC_TLS (map, sym_map);
|
||||
# else
|
||||
- if (!TRY_STATIC_TLS (map, sym_map))
|
||||
+ if (1)
|
||||
{
|
||||
td->arg = _dl_make_tlsdesc_dynamic
|
||||
(sym_map, sym->st_value + reloc->r_addend);
|
@ -1,33 +0,0 @@
|
||||
diff --git a/sysdeps/aarch64/dl-tlsdesc.S b/sysdeps/aarch64/dl-tlsdesc.S
|
||||
index ded5471..7d28496 100644
|
||||
--- a/sysdeps/aarch64/dl-tlsdesc.S
|
||||
+++ b/sysdeps/aarch64/dl-tlsdesc.S
|
||||
@@ -140,7 +140,7 @@ _dl_tlsdesc_undefweak:
|
||||
cfi_startproc
|
||||
.align 2
|
||||
_dl_tlsdesc_dynamic:
|
||||
-# define NSAVEXREGPAIRS 2
|
||||
+# define NSAVEXREGPAIRS 3
|
||||
stp x29, x30, [sp,#-(32+16*NSAVEXREGPAIRS)]!
|
||||
cfi_adjust_cfa_offset (32+16*NSAVEXREGPAIRS)
|
||||
mov x29, sp
|
||||
@@ -151,6 +151,10 @@ _dl_tlsdesc_dynamic:
|
||||
stp x1, x2, [sp, #32+16*0]
|
||||
stp x3, x4, [sp, #32+16*1]
|
||||
|
||||
+ /* Work around GCC rescheduling compares across tlsdesc calls. */
|
||||
+ mrs x30, nzcv
|
||||
+ stp xzr, x30, [sp, #32+16*2]
|
||||
+
|
||||
mrs x4, tpidr_el0
|
||||
/* The ldar here happens after the load from [x0] at the call site
|
||||
(that is generated by the compiler as part of the TLS access ABI),
|
||||
@@ -169,6 +173,8 @@ _dl_tlsdesc_dynamic:
|
||||
1:
|
||||
ldp x1, x2, [sp, #32+16*0]
|
||||
ldp x3, x4, [sp, #32+16*1]
|
||||
+ ldp xzr, x30, [sp, #32+16*2]
|
||||
+ msr nzcv, x30
|
||||
|
||||
ldp x29, x30, [sp], #(32+16*NSAVEXREGPAIRS)
|
||||
cfi_adjust_cfa_offset (-32-16*NSAVEXREGPAIRS)
|
@ -1,20 +0,0 @@
|
||||
diff -Nrup a/elf/dl-load.c b/elf/dl-load.c
|
||||
--- a/elf/dl-load.c 2012-06-06 13:07:41.727524312 -0600
|
||||
+++ b/elf/dl-load.c 2012-06-06 13:11:19.308681002 -0600
|
||||
@@ -2093,10 +2093,14 @@ _dl_map_object (struct link_map *loader,
|
||||
soname = ((const char *) D_PTR (l, l_info[DT_STRTAB])
|
||||
+ l->l_info[DT_SONAME]->d_un.d_val);
|
||||
if (strcmp (name, soname) != 0)
|
||||
- continue;
|
||||
+#ifdef __arm__
|
||||
+ if (strcmp (name, "ld-linux.so.3")
|
||||
+ || strcmp (soname, "ld-linux-armhf.so.3"))
|
||||
+#endif
|
||||
+ continue;
|
||||
|
||||
/* We have a match on a new name -- cache it. */
|
||||
- add_name_to_object (l, soname);
|
||||
+ add_name_to_object (l, name);
|
||||
l->l_soname_added = 1;
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index 710ce7e..3fe9e73 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -12,7 +12,7 @@ install:
|
||||
LC_ALL=C; export LC_ALL; \
|
||||
$(MAKE) -r PARALLELMFLAGS="$(PARALLELMFLAGS)" -C $(srcdir) objdir=`pwd` $@
|
||||
|
||||
-bench bench-clean:
|
||||
+bench bench-clean bench-build:
|
||||
$(MAKE) -C $(srcdir)/benchtests $(PARALLELMFLAGS) objdir=`pwd` $@
|
||||
|
||||
# Convenience target to rebuild ULPs for all math tests.
|
||||
diff --git a/Rules b/Rules
|
||||
index 4f9cdf3..42d0368 100644
|
||||
--- a/Rules
|
||||
+++ b/Rules
|
||||
@@ -83,7 +83,7 @@ common-generated += dummy.o dummy.c
|
||||
|
||||
# This makes all the auxiliary and test programs.
|
||||
|
||||
-.PHONY: others tests bench
|
||||
+.PHONY: others tests bench bench-build
|
||||
|
||||
ifeq ($(build-programs),yes)
|
||||
others: $(addprefix $(objpfx),$(others) $(sysdep-others) $(extra-objs))
|
||||
diff --git a/benchtests/Makefile b/benchtests/Makefile
|
||||
index fd3036d..7cbceaa 100644
|
||||
--- a/benchtests/Makefile
|
||||
+++ b/benchtests/Makefile
|
||||
@@ -103,6 +103,10 @@ bench-clean:
|
||||
|
||||
bench: $(timing-type) $(gen-locales) bench-set bench-func bench-malloc
|
||||
|
||||
+bench-build: bench-set-build bench-func-build
|
||||
+bench-set-build: $(binaries-benchset)
|
||||
+bench-func-build: $(binaries-bench) $(binaries-bench-malloc)
|
||||
+
|
||||
bench-set: $(binaries-benchset)
|
||||
for run in $^; do \
|
||||
echo "Running $${run}"; \
|
@ -1,140 +0,0 @@
|
||||
Index: glibc-2.22-193-g315267a/posix/bug-regex11.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/posix/bug-regex11.c
|
||||
+++ glibc-2.22-193-g315267a/posix/bug-regex11.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
/* Tests supposed to match. */
|
||||
struct
|
||||
@@ -119,6 +120,14 @@ main (void)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since n is limited to
|
||||
+ static nmatch which is limited to at most 5 (see tests above).
|
||||
+ This is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (n = 0; n < tests[i].nmatch; ++n)
|
||||
if (rm[n].rm_so != tests[i].rm[n].rm_so
|
||||
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
|
||||
@@ -130,6 +139,7 @@ main (void)
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
regfree (&re);
|
||||
}
|
||||
Index: glibc-2.22-193-g315267a/posix/bug-regex17.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/posix/bug-regex17.c
|
||||
+++ glibc-2.22-193-g315267a/posix/bug-regex17.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
/* Tests supposed to match. */
|
||||
struct
|
||||
@@ -87,6 +88,14 @@ do_test (void)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since n is limited to
|
||||
+ static nmatch which is limited to at most 5 (see tests above).
|
||||
+ This is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (n = 0; n < tests[i].nmatch; ++n)
|
||||
if (rm[n].rm_so != tests[i].rm[n].rm_so
|
||||
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
|
||||
@@ -98,6 +107,7 @@ do_test (void)
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
regfree (&re);
|
||||
}
|
||||
Index: glibc-2.22-193-g315267a/posix/bug-regex18.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/posix/bug-regex18.c
|
||||
+++ glibc-2.22-193-g315267a/posix/bug-regex18.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
/* Tests supposed to match. */
|
||||
struct
|
||||
@@ -80,6 +81,14 @@ main (void)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since n is limited to
|
||||
+ static nmatch which is limited to at most 5 (see tests above).
|
||||
+ This is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (n = 0; n < tests[i].nmatch; ++n)
|
||||
if (rm[n].rm_so != tests[i].rm[n].rm_so
|
||||
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
|
||||
@@ -91,6 +100,7 @@ main (void)
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
regfree (&re);
|
||||
}
|
||||
Index: glibc-2.22-193-g315267a/posix/bug-regex30.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/posix/bug-regex30.c
|
||||
+++ glibc-2.22-193-g315267a/posix/bug-regex30.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <locale.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
/* Tests supposed to match. */
|
||||
struct
|
||||
@@ -80,6 +81,14 @@ do_test (void)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since n is limited to
|
||||
+ static nmatch which is limited to at most 5 (see tests above).
|
||||
+ This is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (n = 0; n < tests[i].nmatch; ++n)
|
||||
if (rm[n].rm_so != tests[i].rm[n].rm_so
|
||||
|| rm[n].rm_eo != tests[i].rm[n].rm_eo)
|
||||
@@ -91,6 +100,7 @@ do_test (void)
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
regfree (&re);
|
||||
}
|
@ -1,3 +1,19 @@
|
||||
Short description: Add C.UTF-8 support.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-submitted
|
||||
|
||||
This patch needs to upstream as part of Carlos O'Donell
|
||||
<carlos@redhat.com>'s work on enabling upstream C.UTF-8 support. This
|
||||
work is currently blocked on cleaning up the test results to prove that
|
||||
full code-point sorting is working as intended.
|
||||
|
||||
Note that this patch does not provide full code-point sorting as
|
||||
expected.
|
||||
|
||||
This patch needs to upstream as soon as possible since it would be nice
|
||||
to have this in F29 and fixed.
|
||||
|
||||
From 2eda7b462b415105f5a05c1323372d4e39d46439 Mon Sep 17 00:00:00 2001
|
||||
From: Mike FABIAN <mfabian@redhat.com>
|
||||
Date: Mon, 10 Aug 2015 15:58:12 +0200
|
||||
@ -44,18 +60,18 @@ index 0000000..fdf460e
|
||||
+revision "1.0"
|
||||
+date "2015-08-10"
|
||||
+%
|
||||
+category "C:2015";LC_IDENTIFICATION
|
||||
+category "C:2015";LC_CTYPE
|
||||
+category "C:2015";LC_COLLATE
|
||||
+category "C:2015";LC_TIME
|
||||
+category "C:2015";LC_NUMERIC
|
||||
+category "C:2015";LC_MONETARY
|
||||
+category "C:2015";LC_MESSAGES
|
||||
+category "C:2015";LC_PAPER
|
||||
+category "C:2015";LC_NAME
|
||||
+category "C:2015";LC_ADDRESS
|
||||
+category "C:2015";LC_TELEPHONE
|
||||
+category "C:2015";LC_MEASUREMENT
|
||||
+category "i18n:2012";LC_IDENTIFICATION
|
||||
+category "i18n:2012";LC_CTYPE
|
||||
+category "i18n:2012";LC_COLLATE
|
||||
+category "i18n:2012";LC_TIME
|
||||
+category "i18n:2012";LC_NUMERIC
|
||||
+category "i18n:2012";LC_MONETARY
|
||||
+category "i18n:2012";LC_MESSAGES
|
||||
+category "i18n:2012";LC_PAPER
|
||||
+category "i18n:2012";LC_NAME
|
||||
+category "i18n:2012";LC_ADDRESS
|
||||
+category "i18n:2012";LC_TELEPHONE
|
||||
+category "i18n:2012";LC_MEASUREMENT
|
||||
+END LC_IDENTIFICATION
|
||||
+
|
||||
+LC_CTYPE
|
||||
@ -72,21 +88,21 @@ index 0000000..fdf460e
|
||||
+<U0000>
|
||||
+..
|
||||
+<UFFFF>
|
||||
+<U10000>
|
||||
+<U00010000>
|
||||
+..
|
||||
+<U1FFFF>
|
||||
+<U20000>
|
||||
+<U0001FFFF>
|
||||
+<U00020000>
|
||||
+..
|
||||
+<U2FFFF>
|
||||
+<UE0000>
|
||||
+<U0002FFFF>
|
||||
+<U000E0000>
|
||||
+..
|
||||
+<UEFFFF>
|
||||
+<UF0000>
|
||||
+<U000EFFFF>
|
||||
+<U000F0000>
|
||||
+..
|
||||
+<UFFFFF>
|
||||
+<U100000>
|
||||
+<U000FFFFF>
|
||||
+<U00100000>
|
||||
+..
|
||||
+<U10FFFF>
|
||||
+<U0010FFFF>
|
||||
+UNDEFINED
|
||||
+order_end
|
||||
+END LC_COLLATE
|
||||
|
@ -1,3 +1,12 @@
|
||||
Short description: Adjust CS_PATH return value.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
In Fedora we should return only /usr/bin because /bin is just a symlink
|
||||
to /usr/bin after MoveToUsr transition (which glibc has not really
|
||||
completed).
|
||||
|
||||
diff -pruN a/sysdeps/unix/confstr.h b/sysdeps/unix/confstr.h
|
||||
--- a/sysdeps/unix/confstr.h 2012-12-25 08:32:13.000000000 +0530
|
||||
+++ b/sysdeps/unix/confstr.h 2014-09-05 20:02:55.698275219 +0530
|
||||
|
@ -1,22 +0,0 @@
|
||||
diff -urN glibc-2.20.mod/sysdeps/unix/sysv/linux/x86/elision-conf.c glibc-2.20/sysdeps/unix/sysv/linux/x86/elision-conf.c
|
||||
--- glibc-2.20.mod/sysdeps/unix/sysv/linux/x86/elision-conf.c 2014-09-27 00:25:46.443462345 -0400
|
||||
+++ glibc-2.20/sysdeps/unix/sysv/linux/x86/elision-conf.c 2014-09-27 00:29:53.586615813 -0400
|
||||
@@ -62,12 +62,16 @@
|
||||
char **argv __attribute__ ((unused)),
|
||||
char **environ)
|
||||
{
|
||||
- __elision_available = HAS_CPU_FEATURE (RTM);
|
||||
#ifdef ENABLE_LOCK_ELISION
|
||||
+ __elision_available = HAS_CPU_FEATURE (RTM);
|
||||
__pthread_force_elision = __libc_enable_secure ? 0 : __elision_available;
|
||||
-#endif
|
||||
if (!HAS_CPU_FEATURE (RTM))
|
||||
__elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks */
|
||||
+#else
|
||||
+ __elision_available = 0;
|
||||
+ __pthread_force_elision = 0;
|
||||
+ __elision_aconf.retry_try_xbegin = 0;
|
||||
+#endif
|
||||
}
|
||||
|
||||
#ifdef SHARED
|
@ -1,32 +0,0 @@
|
||||
Index: glibc-2.22-193-g315267a/resolv/nss_dns/dns-host.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/resolv/nss_dns/dns-host.c
|
||||
+++ glibc-2.22-193-g315267a/resolv/nss_dns/dns-host.c
|
||||
@@ -79,6 +79,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <sys/syslog.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
#include "nsswitch.h"
|
||||
|
||||
@@ -561,10 +562,19 @@ addrsort (char **ap, int num)
|
||||
num = MAX_NR_ADDRS;
|
||||
for (i = 0; i < num; i++, p++)
|
||||
{
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since i is limited to
|
||||
+ _res.nsort which is limited to MAXRESOLVSORT. This
|
||||
+ is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (j = 0 ; (unsigned)j < _res.nsort; j++)
|
||||
if (_res.sort_list[j].addr.s_addr ==
|
||||
(((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
|
||||
break;
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
aval[i] = j;
|
||||
if (needsort == 0 && i > 0 && j < aval[i-1])
|
||||
needsort = i;
|
@ -1,30 +1,40 @@
|
||||
#
|
||||
# Upstream discussions:
|
||||
# https://sourceware.org/ml/libc-alpha/2014-02/msg00580.html
|
||||
#
|
||||
# Based on the following commit:
|
||||
#
|
||||
# From 16552c01a66633c9e412984d9d92616bd4e5303c Mon Sep 17 00:00:00 2001
|
||||
# From: Andreas Schwab <schwab@redhat.com>
|
||||
# Date: Fri, 11 Jun 2010 11:04:11 +0200
|
||||
# Subject: [PATCH] Properly set __libc_multiple_libcs
|
||||
#
|
||||
# * elf/rtld.c (_dl_starting_up): Always define.
|
||||
# (dl_main): Always set _dl_starting_up.
|
||||
# * elf/dl-support.c (_dl_starting_up): Always define.
|
||||
# * elf/dl-init.c (_dl_init): Always clear _dl_starting_up.
|
||||
#
|
||||
# ---
|
||||
# ChangeLog | 7 +++++++
|
||||
# elf/dl-init.c | 4 ----
|
||||
# elf/dl-support.c | 2 --
|
||||
# elf/rtld.c | 4 ----
|
||||
# 4 files changed, 7 insertions(+), 10 deletions(-)
|
||||
#
|
||||
diff -urN glibc-2.20-205-ga39208b/elf/dl-init.c glibc-2.20-205-ga39208b.mod/elf/dl-init.c
|
||||
--- glibc-2.20-205-ga39208b/elf/dl-init.c 2014-11-21 16:08:32.744913590 -0500
|
||||
+++ glibc-2.20-205-ga39208b.mod/elf/dl-init.c 2014-11-21 16:09:42.485708197 -0500
|
||||
@@ -119,8 +119,6 @@
|
||||
Short description: Cleanup use of _dl_starting_up.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: https://sourceware.org/ml/libc-alpha/2014-02/msg00589.html
|
||||
|
||||
Upstream discussions:
|
||||
https://sourceware.org/ml/libc-alpha/2014-02/msg00580.html
|
||||
|
||||
Based on the following commit:
|
||||
~~~
|
||||
From 16552c01a66633c9e412984d9d92616bd4e5303c Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Schwab <schwab@redhat.com>
|
||||
Date: Fri, 11 Jun 2010 11:04:11 +0200
|
||||
Subject: [PATCH] Properly set __libc_multiple_libcs
|
||||
|
||||
* elf/rtld.c (_dl_starting_up): Always define.
|
||||
(dl_main): Always set _dl_starting_up.
|
||||
* elf/dl-support.c (_dl_starting_up): Always define.
|
||||
* elf/dl-init.c (_dl_init): Always clear _dl_starting_up.
|
||||
|
||||
---
|
||||
ChangeLog | 7 +++++++
|
||||
elf/dl-init.c | 4 ----
|
||||
elf/dl-support.c | 2 --
|
||||
elf/rtld.c | 4 ----
|
||||
4 files changed, 7 insertions(+), 10 deletions(-)
|
||||
~~~
|
||||
|
||||
This patch needs to go upstream to get cleaned up, but has always involed
|
||||
analysis of the GNU/Hurd parts of the change and that stalled out, but
|
||||
perhaps with build-many-glibcs we can now test these changes more easily.
|
||||
|
||||
Index: b/elf/dl-init.c
|
||||
===================================================================
|
||||
--- a/elf/dl-init.c
|
||||
+++ b/elf/dl-init.c
|
||||
@@ -119,8 +119,6 @@ _dl_init (struct link_map *main_map, int
|
||||
while (i-- > 0)
|
||||
call_init (main_map->l_initfini[i], argc, argv, env);
|
||||
|
||||
@ -33,10 +43,11 @@ diff -urN glibc-2.20-205-ga39208b/elf/dl-init.c glibc-2.20-205-ga39208b.mod/elf/
|
||||
_dl_starting_up = 0;
|
||||
-#endif
|
||||
}
|
||||
diff -urN glibc-2.20-205-ga39208b/elf/dl-support.c glibc-2.20-205-ga39208b.mod/elf/dl-support.c
|
||||
--- glibc-2.20-205-ga39208b/elf/dl-support.c 2014-11-19 14:35:03.000000000 -0500
|
||||
+++ glibc-2.20-205-ga39208b.mod/elf/dl-support.c 2014-11-21 16:09:54.829671843 -0500
|
||||
@@ -118,10 +118,8 @@
|
||||
Index: b/elf/dl-support.c
|
||||
===================================================================
|
||||
--- a/elf/dl-support.c
|
||||
+++ b/elf/dl-support.c
|
||||
@@ -117,10 +117,8 @@ struct r_scope_elem _dl_initial_searchli
|
||||
.r_nlist = 1,
|
||||
};
|
||||
|
||||
@ -47,18 +58,19 @@ diff -urN glibc-2.20-205-ga39208b/elf/dl-support.c glibc-2.20-205-ga39208b.mod/e
|
||||
|
||||
/* Random data provided by the kernel. */
|
||||
void *_dl_random;
|
||||
diff -urN glibc-2.20-205-ga39208b/elf/rtld.c glibc-2.20-205-ga39208b.mod/elf/rtld.c
|
||||
--- glibc-2.20-205-ga39208b/elf/rtld.c 2014-11-21 16:08:32.745913587 -0500
|
||||
+++ glibc-2.20-205-ga39208b.mod/elf/rtld.c 2014-11-21 16:09:05.614816785 -0500
|
||||
@@ -107,7 +107,6 @@
|
||||
struct audit_list *next;
|
||||
} *audit_list;
|
||||
Index: b/elf/rtld.c
|
||||
===================================================================
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -214,7 +214,6 @@ audit_list_iter_next (struct audit_list_
|
||||
return iter->previous->name;
|
||||
}
|
||||
|
||||
-#ifndef HAVE_INLINED_SYSCALLS
|
||||
/* Set nonzero during loading and initialization of executable and
|
||||
libraries, cleared before the executable's entry point runs. This
|
||||
must not be initialized to nonzero, because the unused dynamic
|
||||
@@ -117,7 +116,6 @@
|
||||
@@ -224,7 +223,6 @@ audit_list_iter_next (struct audit_list_
|
||||
never be called. */
|
||||
int _dl_starting_up = 0;
|
||||
rtld_hidden_def (_dl_starting_up)
|
||||
@ -66,7 +78,7 @@ diff -urN glibc-2.20-205-ga39208b/elf/rtld.c glibc-2.20-205-ga39208b.mod/elf/rtl
|
||||
|
||||
/* This is the structure which defines all variables global to ld.so
|
||||
(except those which cannot be added for some reason). */
|
||||
@@ -776,10 +774,8 @@
|
||||
@@ -898,10 +896,8 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
/* Process the environment variable which control the behaviour. */
|
||||
process_envvars (&mode);
|
||||
|
||||
|
@ -1,101 +0,0 @@
|
||||
From 207e77fd3f0a94acdf0557608dd4f10ce0e0f22f Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Schwab <schwab@redhat.com>
|
||||
Date: Mon, 9 May 2011 10:55:58 +0200
|
||||
Subject: [PATCH] Never leave $ORIGIN unexpanded
|
||||
|
||||
* elf/dl-load.c (is_dst): Remove parameter secure, all callers
|
||||
changed. Move check for valid use of $ORIGIN ...
|
||||
(_dl_dst_substitute): ... here. Reset check_for_trusted when a
|
||||
path element is skipped.
|
||||
|
||||
---
|
||||
ChangeLog | 7 +++++++
|
||||
elf/dl-load.c | 34 ++++++++++++++++------------------
|
||||
2 files changed, 23 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/elf/dl-load.c b/elf/dl-load.c
|
||||
index 18a83d2..6e16a9a 100644
|
||||
--- a/elf/dl-load.c
|
||||
+++ b/elf/dl-load.c
|
||||
@@ -249,8 +249,7 @@ is_trusted_path_normalize (const char *path, size_t len)
|
||||
|
||||
|
||||
static size_t
|
||||
-is_dst (const char *start, const char *name, const char *str,
|
||||
- int is_path, int secure)
|
||||
+is_dst (const char *start, const char *name, const char *str, int is_path)
|
||||
{
|
||||
size_t len;
|
||||
bool is_curly = false;
|
||||
@@ -279,12 +278,6 @@ is_dst (const char *start, const char *name, const char *str,
|
||||
&& (!is_path || name[len] != ':'))
|
||||
return 0;
|
||||
|
||||
- if (__glibc_unlikely (secure)
|
||||
- && ((name[len] != '\0' && name[len] != '/'
|
||||
- && (!is_path || name[len] != ':'))
|
||||
- || (name != start + 1 && (!is_path || name[-2] != ':'))))
|
||||
- return 0;
|
||||
-
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -299,13 +292,10 @@ _dl_dst_count (const char *name, int is_path)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
- /* $ORIGIN is not expanded for SUID/GUID programs (except if it
|
||||
- is $ORIGIN alone) and it must always appear first in path. */
|
||||
++name;
|
||||
- if ((len = is_dst (start, name, "ORIGIN", is_path,
|
||||
- __libc_enable_secure)) != 0
|
||||
- || (len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0
|
||||
- || (len = is_dst (start, name, "LIB", is_path, 0)) != 0)
|
||||
+ if ((len = is_dst (start, name, "ORIGIN", is_path)) != 0
|
||||
+ || (len = is_dst (start, name, "PLATFORM", is_path)) != 0
|
||||
+ || (len = is_dst (start, name, "LIB", is_path)) != 0)
|
||||
++cnt;
|
||||
|
||||
name = strchr (name + len, '$');
|
||||
@@ -338,10 +328,18 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
|
||||
size_t len;
|
||||
|
||||
++name;
|
||||
- if ((len = is_dst (start, name, "ORIGIN", is_path,
|
||||
- __libc_enable_secure)) != 0)
|
||||
+ if ((len = is_dst (start, name, "ORIGIN", is_path)) != 0)
|
||||
{
|
||||
- repl = l->l_origin;
|
||||
+ /* For SUID/GUID programs $ORIGIN must always appear
|
||||
+ first in a path element. */
|
||||
+ if (__glibc_unlikely (__libc_enable_secure)
|
||||
+ && ((name[len] != '\0' && name[len] != '/'
|
||||
+ && (!is_path || name[len] != ':'))
|
||||
+ || (name != start + 1 && (!is_path || name[-2] != ':'))))
|
||||
+ repl = (const char *) -1;
|
||||
+ else
|
||||
+ repl = l->l_origin;
|
||||
+
|
||||
check_for_trusted = (__libc_enable_secure
|
||||
&& l->l_type == lt_executable);
|
||||
}
|
||||
@@ -351,9 +348,9 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
|
||||
check_for_trusted = (__libc_enable_secure
|
||||
&& l->l_type == lt_executable);
|
||||
}
|
||||
- else if ((len = is_dst (start, name, "PLATFORM", is_path, 0)) != 0)
|
||||
+ else if ((len = is_dst (start, name, "PLATFORM", is_path)) != 0)
|
||||
repl = GLRO(dl_platform);
|
||||
- else if ((len = is_dst (start, name, "LIB", is_path, 0)) != 0)
|
||||
+ else if ((len = is_dst (start, name, "LIB", is_path)) != 0)
|
||||
repl = DL_DST_LIB;
|
||||
|
||||
if (repl != NULL && repl != (const char *) -1)
|
||||
@@ -373,6 +370,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
|
||||
element, but keep an empty element at the end. */
|
||||
if (wp == result && is_path && *name == ':' && name[1] != '\0')
|
||||
++name;
|
||||
+ check_for_trusted = false;
|
||||
}
|
||||
else
|
||||
/* No DST we recognize. */
|
@ -1,18 +0,0 @@
|
||||
diff -Nrup a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile
|
||||
--- a/sysdeps/i386/Makefile 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/sysdeps/i386/Makefile 2012-06-07 12:15:21.826318641 -0600
|
||||
@@ -62,6 +64,14 @@ endif
|
||||
|
||||
ifneq (,$(filter -mno-tls-direct-seg-refs,$(CFLAGS)))
|
||||
defines += -DNO_TLS_DIRECT_SEG_REFS
|
||||
+else
|
||||
+# .a libraries are not performance critical and so we
|
||||
+# build them without direct TLS segment references
|
||||
+# always.
|
||||
+CPPFLAGS-.o += -DNO_TLS_DIRECT_SEG_REFS
|
||||
+CFLAGS-.o += -mno-tls-direct-seg-refs
|
||||
+CPPFLAGS-.oS += -DNO_TLS_DIRECT_SEG_REFS
|
||||
+CFLAGS-.oS += -mno-tls-direct-seg-refs
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),elf)
|
@ -1,30 +0,0 @@
|
||||
From 5eb4509a6651d19c7a28c4506d6aa582c9ee095a Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Wed, 1 Feb 2006 09:30:43 +0000
|
||||
Subject: [PATCH] 128-bit long double fixes
|
||||
|
||||
* include/bits/stdlib-ldbl.h: New file.
|
||||
* include/bits/wchar-ldbl.h: New file.
|
||||
|
||||
---
|
||||
ChangeLog | 5 +++++
|
||||
include/bits/stdlib-ldbl.h | 1 +
|
||||
include/bits/wchar-ldbl.h | 1 +
|
||||
3 files changed, 7 insertions(+), 0 deletions(-)
|
||||
create mode 100644 include/bits/stdlib-ldbl.h
|
||||
create mode 100644 include/bits/wchar-ldbl.h
|
||||
|
||||
diff --git a/include/bits/stdlib-ldbl.h b/include/bits/stdlib-ldbl.h
|
||||
new file mode 100644
|
||||
index 0000000..6250949
|
||||
--- /dev/null
|
||||
+++ b/include/bits/stdlib-ldbl.h
|
||||
@@ -0,0 +1 @@
|
||||
+#include <stdlib/bits/stdlib-ldbl.h>
|
||||
diff --git a/include/bits/wchar-ldbl.h b/include/bits/wchar-ldbl.h
|
||||
new file mode 100644
|
||||
index 0000000..29baa2f
|
||||
--- /dev/null
|
||||
+++ b/include/bits/wchar-ldbl.h
|
||||
@@ -0,0 +1 @@
|
||||
+#include <wcsmbs/bits/wchar-ldbl.h>
|
@ -1,42 +0,0 @@
|
||||
From 83e5edd390eabe8f8e8e0d051f929b77a30c0767 Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Schwab <schwab@redhat.com>
|
||||
Date: Fri, 18 Mar 2011 16:22:52 +0100
|
||||
Subject: [PATCH] ldd: never run file directly
|
||||
|
||||
* elf/ldd.bash.in: Never run file directly.
|
||||
|
||||
---
|
||||
ChangeLog | 4 ++++
|
||||
elf/ldd.bash.in | 14 +-------------
|
||||
2 files changed, 5 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/elf/ldd.bash.in
|
||||
+++ b/elf/ldd.bash.in
|
||||
@@ -166,18 +166,6 @@ warning: you do not have execution permission for" "\`$file'" >&2
|
||||
fi
|
||||
done
|
||||
case $ret in
|
||||
- 0)
|
||||
- # If the program exits with exit code 5, it means the process has been
|
||||
- # invoked with __libc_enable_secure. Fall back to running it through
|
||||
- # the dynamic linker.
|
||||
- try_trace "$file"
|
||||
- rc=$?
|
||||
- if [ $rc = 5 ]; then
|
||||
- try_trace "$RTLD" "$file"
|
||||
- rc=$?
|
||||
- fi
|
||||
- [ $rc = 0 ] || result=1
|
||||
- ;;
|
||||
1)
|
||||
# This can be a non-ELF binary or no binary at all.
|
||||
nonelf "$file" || {
|
||||
@@ -185,7 +173,7 @@ warning: you do not have execution permission for" "\`$file'" >&2
|
||||
result=1
|
||||
}
|
||||
;;
|
||||
- 2)
|
||||
+ 0|2)
|
||||
try_trace "$RTLD" "$file" || result=1
|
||||
;;
|
||||
*)
|
@ -1,7 +1,19 @@
|
||||
diff -Nrup a/sysdeps/unix/sysv/linux/tcsetattr.c b/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
--- a/sysdeps/unix/sysv/linux/tcsetattr.c 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/sysdeps/unix/sysv/linux/tcsetattr.c 2012-06-07 12:15:21.831318623 -0600
|
||||
@@ -48,6 +48,7 @@ tcsetattr (fd, optional_actions, termios
|
||||
Short description: Fedora-specific workaround for kernel pty bug.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-submitted
|
||||
|
||||
This is a Fedora-specific workaround for a kernel bug where calling
|
||||
ioctl on a pty will silently ignore the invalid c_cflag. The
|
||||
workaround is to use TCGETS to verify the setting matches. This is
|
||||
not upstream and needs to either be removed or submitted upstream
|
||||
after analysis.
|
||||
|
||||
Index: b/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
===================================================================
|
||||
--- a/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
+++ b/sysdeps/unix/sysv/linux/tcsetattr.c
|
||||
@@ -45,6 +45,7 @@ __tcsetattr (int fd, int optional_action
|
||||
{
|
||||
struct __kernel_termios k_termios;
|
||||
unsigned long int cmd;
|
||||
@ -9,7 +21,7 @@ diff -Nrup a/sysdeps/unix/sysv/linux/tcsetattr.c b/sysdeps/unix/sysv/linux/tcset
|
||||
|
||||
switch (optional_actions)
|
||||
{
|
||||
@@ -79,6 +80,35 @@ tcsetattr (fd, optional_actions, termios
|
||||
@@ -75,7 +76,36 @@ __tcsetattr (int fd, int optional_action
|
||||
memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0],
|
||||
__KERNEL_NCCS * sizeof (cc_t));
|
||||
|
||||
@ -45,4 +57,5 @@ diff -Nrup a/sysdeps/unix/sysv/linux/tcsetattr.c b/sysdeps/unix/sysv/linux/tcset
|
||||
+
|
||||
+ return retval;
|
||||
}
|
||||
weak_alias (__tcsetattr, tcsetattr)
|
||||
libc_hidden_def (tcsetattr)
|
||||
|
@ -1,3 +1,14 @@
|
||||
Short description: Add 4 ISO-8859-15 locales to SUPPORTED for Euro symbol.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #61908
|
||||
Upstream status: not-needed
|
||||
|
||||
Very early RHL 7.3 requirement to add these locales so users can
|
||||
get access to Euro symbol. We should review this bug and decide if
|
||||
the UTF-8 locales are now serving the same purpose and drop the
|
||||
additional locales.
|
||||
|
||||
* Tue Mar 26 2002 Jakub Jelinek <jakub@redhat.com> 2.2.5-28
|
||||
- add a couple of .ISO-8859-15 locales (#61908)
|
||||
|
||||
|
@ -1,11 +1,21 @@
|
||||
diff -Nrup a/localedata/Makefile b/localedata/Makefile
|
||||
--- a/localedata/Makefile 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/localedata/Makefile 2012-06-07 12:15:21.776318827 -0600
|
||||
@@ -211,6 +211,7 @@ $(INSTALL-SUPPORTED-LOCALES): install-lo
|
||||
Short description: Fedora-specific glibc install locale changes.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
The Fedora glibc build and install does not need the normal install
|
||||
behaviour which updates the locale archive. The Fedora install phase
|
||||
in the spec file of the rpm will handle this manually.
|
||||
|
||||
diff --git a/localedata/Makefile b/localedata/Makefile
|
||||
index 0eea396ad86da956..54caabda33728207 100644
|
||||
--- a/localedata/Makefile
|
||||
+++ b/localedata/Makefile
|
||||
@@ -413,6 +413,7 @@ define build-one-locale
|
||||
echo -n '...'; \
|
||||
input=`echo $$locale | sed 's/\([^.]*\)[^@]*\(.*\)/\1\2/'`; \
|
||||
$(LOCALEDEF) --alias-file=../intl/locale.alias \
|
||||
$(LOCALEDEF) $$flags --alias-file=../intl/locale.alias \
|
||||
+ --no-archive \
|
||||
-i locales/$$input -c -f charmaps/$$charset \
|
||||
-i locales/$$input -f charmaps/$$charset \
|
||||
$(addprefix --prefix=,$(install_root)) $$locale \
|
||||
&& echo ' done'; \
|
||||
&& echo ' done';
|
||||
|
@ -1,51 +0,0 @@
|
||||
This is a part of commit glibc-2.3.3-1492-ga891c7b,
|
||||
needed for fedora/build-locale-archive.c only.
|
||||
|
||||
diff -Nrup a/ChangeLog.17 b/ChangeLog.17
|
||||
--- a/ChangeLog.17 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/ChangeLog.17 2012-06-07 12:15:21.564319619 -0600
|
||||
@@ -11818,6 +11829,10 @@ d2009-10-30 Ulrich Drepper <drepper@re
|
||||
[BZ #4368]
|
||||
* stdlib/stdlib.h: Remove obsolete part of comment for realpath.
|
||||
|
||||
+2007-04-16 Jakub Jelinek <jakub@redhat.com>
|
||||
+
|
||||
+ * locale/programs/locarchive.c (add_alias, insert_name): Remove static.
|
||||
+
|
||||
2007-04-16 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
[BZ #4364]
|
||||
diff -Nrup a/locale/programs/locarchive.c b/locale/programs/locarchive.c
|
||||
--- a/locale/programs/locarchive.c 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/locale/programs/locarchive.c 2012-06-07 12:15:21.585319540 -0600
|
||||
@@ -252,9 +252,9 @@ oldlocrecentcmp (const void *a, const vo
|
||||
/* forward decls for below */
|
||||
static uint32_t add_locale (struct locarhandle *ah, const char *name,
|
||||
locale_data_t data, bool replace);
|
||||
-static void add_alias (struct locarhandle *ah, const char *alias,
|
||||
- bool replace, const char *oldname,
|
||||
- uint32_t *locrec_offset_p);
|
||||
+void add_alias (struct locarhandle *ah, const char *alias,
|
||||
+ bool replace, const char *oldname,
|
||||
+ uint32_t *locrec_offset_p);
|
||||
|
||||
|
||||
static bool
|
||||
@@ -635,7 +635,7 @@ close_archive (struct locarhandle *ah)
|
||||
#include "../../intl/explodename.c"
|
||||
#include "../../intl/l10nflist.c"
|
||||
|
||||
-static struct namehashent *
|
||||
+struct namehashent *
|
||||
insert_name (struct locarhandle *ah,
|
||||
const char *name, size_t name_len, bool replace)
|
||||
{
|
||||
@@ -693,7 +693,7 @@ insert_name (struct locarhandle *ah,
|
||||
return &namehashtab[idx];
|
||||
}
|
||||
|
||||
-static void
|
||||
+void
|
||||
add_alias (struct locarhandle *ah, const char *alias, bool replace,
|
||||
const char *oldname, uint32_t *locrec_offset_p)
|
||||
{
|
@ -1,3 +1,14 @@
|
||||
Short description: Place glibc info into "Libraries" category.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
The category names for libraries is completely random including
|
||||
"Libraries", "GNU Libraries", "GNU libraries", and "Software libraries."
|
||||
In the GNU info manual the "Software libraries" category is given as an
|
||||
example, but really we need to standardize on a category for upstream.
|
||||
I suggest we drop this change after some upstream discussion.
|
||||
|
||||
From 4820b9175535e13df79ce816106016040014916e Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Fri, 3 Nov 2006 16:31:21 +0000
|
||||
|
@ -1,3 +1,13 @@
|
||||
Short description: Fedora-specific enabling batch read in NSS.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #188246
|
||||
Upstream status: not-submitted
|
||||
|
||||
Enable batch read in NSS. It's not clear if this is always a win or
|
||||
just a win for NIS+, this needs to be analyzed and sent upstream or
|
||||
removed.
|
||||
|
||||
From baba5d9461d4e8a581ac26fe4412ad783ffc73e7 Mon Sep 17 00:00:00 2001
|
||||
From: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Mon, 1 May 2006 08:02:53 +0000
|
||||
|
@ -1,25 +0,0 @@
|
||||
diff -Nrup a/nptl/Makefile b/nptl/Makefile
|
||||
--- a/nptl/Makefile 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/nptl/Makefile 2012-06-07 12:15:21.816318678 -0600
|
||||
@@ -529,15 +529,19 @@ $(addprefix $(objpfx), \
|
||||
$(tests) $(xtests) $(test-srcs))): $(objpfx)libpthread.so \
|
||||
$(objpfx)libpthread_nonshared.a
|
||||
$(objpfx)tst-unload: $(libdl)
|
||||
-# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
|
||||
+# $(objpfx)linklibc.so is used instead of $(common-objpfx)libc.so,
|
||||
# since otherwise libpthread.so comes before libc.so when linking.
|
||||
$(addprefix $(objpfx), $(tests-reverse)): \
|
||||
- $(objpfx)../libc.so $(objpfx)libpthread.so \
|
||||
+ $(objpfx)linklibc.so $(objpfx)libpthread.so \
|
||||
$(objpfx)libpthread_nonshared.a
|
||||
$(objpfx)../libc.so: $(common-objpfx)libc.so ;
|
||||
$(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a
|
||||
|
||||
$(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so
|
||||
+
|
||||
+$(objpfx)linklibc.so: $(common-objpfx)libc.so
|
||||
+ ln -s ../libc.so $@
|
||||
+generated += libclink.so
|
||||
else
|
||||
$(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a
|
||||
endif
|
@ -1,3 +1,11 @@
|
||||
Short description: NSCD must use nscd user.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
Fedora-specific configuration adjustment to introduce the nscd user.
|
||||
(Upstream does not assume this user exists.)
|
||||
|
||||
diff -Nrup a/nscd/nscd.conf b/nscd/nscd.conf
|
||||
--- a/nscd/nscd.conf 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/nscd/nscd.conf 2012-06-07 12:15:21.818318670 -0600
|
||||
|
45
glibc-fedora-nsswitch.patch
Normal file
45
glibc-fedora-nsswitch.patch
Normal file
@ -0,0 +1,45 @@
|
||||
The Fedora /etc/nsswitch.conf is based largely on the upstream
|
||||
version with minor downstream distribution modifications for
|
||||
use with SSSD and systemd.
|
||||
|
||||
diff --git a/nss/nsswitch.conf b/nss/nsswitch.conf
|
||||
index f55358811495c9f1..14c3cde8080a848c 100644
|
||||
--- a/nss/nsswitch.conf
|
||||
+++ b/nss/nsswitch.conf
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# /etc/nsswitch.conf
|
||||
#
|
||||
-# An example Name Service Switch config file. This file should be
|
||||
+# Name Service Switch config file. This file should be
|
||||
# sorted with the most-used services at the beginning.
|
||||
#
|
||||
# Valid databases are: aliases, ethers, group, gshadow, hosts,
|
||||
@@ -52,18 +52,20 @@
|
||||
# shadow: db files
|
||||
# group: db files
|
||||
|
||||
-# In alphabetical order. Re-order as required to optimize peformance.
|
||||
+# In order of likelihood of use to accelerate lookup.
|
||||
+passwd: sss files
|
||||
+shadow: files sss
|
||||
+group: sss files
|
||||
+hosts: files dns myhostname
|
||||
+services: files sss
|
||||
+netgroup: sss
|
||||
+automount: files sss
|
||||
+
|
||||
aliases: files
|
||||
ethers: files
|
||||
-group: files
|
||||
gshadow: files
|
||||
-hosts: files dns
|
||||
initgroups: files
|
||||
-netgroup: files
|
||||
networks: files dns
|
||||
-passwd: files
|
||||
protocols: files
|
||||
publickey: files
|
||||
rpc: files
|
||||
-shadow: files
|
||||
-services: files
|
@ -1,20 +0,0 @@
|
||||
glibc-2.3.3-1478-g37582bc
|
||||
|
||||
* Thu Nov 30 2006 Jakub Jelinek <jakub@redhat.com> 2.5.90-9
|
||||
- on ppc64 build __libc_start_main without unwind info,
|
||||
as it breaks MD_FROB_UPDATE_CONTEXT (#217729, #217775; in the
|
||||
future that could be fixable just by providing .cfi_undefined r2
|
||||
in __libc_start_main instead)
|
||||
|
||||
diff -Nrup a/sysdeps/powerpc/powerpc64/Makefile b/sysdeps/powerpc/powerpc64/Makefile
|
||||
--- a/sysdeps/powerpc/powerpc64/Makefile 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/sysdeps/powerpc/powerpc64/Makefile 2012-06-07 12:15:21.828318633 -0600
|
||||
@@ -35,6 +35,8 @@ CFLAGS-rtld-memmove.os = $(no-special-re
|
||||
CFLAGS-rtld-memchr.os = $(no-special-regs)
|
||||
CFLAGS-rtld-strnlen.os = $(no-special-regs)
|
||||
|
||||
+CFLAGS-libc-start.c += -fno-asynchronous-unwind-tables
|
||||
+
|
||||
ifeq ($(subdir),elf)
|
||||
# help gcc inline asm code from dl-machine.h
|
||||
+cflags += -finline-limit=2000
|
@ -1,28 +0,0 @@
|
||||
This is part of commit glibc-2.3.3-1564-gd0b6ac6
|
||||
|
||||
* Fri Mar 14 2008 Jakub Jelinek <jakub@redhat.com> 2.7.90-11
|
||||
- remove <stropts.h>, define _XOPEN_STREAMS -1 (#436349)
|
||||
|
||||
diff -Nrup a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
|
||||
--- a/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-07 12:15:21.817318674 -0600
|
||||
@@ -188,4 +188,7 @@
|
||||
/* Typed memory objects are not available. */
|
||||
#define _POSIX_TYPED_MEMORY_OBJECTS -1
|
||||
|
||||
+/* Streams are not available. */
|
||||
+#define _XOPEN_STREAMS -1
|
||||
+
|
||||
#endif /* bits/posix_opt.h */
|
||||
diff -Nrup a/streams/Makefile b/streams/Makefile
|
||||
--- a/streams/Makefile 2012-06-05 07:42:49.000000000 -0600
|
||||
+++ b/streams/Makefile 2012-06-07 12:15:21.824318649 -0600
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
-headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
|
||||
+#headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
|
||||
routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach
|
||||
|
||||
include ../Rules
|
@ -1,50 +0,0 @@
|
||||
From cde99cd2b7b16a6113acb054e89d490047932a9f Mon Sep 17 00:00:00 2001
|
||||
From: Andreas Schwab <schwab@redhat.com>
|
||||
Date: Thu, 8 Apr 2010 11:18:26 +0200
|
||||
Subject: [PATCH] Don't call uname or getrlimit in libpthread init function
|
||||
|
||||
* sysdeps/unix/sysv/linux/i386/Versions: Export __uname under
|
||||
GLIBC_PRIVATE.
|
||||
* nptl/Versions: Export __getrlimit under GLIBC_PRIVATE.
|
||||
* sysdeps/unix/sysv/linux/i386/smp.h: Call __uname instead of uname.
|
||||
* nptl/nptl-init.c: Call __getrlimit instead of getrlimit.
|
||||
|
||||
---
|
||||
ChangeLog | 8 ++++++++
|
||||
nptl/Versions | 1 +
|
||||
nptl/nptl-init.c | 2 +-
|
||||
sysdeps/unix/sysv/linux/i386/Versions | 6 ++++++
|
||||
sysdeps/unix/sysv/linux/i386/smp.h | 2 +-
|
||||
5 files changed, 17 insertions(+), 2 deletions(-)
|
||||
create mode 100644 sysdeps/unix/sysv/linux/i386/Versions
|
||||
|
||||
--- a/nptl/Version
|
||||
+++ b/nptl/Versions
|
||||
@@ -30,6 +30,7 @@ libc {
|
||||
__libc_pthread_init;
|
||||
__libc_current_sigrtmin_private; __libc_current_sigrtmax_private;
|
||||
__libc_allocate_rtsig_private;
|
||||
+ __getrlimit;
|
||||
}
|
||||
}
|
||||
|
||||
--- a/sysdeps/unix/sysv/linux/i386/Versions
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/Versions
|
||||
@@ -53,5 +53,6 @@
|
||||
}
|
||||
GLIBC_PRIVATE {
|
||||
__modify_ldt;
|
||||
+ __uname;
|
||||
}
|
||||
}
|
||||
--- a/sysdeps/unix/sysv/linux/i386/smp.h
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/smp.h
|
||||
@@ -36,7 +36,7 @@ is_smp_system (void)
|
||||
char *cp;
|
||||
|
||||
/* Try reading the number using `sysctl' first. */
|
||||
- if (uname (&u.uts) == 0)
|
||||
+ if (__uname (&u.uts) == 0)
|
||||
cp = u.uts.version;
|
||||
else
|
||||
{
|
File diff suppressed because it is too large
Load Diff
@ -1,17 +0,0 @@
|
||||
Work around incorrect -Wmaybe-uninitialized warning due to this GCC bug:
|
||||
|
||||
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69537
|
||||
|
||||
Index: glibc-2.22-709-g8a71d2e/nis/ypclnt.c
|
||||
===================================================================
|
||||
--- glibc-2.22-709-g8a71d2e.orig/nis/ypclnt.c
|
||||
+++ glibc-2.22-709-g8a71d2e/nis/ypclnt.c
|
||||
@@ -584,7 +584,7 @@ yp_master (const char *indomain, const c
|
||||
{
|
||||
ypreq_nokey req;
|
||||
ypresp_master resp;
|
||||
- enum clnt_stat result;
|
||||
+ int result;
|
||||
|
||||
if (indomain == NULL || indomain[0] == '\0' ||
|
||||
inmap == NULL || inmap[0] == '\0')
|
@ -1,32 +0,0 @@
|
||||
Index: glibc-2.22-193-g315267a/resolv/gethnamaddr.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/resolv/gethnamaddr.c
|
||||
+++ glibc-2.22-193-g315267a/resolv/gethnamaddr.c
|
||||
@@ -71,6 +71,7 @@ static char sccsid[] = "@(#)gethostnamad
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
#define RESOLVSORT
|
||||
|
||||
@@ -986,10 +987,19 @@ addrsort(ap, num)
|
||||
|
||||
p = ap;
|
||||
for (i = 0; i < num; i++, p++) {
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since i is limited to
|
||||
+ _res.nsort which is limited to MAXRESOLVSORT. This
|
||||
+ is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (j = 0 ; (unsigned)j < _res.nsort; j++)
|
||||
if (_res.sort_list[j].addr.s_addr ==
|
||||
(((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
|
||||
break;
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
aval[i] = j;
|
||||
if (needsort == 0 && i > 0 && j < aval[i-1])
|
||||
needsort = i;
|
@ -1,32 +0,0 @@
|
||||
commit 48746aa5a013aab5ca89ee8c29761baec8850c0f
|
||||
Author: Jakub Jelinek <jakub@redhat.com>
|
||||
Date: Mon Feb 1 16:17:55 2016 +0000
|
||||
|
||||
Restore isinf, isinfl, isnanf and isnanl for C++11
|
||||
|
||||
diff --git a/math/bits/mathcalls.h b/math/bits/mathcalls.h
|
||||
index a48345d..9a7b3f0 100644
|
||||
--- a/math/bits/mathcalls.h
|
||||
+++ b/math/bits/mathcalls.h
|
||||
@@ -196,7 +196,9 @@ __MATHDECL_1 (int,__finite,, (_Mdouble_ __value)) __attribute__ ((__const__));
|
||||
_Mdouble_END_NAMESPACE
|
||||
|
||||
#ifdef __USE_MISC
|
||||
-# if !defined __cplusplus || __cplusplus < 201103L /* Conflicts with C++11. */
|
||||
+# if (!defined __cplusplus \
|
||||
+ || __cplusplus < 201103L /* isinf conflicts with C++11. */ \
|
||||
+ || __MATH_DECLARING_DOUBLE == 0) /* isinff or isinfl don't. */
|
||||
/* Return 0 if VALUE is finite or NaN, +1 if it
|
||||
is +Infinity, -1 if it is -Infinity. */
|
||||
__MATHDECL_1 (int,isinf,, (_Mdouble_ __value)) __attribute__ ((__const__));
|
||||
@@ -232,7 +234,9 @@ __END_NAMESPACE_C99
|
||||
__MATHDECL_1 (int,__isnan,, (_Mdouble_ __value)) __attribute__ ((__const__));
|
||||
|
||||
#if defined __USE_MISC || (defined __USE_XOPEN && !defined __USE_XOPEN2K)
|
||||
-# if !defined __cplusplus || __cplusplus < 201103L /* Conflicts with C++11. */
|
||||
+# if (!defined __cplusplus \
|
||||
+ || __cplusplus < 201103L /* isnan conflicts with C++11. */ \
|
||||
+ || __MATH_DECLARING_DOUBLE == 0) /* isnanf or isnanl don't. */
|
||||
/* Return nonzero if VALUE is not a number. */
|
||||
__MATHDECL_1 (int,isnan,, (_Mdouble_ __value)) __attribute__ ((__const__));
|
||||
# endif
|
@ -1,72 +0,0 @@
|
||||
Index: glibc-2.22-193-g315267a/locale/programs/ld-ctype.c
|
||||
===================================================================
|
||||
--- glibc-2.22-193-g315267a.orig/locale/programs/ld-ctype.c
|
||||
+++ glibc-2.22-193-g315267a/locale/programs/ld-ctype.c
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <wctype.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/uio.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
#include "localedef.h"
|
||||
#include "charmap.h"
|
||||
@@ -2534,9 +2535,19 @@ with character code range values one mus
|
||||
{
|
||||
size_t cnt;
|
||||
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not possible since ctype_map_new prevents
|
||||
+ map_collection_nr from being greater than MAX_NR_CHARMP which
|
||||
+ is the size of mapnames. This is likely PR/59124 which is still
|
||||
+ not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (cnt = 2; cnt < ctype->map_collection_nr; ++cnt)
|
||||
if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
|
||||
break;
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
if (cnt < ctype->map_collection_nr)
|
||||
free (now->val.str.startmb);
|
||||
@@ -2807,9 +2818,19 @@ previous definition was here")));
|
||||
|
||||
/* This could mean one of several things. First test whether
|
||||
it's a character class name. */
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not possible since ctype_class_new prevents
|
||||
+ nr_charclass from being greater than MAX_NR_CHARCLASS which
|
||||
+ is the size of classnames. This is likely PR/59124 which is still
|
||||
+ not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (cnt = 0; cnt < ctype->nr_charclass; ++cnt)
|
||||
if (strcmp (now->val.str.startmb, ctype->classnames[cnt]) == 0)
|
||||
break;
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
if (cnt < ctype->nr_charclass)
|
||||
{
|
||||
class_bit = _ISwbit (cnt);
|
||||
@@ -2817,9 +2838,19 @@ previous definition was here")));
|
||||
free (now->val.str.startmb);
|
||||
goto read_charclass;
|
||||
}
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not possible since ctype_map_new prevents
|
||||
+ map_collection_nr from being greater than MAX_NR_CHARMP which
|
||||
+ is the size of mapnames. This is likely PR/59124 which is still
|
||||
+ not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
for (cnt = 0; cnt < ctype->map_collection_nr; ++cnt)
|
||||
if (strcmp (now->val.str.startmb, ctype->mapnames[cnt]) == 0)
|
||||
break;
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
if (cnt < ctype->map_collection_nr)
|
||||
{
|
||||
mapidx = cnt;
|
@ -1,3 +1,10 @@
|
||||
Short description: Provide options to nscd startup.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Upstream status: not-needed
|
||||
|
||||
Fedora-specific nscd startup configuration file.
|
||||
|
||||
diff --git a/nscd/nscd.service b/nscd/nscd.service
|
||||
index b7428a3..19ba185 100644
|
||||
--- a/nscd/nscd.service
|
||||
|
@ -1,858 +0,0 @@
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: nsswitch: Add group merging support
|
||||
From: Stephen Gallagher <sgallagh@redhat.com>
|
||||
X-Patchwork-Id: 10289
|
||||
Message-Id: <1452213991-6499-1-git-send-email-sgallagh@redhat.com>
|
||||
To: libc-alpha@sourceware.org
|
||||
Date: Thu, 7 Jan 2016 19:46:31 -0500
|
||||
|
||||
https://sourceware.org/glibc/wiki/Proposals/GroupMerging
|
||||
|
||||
== Justification ==
|
||||
It is common today for users to rely on centrally-managed user stores for
|
||||
handling their user accounts. However, much software existing today does
|
||||
not have an innate understanding of such accounts. Instead, they commonly
|
||||
rely on membership in known groups for managing access-control (for
|
||||
example the "wheel" group on Fedora and RHEL systems or the "adm" group
|
||||
on Debian-derived systems). In the present incarnation of nsswitch, the
|
||||
only way to have such groups managed by a remote user store such as
|
||||
FreeIPA or Active Directory would be to manually remove the groups from
|
||||
/etc/group on the clients so that nsswitch would then move past nss_files
|
||||
and into the SSSD, nss-ldap or other remote user database.
|
||||
|
||||
== Solution ==
|
||||
With this patch, a new action is introduced for nsswitch:
|
||||
NSS_ACTION_MERGE. To take advantage of it, one will add [SUCCESS=merge]
|
||||
between two database entries in the nsswitch.conf file. When a group is
|
||||
located in the first of the two group entries, processing will continue
|
||||
on to the next one. If the group is also found in the next entry (and the
|
||||
group name and GID are an exact match), the member list of the second
|
||||
entry will be added to the group object to be returned.
|
||||
|
||||
== Implementation ==
|
||||
After each DL_LOOKUP_FN() returns, the next action is checked. If the
|
||||
function returned NSS_STATUS_SUCCESS and the next action is
|
||||
NSS_ACTION_MERGE, a copy of the result buffer is saved for the next pass
|
||||
through the loop. If on this next pass through the loop the database
|
||||
returns another instance of a group matching both the group name and GID,
|
||||
the member list is added to the previous list and it is returned as a
|
||||
single object. If the following database does not contain the same group,
|
||||
then the original is copied back into the destination buffer.
|
||||
|
||||
This patch implements merge functionality only for the group database.
|
||||
For other databases, there is a default implementation that will return
|
||||
the EINVAL errno if a merge is requested. The merge functionality can be
|
||||
implemented for other databases at a later time if such is needed. Each
|
||||
database must provide a unique implementation of the deep-copy and merge
|
||||
functions.
|
||||
|
||||
If [SUCCESS=merge] is present in nsswitch.conf for a glibc version that
|
||||
does not support it, glibc will process results up until that operation,
|
||||
at which time it will return results if it has found them or else will
|
||||
simply return an error. In practical terms, this ends up behaving like
|
||||
the remainder of the nsswitch.conf line does not exist.
|
||||
|
||||
== Iterators ==
|
||||
This feature does not modify the iterator functionality from its current
|
||||
behavior. If getgrnam() or getgrgid() is called, glibc will iterate
|
||||
through all entries in the `group` line in nsswitch.conf and display the
|
||||
list of members without attempting to merge them. This is consistent with
|
||||
the behavior of nss_files where if two separate lines are specified for
|
||||
the same group in /etc/groups, getgrnam()/getgrgid() will display both.
|
||||
Clients are already expected to handle this gracefully.
|
||||
|
||||
== No Premature Optimizations ==
|
||||
The following is a list of places that might be eligible for
|
||||
optimization, but were not overengineered for this initial contribution:
|
||||
* Any situation where a merge may occur will result in one malloc() of
|
||||
the same size as the input buffer.
|
||||
* Any situation where a merge does occur will result in a second
|
||||
malloc() to hold the list of pointers to member name strings.
|
||||
* The list of members is simply concatenated together and is not tested
|
||||
for uniqueness (which is identical to the behavior for nss_files,
|
||||
which will simply return identical values if they both exist on the
|
||||
line in the file. This could potentially be optimized to reduce space
|
||||
usage in the buffer, but it is both complex and computationally
|
||||
expensive to do so.
|
||||
|
||||
== Testing ==
|
||||
I performed testing by running the getent utility against my newly-built
|
||||
glibc and configuring /etc/nsswitch.conf with the following entry:
|
||||
group: group: files [SUCCESS=merge] sss
|
||||
|
||||
In /etc/group I included the line:
|
||||
wheel:x:10:sgallagh
|
||||
|
||||
I then configured my local SSSD using the id_provider=local to respond
|
||||
with:
|
||||
wheel:*:10:localuser,localuser2
|
||||
|
||||
I then ran `getent group wheel` against the newly-built glibc in
|
||||
multiple situations and received the expected output as described
|
||||
above:
|
||||
* When SSSD was running.
|
||||
* When SSSD was configured in nsswitch.conf but the daemon was not
|
||||
running.
|
||||
* When SSSD was configured in nsswitch.conf but nss_sss.so.2 was not
|
||||
installed on the system.
|
||||
* When the order of 'sss' and 'files' was reversed.
|
||||
* All of the above with the [SUCCESS=merge] removed (to ensure no
|
||||
regressions).
|
||||
* All of the above with `getent group 10`.
|
||||
* All of the above with `getent group` with and without
|
||||
`enumerate=true` set in SSSD.
|
||||
* All of the above with and without nscd enabled on the system.
|
||||
|
||||
== NEWS ==
|
||||
|
||||
* A new NSS action is added to facilitate large distribution system
|
||||
administration. The action, MERGE, allows remote user stores like
|
||||
LDAP to be merged into local user stores like /etc/groups in order
|
||||
to provide easy to use, updated, and managed sets of merged
|
||||
credentials. The new action can be used by configuring it in
|
||||
/etc/nsswitch.conf:
|
||||
group: files [SUCCESS=merge] nis
|
||||
Implemented by Stephen Gallagher (Red Hat).
|
||||
|
||||
== ChangeLog ==
|
||||
|
||||
2015-12-16 Stephen Gallagher <sgallagh@redhat.com>
|
||||
|
||||
[BZ #19072]
|
||||
* grp/Makefile (headers): Add grp-merge.h
|
||||
(routines): Add grp-merge.
|
||||
* grp/getgrgid_r.c: Include grp-merge.h.
|
||||
(DEEPCOPY_FN): Define.
|
||||
(MERGE_FN): Define.
|
||||
* grp/getgrname_r.c: Include grp-merge.h.
|
||||
(DEEPCOPY_FN): Define.
|
||||
(MERGE_FN): Define.
|
||||
* grp/grp-merge.c: New file.
|
||||
* grp/grp-merge.h: New file.
|
||||
* manual/nss.texi (Actions in the NSS configuration): Describe
|
||||
return, continue, and merge.
|
||||
* nscd/Makefile: Add vpath to find grp-merge.c
|
||||
(nscd-modules): Add grp-merge.
|
||||
* nscd/getgrgid_r.c: Include grp/grp-merge.h.
|
||||
(DEEPCOPY_FN): Define.
|
||||
(MERGE_FN): Define.
|
||||
* nscd/getgrnam_r.c: Include grp/grp-merge.h.
|
||||
(DEEPCOPY_FN): Define.
|
||||
(MERGE_FN): Define.
|
||||
* nss/getXXbyYY_r.c [!DEEPCOPY_FN]: Define __copy_einval.
|
||||
[!MERGE_FN]: Define __merge_einval.
|
||||
(CHECK_MERGE): Define.
|
||||
(REENTRANT_NAME): Process merge if do_merge is true.
|
||||
* nss/getnssent_r.c (__nss_setent): Process NSS_ACTION_MERGE.
|
||||
(__nss_getent_r): Likewise.
|
||||
* nss/nsswitch.c (nss_parse_service_list): Likewise.
|
||||
* nss/nsswitch.h (lookup_actions): Define NSS_ACTION_MERGE.
|
||||
|
||||
Resolves BZ #19072
|
||||
|
||||
---
|
||||
grp/Makefile | 5 +-
|
||||
grp/getgrgid_r.c | 3 +
|
||||
grp/getgrnam_r.c | 4 ++
|
||||
grp/grp-merge.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
grp/grp-merge.h | 35 +++++++++++
|
||||
manual/nss.texi | 46 +++++++++++++-
|
||||
nscd/Makefile | 5 +-
|
||||
nscd/getgrgid_r.c | 4 ++
|
||||
nscd/getgrnam_r.c | 4 ++
|
||||
nss/getXXbyYY_r.c | 105 +++++++++++++++++++++++++++++++-
|
||||
nss/getnssent_r.c | 34 ++++++++++-
|
||||
nss/nsswitch.c | 3 +
|
||||
nss/nsswitch.h | 3 +-
|
||||
13 files changed, 419 insertions(+), 10 deletions(-)
|
||||
create mode 100644 grp/grp-merge.c
|
||||
create mode 100644 grp/grp-merge.h
|
||||
|
||||
diff --git a/grp/Makefile b/grp/Makefile
|
||||
index ed8cc2b0564f0e3842cd78f24a4e0788d659bbc4..52af992365268aae8cf8a80cd7216160b1431e84 100644
|
||||
--- a/grp/Makefile
|
||||
+++ b/grp/Makefile
|
||||
@@ -20,15 +20,16 @@
|
||||
#
|
||||
subdir := grp
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
-headers := grp.h
|
||||
+headers := grp.h grp-merge.h
|
||||
|
||||
routines := fgetgrent initgroups setgroups \
|
||||
getgrent getgrgid getgrnam putgrent \
|
||||
- getgrent_r getgrgid_r getgrnam_r fgetgrent_r
|
||||
+ getgrent_r getgrgid_r getgrnam_r fgetgrent_r \
|
||||
+ grp-merge
|
||||
|
||||
tests := testgrp tst-putgrent
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
test-srcs := tst_fgetgrent
|
||||
diff --git a/grp/getgrgid_r.c b/grp/getgrgid_r.c
|
||||
index 05d4d772d3ef0bfae8f9375387c41310885ce41a..447fa633807deec8f26d654ebeb6386a150d3a37 100644
|
||||
--- a/grp/getgrgid_r.c
|
||||
+++ b/grp/getgrgid_r.c
|
||||
@@ -16,14 +16,17 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <grp.h>
|
||||
|
||||
+#include "grp-merge.h"
|
||||
|
||||
#define LOOKUP_TYPE struct group
|
||||
#define FUNCTION_NAME getgrgid
|
||||
#define DATABASE_NAME group
|
||||
#define ADD_PARAMS gid_t gid
|
||||
#define ADD_VARIABLES gid
|
||||
#define BUFLEN NSS_BUFLEN_GROUP
|
||||
+#define DEEPCOPY_FN __copy_grp
|
||||
+#define MERGE_FN __merge_grp
|
||||
|
||||
#include <nss/getXXbyYY_r.c>
|
||||
diff --git a/grp/getgrnam_r.c b/grp/getgrnam_r.c
|
||||
index 0061cb2f7e0bd311d19775e49eb3fdd8a93447f1..c5535f4057ddfc40965f27789c34345045c8bf3b 100644
|
||||
--- a/grp/getgrnam_r.c
|
||||
+++ b/grp/getgrnam_r.c
|
||||
@@ -16,13 +16,17 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <grp.h>
|
||||
|
||||
+#include "grp-merge.h"
|
||||
|
||||
#define LOOKUP_TYPE struct group
|
||||
#define FUNCTION_NAME getgrnam
|
||||
#define DATABASE_NAME group
|
||||
#define ADD_PARAMS const char *name
|
||||
#define ADD_VARIABLES name
|
||||
|
||||
+#define DEEPCOPY_FN __copy_grp
|
||||
+#define MERGE_FN __merge_grp
|
||||
+
|
||||
#include <nss/getXXbyYY_r.c>
|
||||
diff --git a/grp/grp-merge.c b/grp/grp-merge.c
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ca959dbfe403c89d6f3184f2b361b0c6488c9182
|
||||
--- /dev/null
|
||||
+++ b/grp/grp-merge.c
|
||||
@@ -0,0 +1,178 @@
|
||||
+/* Group merging implementation.
|
||||
+ Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <grp.h>
|
||||
+#include "grp-merge.h"
|
||||
+
|
||||
+#define BUFCHECK(size) \
|
||||
+ do { \
|
||||
+ if (c + size > buflen) \
|
||||
+ { \
|
||||
+ free (members); \
|
||||
+ return ERANGE; \
|
||||
+ } \
|
||||
+ } while(0)
|
||||
+
|
||||
+int
|
||||
+__copy_grp (const struct group srcgrp, const size_t buflen,
|
||||
+ struct group *destgrp, char *destbuf, char **endptr)
|
||||
+{
|
||||
+ size_t i;
|
||||
+ size_t c = 0;
|
||||
+ size_t len;
|
||||
+ size_t memcount;
|
||||
+ char **members = NULL;
|
||||
+
|
||||
+ /* Copy the GID. */
|
||||
+ destgrp->gr_gid = srcgrp.gr_gid;
|
||||
+
|
||||
+ /* Copy the name. */
|
||||
+ len = strlen (srcgrp.gr_name) + 1;
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&destbuf[c], srcgrp.gr_name, len);
|
||||
+ destgrp->gr_name = &destbuf[c];
|
||||
+ c += len;
|
||||
+
|
||||
+ /* Copy the password. */
|
||||
+ len = strlen (srcgrp.gr_passwd) + 1;
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&destbuf[c], srcgrp.gr_passwd, len);
|
||||
+ destgrp->gr_passwd = &destbuf[c];
|
||||
+ c += len;
|
||||
+
|
||||
+ /* Count all of the members. */
|
||||
+ for (memcount = 0; srcgrp.gr_mem[memcount]; memcount++)
|
||||
+ ;
|
||||
+
|
||||
+ /* Allocate a temporary holding area for the pointers to the member
|
||||
+ contents, including space for a NULL-terminator. */
|
||||
+ members = malloc (sizeof (char *) * (memcount + 1));
|
||||
+ if (members == NULL)
|
||||
+ return ENOMEM;
|
||||
+
|
||||
+ /* Copy all of the group members to destbuf and add a pointer to each of
|
||||
+ them into the 'members' array. */
|
||||
+ for (i = 0; srcgrp.gr_mem[i]; i++)
|
||||
+ {
|
||||
+ len = strlen (srcgrp.gr_mem[i]) + 1;
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&destbuf[c], srcgrp.gr_mem[i], len);
|
||||
+ members[i] = &destbuf[c];
|
||||
+ c += len;
|
||||
+ }
|
||||
+ members[i] = NULL;
|
||||
+
|
||||
+ /* Copy the pointers from the members array into the buffer and assign them
|
||||
+ to the gr_mem member of destgrp. */
|
||||
+ destgrp->gr_mem = (char **) &destbuf[c];
|
||||
+ len = sizeof (char *) * (memcount + 1);
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&destbuf[c], members, len);
|
||||
+ c += len;
|
||||
+ free (members);
|
||||
+ members = NULL;
|
||||
+
|
||||
+ /* Save the count of members at the end. */
|
||||
+ BUFCHECK (sizeof (size_t));
|
||||
+ memcpy (&destbuf[c], &memcount, sizeof (size_t));
|
||||
+ c += sizeof (size_t);
|
||||
+
|
||||
+ if (endptr)
|
||||
+ *endptr = destbuf + c;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Check that the name, GID and passwd fields match, then
|
||||
+ copy in the gr_mem array. */
|
||||
+int
|
||||
+__merge_grp (struct group *savedgrp, char *savedbuf, char *savedend,
|
||||
+ size_t buflen, struct group *mergegrp, char *mergebuf)
|
||||
+{
|
||||
+ size_t c, i, len;
|
||||
+ size_t savedmemcount;
|
||||
+ size_t memcount;
|
||||
+ size_t membersize;
|
||||
+ char **members = NULL;
|
||||
+
|
||||
+ /* We only support merging members of groups with identical names and
|
||||
+ GID values. If we hit this case, we need to overwrite the current
|
||||
+ buffer with the saved one (which is functionally equivalent to
|
||||
+ treating the new lookup as NSS_STATUS NOTFOUND. */
|
||||
+ if (mergegrp->gr_gid != savedgrp->gr_gid
|
||||
+ || strcmp (mergegrp->gr_name, savedgrp->gr_name))
|
||||
+ return __copy_grp (*savedgrp, buflen, mergegrp, mergebuf, NULL);
|
||||
+
|
||||
+ /* Get the count of group members from the last sizeof (size_t) bytes in the
|
||||
+ mergegrp buffer. */
|
||||
+ savedmemcount = (size_t) *(savedend - sizeof (size_t));
|
||||
+
|
||||
+ /* Get the count of new members to add. */
|
||||
+ for (memcount = 0; mergegrp->gr_mem[memcount]; memcount++)
|
||||
+ ;
|
||||
+
|
||||
+ /* Create a temporary array to hold the pointers to the member values from
|
||||
+ both the saved and merge groups. */
|
||||
+ membersize = savedmemcount + memcount + 1;
|
||||
+ members = malloc (sizeof (char *) * membersize);
|
||||
+ if (members == NULL)
|
||||
+ return ENOMEM;
|
||||
+
|
||||
+ /* Copy in the existing member pointers from the saved group
|
||||
+ Note: this is not NULL-terminated yet. */
|
||||
+ memcpy (members, savedgrp->gr_mem, sizeof (char *) * savedmemcount);
|
||||
+
|
||||
+ /* Back up into the savedbuf until we get back to the NULL-terminator of the
|
||||
+ group member list. (This means walking back savedmemcount + 1 (char *) pointers
|
||||
+ and the member count value.
|
||||
+ The value of c is going to be the used length of the buffer backed up by
|
||||
+ the member count and further backed up by the size of the pointers. */
|
||||
+ c = savedend - savedbuf
|
||||
+ - sizeof (size_t)
|
||||
+ - sizeof (char *) * (savedmemcount + 1);
|
||||
+
|
||||
+ /* Add all the new group members, overwriting the old NULL-terminator while
|
||||
+ adding the new pointers to the temporary array. */
|
||||
+ for (i = 0; mergegrp->gr_mem[i]; i++)
|
||||
+ {
|
||||
+ len = strlen (mergegrp->gr_mem[i]) + 1;
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&savedbuf[c], mergegrp->gr_mem[i], len);
|
||||
+ members[savedmemcount + i] = &savedbuf[c];
|
||||
+ c += len;
|
||||
+ }
|
||||
+ /* Add the NULL-terminator. */
|
||||
+ members[savedmemcount + memcount] = NULL;
|
||||
+
|
||||
+ /* Copy the member array back into the buffer after the member list and free
|
||||
+ the member array. */
|
||||
+ savedgrp->gr_mem = (char **) &savedbuf[c];
|
||||
+ len = sizeof (char *) * membersize;
|
||||
+ BUFCHECK (len);
|
||||
+ memcpy (&savedbuf[c], members, len);
|
||||
+ c += len;
|
||||
+
|
||||
+ free (members);
|
||||
+ members = NULL;
|
||||
+
|
||||
+ /* Finally, copy the results back into mergebuf, since that's the buffer
|
||||
+ that we were provided by the caller. */
|
||||
+ return __copy_grp (*savedgrp, buflen, mergegrp, mergebuf, NULL);
|
||||
+}
|
||||
diff --git a/grp/grp-merge.h b/grp/grp-merge.h
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..59013487d0d907c76521ab504e265077937bfb5e
|
||||
--- /dev/null
|
||||
+++ b/grp/grp-merge.h
|
||||
@@ -0,0 +1,35 @@
|
||||
+/* Group merging implementation.
|
||||
+ Copyright (C) 2016 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef _GRP_MERGE_H
|
||||
+#define _GRP_MERGE_H 1
|
||||
+
|
||||
+#include <grp.h>
|
||||
+
|
||||
+/* Duplicate a grp struct (and its members). When no longer needed, the
|
||||
+ calling function must free(newbuf). */
|
||||
+int
|
||||
+__copy_grp (const struct group srcgrp, const size_t buflen,
|
||||
+ struct group *destgrp, char *destbuf, char **endptr);
|
||||
+
|
||||
+/* Merge the member lists of two grp structs together. */
|
||||
+int
|
||||
+__merge_grp (struct group *savedgrp, char *savedbuf, char *savedend,
|
||||
+ size_t buflen, struct group *mergegrp, char *mergebuf);
|
||||
+
|
||||
+#endif /* _GRP_MERGE_H */
|
||||
diff --git a/manual/nss.texi b/manual/nss.texi
|
||||
index 66dcceffe01f225f078e88dd006bb90e80c85723..95e3544bcd97995720e7154ec43df4090154bf4c 100644
|
||||
--- a/manual/nss.texi
|
||||
+++ b/manual/nss.texi
|
||||
@@ -178,11 +178,11 @@ where
|
||||
@var{action} @result{} return | continue
|
||||
@end smallexample
|
||||
|
||||
The case of the keywords is insignificant. The @var{status}
|
||||
values are the results of a call to a lookup function of a specific
|
||||
-service. They mean
|
||||
+service. They mean:
|
||||
|
||||
@ftable @samp
|
||||
@item success
|
||||
No error occurred and the wanted entry is returned. The default action
|
||||
for this is @code{return}.
|
||||
@@ -202,10 +202,54 @@ The service is temporarily unavailable. This could mean a file is
|
||||
locked or a server currently cannot accept more connections. The
|
||||
default action is @code{continue}.
|
||||
@end ftable
|
||||
|
||||
@noindent
|
||||
+The @var{action} values mean:
|
||||
+
|
||||
+@ftable @samp
|
||||
+@item return
|
||||
+
|
||||
+If the status matches, stop the lookup process at this service
|
||||
+specification. If an entry is available, provide it to the application.
|
||||
+If an error occurred, report it to the application. In case of a prior
|
||||
+@samp{merge} action, the data is combined with previous lookup results,
|
||||
+as explained below.
|
||||
+
|
||||
+@item continue
|
||||
+
|
||||
+If the status matches, proceed with the lookup process at the next
|
||||
+entry, discarding the result of the current lookup (and any merged
|
||||
+data). An exception is the @samp{initgroups} database and the
|
||||
+@samp{success} status, where @samp{continue} acts like @code{merge}
|
||||
+below.
|
||||
+
|
||||
+@item merge
|
||||
+
|
||||
+Proceed with the lookup process, retaining the current lookup result.
|
||||
+This action is useful only with the @samp{success} status. If a
|
||||
+subsequent service lookup succeeds and has a matching @samp{return}
|
||||
+specification, the results are merged, the lookup process ends, and the
|
||||
+merged results are returned to the application. If the following service
|
||||
+has a matching @samp{merge} action, the lookup process continues,
|
||||
+retaining the combined data from this and any previous lookups.
|
||||
+
|
||||
+After a @code{merge} action, errors from subsequent lookups are ignored,
|
||||
+and the data gathered so far will be returned.
|
||||
+
|
||||
+The @samp{merge} only applies to the @samp{success} status. It is
|
||||
+currently implemented for the @samp{group} database and its group
|
||||
+members field, @samp{gr_mem}. If specified for other databases, it
|
||||
+causes the lookup to fail (if the @var{status} matches).
|
||||
+
|
||||
+When processing @samp{merge} for @samp{group} membership, the group GID
|
||||
+and name must be identical for both entries. If only one or the other is
|
||||
+a match, the behavior is undefined.
|
||||
+
|
||||
+@end ftable
|
||||
+
|
||||
+@noindent
|
||||
If we have a line like
|
||||
|
||||
@smallexample
|
||||
ethers: nisplus [NOTFOUND=return] db files
|
||||
@end smallexample
|
||||
diff --git a/nscd/Makefile b/nscd/Makefile
|
||||
index e1a1aa92fc699aa132f7192da49f698a078e5910..3e6895573ae33221c728617f4c95bb3e8c5d5c47 100644
|
||||
--- a/nscd/Makefile
|
||||
+++ b/nscd/Makefile
|
||||
@@ -29,16 +29,19 @@ aux := nscd_helper
|
||||
endif
|
||||
|
||||
# To find xmalloc.c
|
||||
vpath %.c ../locale/programs
|
||||
|
||||
+# To find grp-merge.c
|
||||
+vpath %.c ../grp
|
||||
+
|
||||
nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \
|
||||
getgrnam_r getgrgid_r hstcache gethstbyad_r gethstbynm3_r \
|
||||
getsrvbynm_r getsrvbypt_r servicescache \
|
||||
dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \
|
||||
xmalloc xstrdup aicache initgrcache gai res_hconf \
|
||||
- netgroupcache
|
||||
+ netgroupcache grp-merge
|
||||
|
||||
ifeq ($(build-nscd)$(have-thread-library),yesyes)
|
||||
|
||||
others += nscd
|
||||
others-pie += nscd
|
||||
diff --git a/nscd/getgrgid_r.c b/nscd/getgrgid_r.c
|
||||
index fe5bda424169d56f642f125ef1f2df77a84de221..25de4a3b0b74841c44844a0541cf4d2365b22515 100644
|
||||
--- a/nscd/getgrgid_r.c
|
||||
+++ b/nscd/getgrgid_r.c
|
||||
@@ -15,17 +15,21 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <grp.h>
|
||||
|
||||
+#include "grp/grp-merge.h"
|
||||
|
||||
#define LOOKUP_TYPE struct group
|
||||
#define FUNCTION_NAME getgrgid
|
||||
#define DATABASE_NAME group
|
||||
#define ADD_PARAMS gid_t gid
|
||||
#define ADD_VARIABLES gid
|
||||
#define BUFLEN NSS_BUFLEN_GROUP
|
||||
|
||||
+#define DEEPCOPY_FN __copy_grp
|
||||
+#define MERGE_FN __merge_grp
|
||||
+
|
||||
/* We are nscd, so we don't want to be talking to ourselves. */
|
||||
#undef USE_NSCD
|
||||
|
||||
#include <nss/getXXbyYY_r.c>
|
||||
diff --git a/nscd/getgrnam_r.c b/nscd/getgrnam_r.c
|
||||
index 5ec56877f5798ca34c2e0074d5093cc22b6d58dc..386d66c5832ffee68e95195f6e34b723f41d0984 100644
|
||||
--- a/nscd/getgrnam_r.c
|
||||
+++ b/nscd/getgrnam_r.c
|
||||
@@ -15,16 +15,20 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <grp.h>
|
||||
|
||||
+#include "grp/grp-merge.h"
|
||||
|
||||
#define LOOKUP_TYPE struct group
|
||||
#define FUNCTION_NAME getgrnam
|
||||
#define DATABASE_NAME group
|
||||
#define ADD_PARAMS const char *name
|
||||
#define ADD_VARIABLES name
|
||||
|
||||
+#define DEEPCOPY_FN __copy_grp
|
||||
+#define MERGE_FN __merge_grp
|
||||
+
|
||||
/* We are nscd, so we don't want to be talking to ourselves. */
|
||||
#undef USE_NSCD
|
||||
|
||||
#include <nss/getXXbyYY_r.c>
|
||||
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
|
||||
index 198f8cfebd51be9c738f03f950f093b0855ab3cb..5f49ae8b828fce6dc30c7ccc9606319bffc52d5b 100644
|
||||
--- a/nss/getXXbyYY_r.c
|
||||
+++ b/nss/getXXbyYY_r.c
|
||||
@@ -129,10 +129,52 @@
|
||||
# define AF_VAL af
|
||||
#else
|
||||
# define AF_VAL AF_INET
|
||||
#endif
|
||||
|
||||
+
|
||||
+/* Set defaults for merge functions that haven't been defined. */
|
||||
+#ifndef DEEPCOPY_FN
|
||||
+static inline int
|
||||
+__copy_einval (LOOKUP_TYPE a,
|
||||
+ const size_t b,
|
||||
+ LOOKUP_TYPE *c,
|
||||
+ char *d,
|
||||
+ char **e)
|
||||
+{
|
||||
+ return EINVAL;
|
||||
+}
|
||||
+# define DEEPCOPY_FN __copy_einval
|
||||
+#endif
|
||||
+
|
||||
+#ifndef MERGE_FN
|
||||
+static inline int
|
||||
+__merge_einval (LOOKUP_TYPE *a,
|
||||
+ char *b,
|
||||
+ char *c,
|
||||
+ size_t d,
|
||||
+ LOOKUP_TYPE *e,
|
||||
+ char *f)
|
||||
+{
|
||||
+ return EINVAL;
|
||||
+}
|
||||
+# define MERGE_FN __merge_einval
|
||||
+#endif
|
||||
+
|
||||
+#define CHECK_MERGE(err, status) \
|
||||
+do { \
|
||||
+ if (err) \
|
||||
+ { \
|
||||
+ __set_errno (err); \
|
||||
+ if (err == ERANGE) \
|
||||
+ status = NSS_STATUS_TRYAGAIN; \
|
||||
+ else \
|
||||
+ status = NSS_STATUS_UNAVAIL; \
|
||||
+ break; \
|
||||
+ } \
|
||||
+} while(0)
|
||||
+
|
||||
/* Type of the lookup function we need here. */
|
||||
typedef enum nss_status (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *,
|
||||
size_t, int * H_ERRNO_PARM
|
||||
EXTRA_PARAMS);
|
||||
|
||||
@@ -150,17 +192,20 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||||
{
|
||||
static bool startp_initialized;
|
||||
static service_user *startp;
|
||||
static lookup_function start_fct;
|
||||
service_user *nip;
|
||||
+ int do_merge = 0;
|
||||
+ LOOKUP_TYPE mergegrp;
|
||||
+ char *mergebuf = NULL;
|
||||
+ char *endptr = NULL;
|
||||
union
|
||||
{
|
||||
lookup_function l;
|
||||
void *ptr;
|
||||
} fct;
|
||||
-
|
||||
- int no_more;
|
||||
+ int no_more, err;
|
||||
enum nss_status status = NSS_STATUS_UNAVAIL;
|
||||
#ifdef USE_NSCD
|
||||
int nscd_status;
|
||||
#endif
|
||||
#ifdef NEED_H_ERRNO
|
||||
@@ -276,13 +321,69 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||||
&& *h_errnop == NETDB_INTERNAL
|
||||
#endif
|
||||
&& errno == ERANGE)
|
||||
break;
|
||||
|
||||
+ if (do_merge)
|
||||
+ {
|
||||
+
|
||||
+ if (status == NSS_STATUS_SUCCESS)
|
||||
+ {
|
||||
+ /* The previous loop saved a buffer for merging.
|
||||
+ Perform the merge now. */
|
||||
+ err = MERGE_FN (&mergegrp, mergebuf, endptr, buflen, resbuf,
|
||||
+ buffer);
|
||||
+ CHECK_MERGE (err,status);
|
||||
+ do_merge = 0;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* If the result wasn't SUCCESS, copy the saved buffer back
|
||||
+ into the result buffer and set the status back to
|
||||
+ NSS_STATUS_SUCCESS to match the previous pass through the loop.
|
||||
+ * If the next action is CONTINUE, it will overwrite the value
|
||||
+ currently in the buffer and return the new value.
|
||||
+ * If the next action is RETURN, we'll return the previously-
|
||||
+ acquired values.
|
||||
+ * If the next action is MERGE, then it will be added to the buffer
|
||||
+ saved from the previous source. */
|
||||
+ err = DEEPCOPY_FN (mergegrp, buflen, resbuf, buffer, NULL);
|
||||
+ CHECK_MERGE (err, status);
|
||||
+ status = NSS_STATUS_SUCCESS;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If we were are configured to merge this value with the next one,
|
||||
+ save the current value of the group struct. */
|
||||
+ if (nss_next_action (nip, status) == NSS_ACTION_MERGE
|
||||
+ && status == NSS_STATUS_SUCCESS)
|
||||
+ {
|
||||
+ /* Copy the current values into a buffer to be merged with the next
|
||||
+ set of retrieved values. */
|
||||
+ if (!mergebuf)
|
||||
+ {
|
||||
+ /* Only allocate once and reuse it for as many merges as we need
|
||||
+ to perform. */
|
||||
+ mergebuf = malloc (buflen);
|
||||
+ if (!mergebuf)
|
||||
+ {
|
||||
+ __set_errno (ENOMEM);
|
||||
+ status = NSS_STATUS_UNAVAIL;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ err = DEEPCOPY_FN (*resbuf, buflen, &mergegrp, mergebuf, &endptr);
|
||||
+ CHECK_MERGE (err, status);
|
||||
+ do_merge = 1;
|
||||
+ }
|
||||
+
|
||||
no_more = __nss_next2 (&nip, REENTRANT_NAME_STRING,
|
||||
REENTRANT2_NAME_STRING, &fct.ptr, status, 0);
|
||||
}
|
||||
+ free(mergebuf);
|
||||
+ mergebuf = NULL;
|
||||
|
||||
#ifdef HANDLE_DIGITS_DOTS
|
||||
done:
|
||||
#endif
|
||||
*result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
|
||||
diff --git a/nss/getnssent_r.c b/nss/getnssent_r.c
|
||||
index f5b903671ca53ccad108eeb4e49ea40a45fa5cdf..c0743436f661d4d83045a6353b49291a4c0f220b 100644
|
||||
--- a/nss/getnssent_r.c
|
||||
+++ b/nss/getnssent_r.c
|
||||
@@ -77,11 +77,25 @@ __nss_setent (const char *func_name, db_lookup_function lookup_fct,
|
||||
if (stayopen_tmp)
|
||||
status = DL_CALL_FCT (fct.f, (*stayopen_tmp));
|
||||
else
|
||||
status = DL_CALL_FCT (fct.f, (0));
|
||||
|
||||
- no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, status, 0);
|
||||
+ if (nss_next_action (*nip, status) == NSS_ACTION_MERGE)
|
||||
+ {
|
||||
+ /* This is a special-case. When [SUCCESS=merge] is in play,
|
||||
+ _nss_next2() will skip to the next database. Due to the
|
||||
+ implementation of that function, we can't know whether we're
|
||||
+ in an enumeration or an individual lookup, which behaves
|
||||
+ differently with regards to merging. We'll treat SUCCESS as
|
||||
+ an indication to start the enumeration at this database. */
|
||||
+ no_more = 1;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, status, 0);
|
||||
+ }
|
||||
+
|
||||
if (is_last_nip)
|
||||
*last_nip = *nip;
|
||||
}
|
||||
|
||||
if (stayopen_tmp)
|
||||
@@ -173,12 +187,26 @@ __nss_getent_r (const char *getent_func_name,
|
||||
&& errno == ERANGE)
|
||||
break;
|
||||
|
||||
do
|
||||
{
|
||||
- no_more = __nss_next2 (nip, getent_func_name, NULL, &fct.ptr,
|
||||
- status, 0);
|
||||
+ if (status == NSS_STATUS_SUCCESS
|
||||
+ && nss_next_action (*nip, status) == NSS_ACTION_MERGE)
|
||||
+ {
|
||||
+ /* This is a special-case. When [SUCCESS=merge] is in play,
|
||||
+ _nss_next2() will skip to the next database. Due to the
|
||||
+ implementation of that function, we can't know whether we're
|
||||
+ in an enumeration or an individual lookup, which behaves
|
||||
+ differently with regards to merging. We'll treat SUCCESS as
|
||||
+ an indication to return the results here. */
|
||||
+ no_more = 1;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ no_more = __nss_next2 (nip, getent_func_name, NULL, &fct.ptr,
|
||||
+ status, 0);
|
||||
+ }
|
||||
|
||||
if (is_last_nip)
|
||||
*last_nip = *nip;
|
||||
|
||||
if (! no_more)
|
||||
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
|
||||
index faf9d1a0d5680aa79e88b2dfeea18da371c336fb..f8f60ba05aad9a571f928a3ea7d3b14f908ccb2d 100644
|
||||
--- a/nss/nsswitch.c
|
||||
+++ b/nss/nsswitch.c
|
||||
@@ -710,10 +710,13 @@ nss_parse_service_list (const char *line)
|
||||
if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0)
|
||||
action = NSS_ACTION_RETURN;
|
||||
else if (line - name == 8
|
||||
&& __strncasecmp (name, "CONTINUE", 8) == 0)
|
||||
action = NSS_ACTION_CONTINUE;
|
||||
+ else if (line - name == 5
|
||||
+ && __strncasecmp (name, "MERGE", 5) == 0)
|
||||
+ action = NSS_ACTION_MERGE;
|
||||
else
|
||||
goto finish;
|
||||
|
||||
if (not)
|
||||
{
|
||||
diff --git a/nss/nsswitch.h b/nss/nsswitch.h
|
||||
index a5318fa82be43c8314807ad76de231e572e91c06..5bc2de3b1d82978102ac7a129c0ba5b7eb3cfd25 100644
|
||||
--- a/nss/nsswitch.h
|
||||
+++ b/nss/nsswitch.h
|
||||
@@ -30,11 +30,12 @@
|
||||
|
||||
/* Actions performed after lookup finished. */
|
||||
typedef enum
|
||||
{
|
||||
NSS_ACTION_CONTINUE,
|
||||
- NSS_ACTION_RETURN
|
||||
+ NSS_ACTION_RETURN,
|
||||
+ NSS_ACTION_MERGE
|
||||
} lookup_actions;
|
||||
|
||||
|
||||
typedef struct service_library
|
||||
{
|
40
glibc-python3.patch
Normal file
40
glibc-python3.patch
Normal file
@ -0,0 +1,40 @@
|
||||
Use python3 for installed executable python scripts.
|
||||
|
||||
Fedora is a Python3-only distribution:
|
||||
https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3
|
||||
|
||||
This fixes build failures where builders may strictly enforce only
|
||||
python3 during a transitional phase.
|
||||
|
||||
Author: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/benchtests/scripts/compare_bench.py b/benchtests/scripts/compare_bench.py
|
||||
index c1c438a1c9f0eae6..b7d3d7bcee87969d 100755
|
||||
--- a/benchtests/scripts/compare_bench.py
|
||||
+++ b/benchtests/scripts/compare_bench.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
# Copyright (C) 2015-2019 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
#
|
||||
diff --git a/benchtests/scripts/import_bench.py b/benchtests/scripts/import_bench.py
|
||||
index 7a55d19f038e64d4..72e6034243a8c9b6 100644
|
||||
--- a/benchtests/scripts/import_bench.py
|
||||
+++ b/benchtests/scripts/import_bench.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
# Copyright (C) 2015-2019 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
#
|
||||
diff --git a/benchtests/scripts/validate_benchout.py b/benchtests/scripts/validate_benchout.py
|
||||
index 55d07c6bce5b5184..04129f9c26c2874c 100755
|
||||
--- a/benchtests/scripts/validate_benchout.py
|
||||
+++ b/benchtests/scripts/validate_benchout.py
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/usr/bin/python
|
||||
+#!/usr/bin/python3
|
||||
# Copyright (C) 2014-2019 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
#
|
@ -1,29 +0,0 @@
|
||||
Index: glibc-2.22-386-g95e8397/resolv/res_hconf.c
|
||||
===================================================================
|
||||
--- glibc-2.22-386-g95e8397.orig/resolv/res_hconf.c
|
||||
+++ glibc-2.22-386-g95e8397/resolv/res_hconf.c
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "res_hconf.h"
|
||||
#include <wchar.h>
|
||||
#include <atomic.h>
|
||||
+#include <libc-internal.h>
|
||||
|
||||
#if IS_IN (libc)
|
||||
# define fgets_unlocked __fgets_unlocked
|
||||
@@ -577,7 +578,16 @@ _res_hconf_trim_domain (char *hostname)
|
||||
|
||||
for (i = 0; i < _res_hconf.num_trimdomains; ++i)
|
||||
{
|
||||
+ DIAG_PUSH_NEEDS_COMMENT
|
||||
+#if __GNUC_PREREQ (5, 0)
|
||||
+ /* GCC 5.0 warns about array subscript being above array bounds,
|
||||
+ but that's not entirely possible since i is limited to
|
||||
+ num_trimdomains which is limited to <= TRIMDOMAINS_MAX. This
|
||||
+ is likely PR/59124 which is still not fixed. */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Warray-bounds")
|
||||
+#endif
|
||||
const char *trim = _res_hconf.trimdomain[i];
|
||||
+ DIAG_POP_NEEDS_COMMENT
|
||||
|
||||
trim_len = strlen (trim);
|
||||
if (hostname_len > trim_len
|
@ -1,19 +0,0 @@
|
||||
--- glibc-2.18-151-g303e567.orig/elf/ldconfig.c 2013-09-25 14:01:01.522446341 -0400
|
||||
+++ glibc-2.18-151-g303e567/elf/ldconfig.c 2013-09-25 14:06:31.094218857 -0400
|
||||
@@ -959,6 +959,16 @@
|
||||
|| dlib_ptr->flag == FLAG_ELF_LIBC6)
|
||||
&& flag == FLAG_ELF)
|
||||
dlib_ptr->flag = flag;
|
||||
+#ifdef __arm__
|
||||
+ /* In Fedora 20 binutils regressed temporarily and failed to
|
||||
+ mark hard ABI objects with the correct flag. Therefore we
|
||||
+ must accept unmarked objects that were previously marked
|
||||
+ hard ABI. We can remove this check once the entire distribution
|
||||
+ has been rebuilt. */
|
||||
+ else if (dlib_ptr->flag & FLAG_ARM_LIBHF &&
|
||||
+ (flag == FLAG_ELF_LIBC6))
|
||||
+ ;
|
||||
+#endif
|
||||
else
|
||||
error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
|
||||
dlib_ptr->name, direntry->d_name,
|
@ -1,90 +0,0 @@
|
||||
#
|
||||
# Posted upstream:
|
||||
# https://sourceware.org/ml/libc-alpha/2013-10/msg00065.html
|
||||
#
|
||||
# This is related to bug 1013801 in that it fixes the problem
|
||||
# by modifying the runtime. In bug 1013801 we have libselinux
|
||||
# using pthread_atfork which pulls in libpthread, but we don't
|
||||
# want that, we want libpthread to be pulled in only when
|
||||
# actually needed by the application. This patch makes it
|
||||
# possible to avoid requiring libpthread and still use
|
||||
# pthread_atfork.
|
||||
#
|
||||
# The general idea for the design is in the leading comment
|
||||
# in the source code.
|
||||
#
|
||||
diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile
|
||||
index 6078e2d..36fd50b 100644
|
||||
--- a/nptl/Makefile
|
||||
+++ b/nptl/Makefile
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \
|
||||
libc-cleanup libc_pthread_init libc_multiple_threads \
|
||||
- register-atfork unregister-atfork
|
||||
+ register-atfork unregister-atfork libc_pthread_atfork
|
||||
+
|
||||
+static-only-routines += libc_pthread_atfork
|
||||
shared-only-routines = forward
|
||||
|
||||
libpthread-routines = nptl-init vars events version pt-interp \
|
||||
diff --git a/nptl/libc_pthread_atfork.c b/nptl/libc_pthread_atfork.c
|
||||
new file mode 100644
|
||||
index 0000000..667049a
|
||||
--- /dev/null
|
||||
+++ b/nptl/libc_pthread_atfork.c
|
||||
@@ -0,0 +1,54 @@
|
||||
+/* Copyright (C) 2013 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* The standard design pattern for making it optional to link against
|
||||
+ libpthread is to mark the function weak, test if the function
|
||||
+ address is non-zero and call the function, otherwise use a fallback.
|
||||
+ The problem with pthread_atfork is that there is no viable
|
||||
+ fallback. If you need to do something during fork it has to be done
|
||||
+ via pthread_atfork. This makes having libpthread optional and using
|
||||
+ pthread_atfork impossible. We make it possible by providing
|
||||
+ pthread_atfork in libc_nonshared.a. The real work of pthread_atfork
|
||||
+ is done by __register_atfork which is already provided in
|
||||
+ libc_nonshared.a. It's included in libc_nonshared.a because
|
||||
+ __dso_handle has to be unique to each DSO such that unloading the DSO
|
||||
+ can unregister the atfork handlers. We build pthread_atfork again
|
||||
+ under a different file name and include it into libc_nonshared.a and
|
||||
+ libc.a. We keep pthread_atfork in libpthread_nonshared.a and
|
||||
+ libpthread.a for compatibility and completeness.
|
||||
+
|
||||
+ Applications that can't rely on a new glibc should use the following
|
||||
+ code to optionally include libpthread and still register a function
|
||||
+ via pthread_atfork i.e. use __register_atfork directly:
|
||||
+
|
||||
+ extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
|
||||
+ extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
|
||||
+
|
||||
+ static int __app_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
|
||||
+ {
|
||||
+ return __register_atfork (prepare, parent, child,
|
||||
+ &__dso_handle == NULL ? NULL : __dso_handle);
|
||||
+ }
|
||||
+
|
||||
+ This code requires glibc 2.3.2 or newer. Previous to 2.3.2 no such
|
||||
+ interfaces exist and at that point is is impossible to have an
|
||||
+ optional libpthread and call pthread_atfork.
|
||||
+
|
||||
+ This code adds no more ABI requirements than already exist since
|
||||
+ __dso_handle and __register_atfork are already part of the ABI. */
|
||||
+#include <pthread_atfork.c>
|
@ -1,47 +0,0 @@
|
||||
commit 403ce35141da511898cde550f48ebc68a2a3ac82
|
||||
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
Date: Mon Jan 6 14:37:21 2014 +0530
|
||||
|
||||
Fix infinite loop in ftell when writing wide char data (BZ #16398)
|
||||
|
||||
ftell tries to avoid flushing the buffer when it is in write mode by
|
||||
converting the wide char data and placing it into the binary buffer.
|
||||
If the output buffer space is full and there is data to write, the
|
||||
code reverts to flushing the buffer. This breaks when there is space
|
||||
in the buffer but it is not enough to convert the next character in
|
||||
the wide data buffer, due to which __codecvt_do_out returns a
|
||||
__codecvt_partial status. In this case, ftell keeps running in an
|
||||
infinite loop.
|
||||
|
||||
The fix here is to detect the __codecvt_partial status in addition to
|
||||
checking if the buffer is full.
|
||||
|
||||
diff --git a/libio/wfileops.c b/libio/wfileops.c
|
||||
index 87d3cdc..877fc1f 100644
|
||||
--- a/libio/wfileops.c
|
||||
+++ b/libio/wfileops.c
|
||||
@@ -715,7 +715,7 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
- fp->_wide_data->_IO_write_base) / clen;
|
||||
else
|
||||
{
|
||||
- enum __codecvt_result status;
|
||||
+ enum __codecvt_result status = __codecvt_ok;
|
||||
delta = (fp->_wide_data->_IO_write_ptr
|
||||
- fp->_wide_data->_IO_write_base);
|
||||
const wchar_t *write_base = fp->_wide_data->_IO_write_base;
|
||||
@@ -728,9 +728,12 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
flush buffers for every ftell. */
|
||||
do
|
||||
{
|
||||
- /* Ugh, no point trying to avoid the flush. Just do it
|
||||
- and go back to how it was with the read mode. */
|
||||
- if (delta > 0 && new_write_ptr == fp->_IO_buf_end)
|
||||
+ /* There is not enough space in the buffer to do the entire
|
||||
+ conversion, so there is no point trying to avoid the
|
||||
+ buffer flush. Just do it and go back to how it was with
|
||||
+ the read mode. */
|
||||
+ if (status == __codecvt_partial
|
||||
+ || (delta > 0 && new_write_ptr == fp->_IO_buf_end))
|
||||
{
|
||||
if (_IO_switch_to_wget_mode (fp))
|
||||
return WEOF;
|
@ -1,836 +0,0 @@
|
||||
commit 03425ba6ab17b87b2c64f0d7b47fb0b86add9993
|
||||
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
Date: Thu Feb 20 15:41:18 2014 +0530
|
||||
|
||||
Separate ftell from fseek logic and avoid modifying FILE data (#16532)
|
||||
|
||||
ftell semantics are distinct from fseek(SEEK_CUR) especially when it
|
||||
is called on a file handler that is not yet active. Due to this
|
||||
caveat, much care needs to be taken while modifying the handler data
|
||||
and hence, this first iteration on separating out ftell focusses on
|
||||
maintaining handler data integrity at all times while it figures out
|
||||
the current stream offset. The result is that it makes a syscall for
|
||||
every offset request.
|
||||
|
||||
There is scope for optimizing this by caching offsets when we know
|
||||
that the handler is active. A simple way to find out is when the
|
||||
buffers have data. It is not so simple to find this out when the
|
||||
buffer is empty without adding some kind of flag.
|
||||
|
||||
diff --git a/libio/Makefile b/libio/Makefile
|
||||
index 8c333ce..8ccd80f 100644
|
||||
--- a/libio/Makefile
|
||||
+++ b/libio/Makefile
|
||||
@@ -60,7 +60,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
|
||||
tst-wmemstream1 tst-wmemstream2 \
|
||||
bug-memstream1 bug-wmemstream1 \
|
||||
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
|
||||
- tst-fwrite-error tst-ftell-partial-wide
|
||||
+ tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler
|
||||
ifeq (yes,$(build-shared))
|
||||
# Add test-fopenloc only if shared library is enabled since it depends on
|
||||
# shared localedata objects.
|
||||
diff --git a/libio/fileops.c b/libio/fileops.c
|
||||
index a3499be..a177302 100644
|
||||
--- a/libio/fileops.c
|
||||
+++ b/libio/fileops.c
|
||||
@@ -931,6 +931,59 @@ _IO_file_sync_mmap (_IO_FILE *fp)
|
||||
|
||||
|
||||
_IO_off64_t
|
||||
+get_file_offset (_IO_FILE *fp)
|
||||
+{
|
||||
+ if ((fp->_flags & _IO_IS_APPENDING) == _IO_IS_APPENDING)
|
||||
+ {
|
||||
+ struct stat64 st;
|
||||
+ bool ret = (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode));
|
||||
+ if (ret)
|
||||
+ return st.st_size;
|
||||
+ else
|
||||
+ return EOF;
|
||||
+ }
|
||||
+ else
|
||||
+ return _IO_SYSSEEK (fp, 0, _IO_seek_cur);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* ftell{,o} implementation. Don't modify any state of the file pointer while
|
||||
+ we try to get the current state of the stream. */
|
||||
+static _IO_off64_t
|
||||
+do_ftell (_IO_FILE *fp)
|
||||
+{
|
||||
+ _IO_off64_t result;
|
||||
+
|
||||
+ result = get_file_offset (fp);
|
||||
+
|
||||
+ if (result == EOF)
|
||||
+ return result;
|
||||
+
|
||||
+ /* No point looking at unflushed data if we haven't allocated buffers
|
||||
+ yet. */
|
||||
+ if (fp->_IO_buf_base != NULL)
|
||||
+ {
|
||||
+ bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
|
||||
+ || _IO_in_put_mode (fp));
|
||||
+
|
||||
+ /* Adjust for unflushed data. */
|
||||
+ if (!was_writing)
|
||||
+ result -= fp->_IO_read_end - fp->_IO_read_ptr;
|
||||
+ else
|
||||
+ result += fp->_IO_write_ptr - fp->_IO_read_end;
|
||||
+ }
|
||||
+
|
||||
+ if (result < 0)
|
||||
+ {
|
||||
+ __set_errno (EINVAL);
|
||||
+ return EOF;
|
||||
+ }
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+_IO_off64_t
|
||||
_IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
_IO_FILE *fp;
|
||||
_IO_off64_t offset;
|
||||
@@ -940,6 +993,13 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
_IO_off64_t result;
|
||||
_IO_off64_t delta, new_offset;
|
||||
long count;
|
||||
+
|
||||
+ /* Short-circuit into a separate function. We don't want to mix any
|
||||
+ functionality and we don't want to touch anything inside the FILE
|
||||
+ object. */
|
||||
+ if (mode == 0)
|
||||
+ return do_ftell (fp);
|
||||
+
|
||||
/* POSIX.1 8.2.3.7 says that after a call the fflush() the file
|
||||
offset of the underlying file must be exact. */
|
||||
int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
|
||||
@@ -948,9 +1008,6 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
|
||||
|| _IO_in_put_mode (fp));
|
||||
|
||||
- if (mode == 0)
|
||||
- dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
|
||||
-
|
||||
/* Flush unwritten characters.
|
||||
(This may do an unneeded write if we seek within the buffer.
|
||||
But to be able to switch to reading, we would need to set
|
||||
@@ -958,7 +1015,7 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
which assumes file_ptr() is eGptr. Anyway, since we probably
|
||||
end up flushing when we close(), it doesn't make much difference.)
|
||||
FIXME: simulate mem-mapped files. */
|
||||
- else if (was_writing && _IO_switch_to_get_mode (fp))
|
||||
+ if (was_writing && _IO_switch_to_get_mode (fp))
|
||||
return EOF;
|
||||
|
||||
if (fp->_IO_buf_base == NULL)
|
||||
@@ -978,30 +1035,10 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
{
|
||||
case _IO_seek_cur:
|
||||
/* Adjust for read-ahead (bytes is buffer). */
|
||||
- if (mode != 0 || !was_writing)
|
||||
- offset -= fp->_IO_read_end - fp->_IO_read_ptr;
|
||||
- else
|
||||
- {
|
||||
- /* _IO_read_end coincides with fp._offset, so the actual file position
|
||||
- is fp._offset - (_IO_read_end - new_write_ptr). This is fine
|
||||
- even if fp._offset is not set, since fp->_IO_read_end is then at
|
||||
- _IO_buf_base and this adjustment is for unbuffered output. */
|
||||
- offset -= fp->_IO_read_end - fp->_IO_write_ptr;
|
||||
- }
|
||||
+ offset -= fp->_IO_read_end - fp->_IO_read_ptr;
|
||||
|
||||
if (fp->_offset == _IO_pos_BAD)
|
||||
- {
|
||||
- if (mode != 0)
|
||||
- goto dumb;
|
||||
- else
|
||||
- {
|
||||
- result = _IO_SYSSEEK (fp, 0, dir);
|
||||
- if (result == EOF)
|
||||
- return result;
|
||||
-
|
||||
- fp->_offset = result;
|
||||
- }
|
||||
- }
|
||||
+ goto dumb;
|
||||
/* Make offset absolute, assuming current pointer is file_ptr(). */
|
||||
offset += fp->_offset;
|
||||
if (offset < 0)
|
||||
@@ -1028,10 +1065,6 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
||||
}
|
||||
/* At this point, dir==_IO_seek_set. */
|
||||
|
||||
- /* If we are only interested in the current position we've found it now. */
|
||||
- if (mode == 0)
|
||||
- return offset;
|
||||
-
|
||||
/* If destination is within current buffer, optimize: */
|
||||
if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
|
||||
&& !_IO_in_backup (fp))
|
||||
diff --git a/libio/libioP.h b/libio/libioP.h
|
||||
index 4ca723c..8a7b85b 100644
|
||||
--- a/libio/libioP.h
|
||||
+++ b/libio/libioP.h
|
||||
@@ -397,6 +397,7 @@ extern void _IO_wdoallocbuf (_IO_FILE *) __THROW;
|
||||
libc_hidden_proto (_IO_wdoallocbuf)
|
||||
extern void _IO_unsave_wmarkers (_IO_FILE *) __THROW;
|
||||
extern unsigned _IO_adjust_wcolumn (unsigned, const wchar_t *, int) __THROW;
|
||||
+extern _IO_off64_t get_file_offset (_IO_FILE *fp);
|
||||
|
||||
/* Marker-related function. */
|
||||
|
||||
diff --git a/libio/tst-ftell-active-handler.c b/libio/tst-ftell-active-handler.c
|
||||
new file mode 100644
|
||||
index 0000000..aac2923
|
||||
--- /dev/null
|
||||
+++ b/libio/tst-ftell-active-handler.c
|
||||
@@ -0,0 +1,366 @@
|
||||
+/* Verify that ftell returns the correct value at various points before and
|
||||
+ after the handler on which it is called becomes active.
|
||||
+ Copyright (C) 2014 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <errno.h>
|
||||
+#include <unistd.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <locale.h>
|
||||
+#include <wchar.h>
|
||||
+
|
||||
+static int do_test (void);
|
||||
+
|
||||
+#define TEST_FUNCTION do_test ()
|
||||
+#include "../test-skeleton.c"
|
||||
+
|
||||
+#define get_handles_fdopen(filename, fd, fp, fd_mode, mode) \
|
||||
+({ \
|
||||
+ int ret = 0; \
|
||||
+ (fd) = open ((filename), (fd_mode), 0); \
|
||||
+ if ((fd) == -1) \
|
||||
+ { \
|
||||
+ printf ("open failed: %m\n"); \
|
||||
+ ret = 1; \
|
||||
+ } \
|
||||
+ else \
|
||||
+ { \
|
||||
+ (fp) = fdopen ((fd), (mode)); \
|
||||
+ if ((fp) == NULL) \
|
||||
+ { \
|
||||
+ printf ("fdopen failed: %m\n"); \
|
||||
+ close (fd); \
|
||||
+ ret = 1; \
|
||||
+ } \
|
||||
+ } \
|
||||
+ ret; \
|
||||
+})
|
||||
+
|
||||
+#define get_handles_fopen(filename, fd, fp, mode) \
|
||||
+({ \
|
||||
+ int ret = 0; \
|
||||
+ (fp) = fopen ((filename), (mode)); \
|
||||
+ if ((fp) == NULL) \
|
||||
+ { \
|
||||
+ printf ("fopen failed: %m\n"); \
|
||||
+ ret = 1; \
|
||||
+ } \
|
||||
+ else \
|
||||
+ { \
|
||||
+ (fd) = fileno (fp); \
|
||||
+ if ((fd) == -1) \
|
||||
+ { \
|
||||
+ printf ("fileno failed: %m\n"); \
|
||||
+ ret = 1; \
|
||||
+ } \
|
||||
+ } \
|
||||
+ ret; \
|
||||
+})
|
||||
+
|
||||
+static const void *data;
|
||||
+static const char *char_data = "abcdef";
|
||||
+static const wchar_t *wide_data = L"abcdef";
|
||||
+static size_t data_len;
|
||||
+/* Maintain the current file length for validation. */
|
||||
+static size_t file_len;
|
||||
+
|
||||
+typedef int (*fputs_func_t) (const void *data, FILE *fp);
|
||||
+fputs_func_t fputs_func;
|
||||
+
|
||||
+/* Test that the value of ftell is not cached when the stream handle is not
|
||||
+ active. */
|
||||
+static int
|
||||
+do_ftell_test (const char *filename)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ struct test
|
||||
+ {
|
||||
+ const char *mode;
|
||||
+ int fd_mode;
|
||||
+ size_t old_off;
|
||||
+ size_t new_off;
|
||||
+ } test_modes[] = {
|
||||
+ {"w", O_WRONLY, 0, data_len},
|
||||
+ {"w+", O_RDWR, 0, data_len},
|
||||
+ {"r+", O_RDWR, 0, data_len},
|
||||
+ {"a", O_WRONLY, data_len, 2 * data_len},
|
||||
+ {"a+", O_RDWR, 2 * data_len, 3 * data_len},
|
||||
+ };
|
||||
+ for (int j = 0; j < 2; j++)
|
||||
+ {
|
||||
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
|
||||
+ {
|
||||
+ FILE *fp;
|
||||
+ int fd;
|
||||
+ printf ("\tftell: %s (file, \"%s\"): ", j == 0 ? "fdopen" : "fopen",
|
||||
+ test_modes[i].mode);
|
||||
+
|
||||
+ if (j == 0)
|
||||
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
|
||||
+ test_modes[i].mode);
|
||||
+ else
|
||||
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
|
||||
+
|
||||
+ if (ret != 0)
|
||||
+ return 1;
|
||||
+
|
||||
+ long off = ftell (fp);
|
||||
+ if (off != test_modes[i].old_off)
|
||||
+ {
|
||||
+ printf ("Incorrect old offset. Expected %zu but got %ld, ",
|
||||
+ test_modes[i].old_off, off);
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+ else
|
||||
+ printf ("old offset = %ld, ", off);
|
||||
+
|
||||
+ int ret = write (fd, data, data_len);
|
||||
+ off = ftell (fp);
|
||||
+
|
||||
+ if (off != test_modes[i].new_off)
|
||||
+ {
|
||||
+ printf ("Incorrect new offset. Expected %zu but got %ld\n",
|
||||
+ test_modes[i].old_off, off);
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+ else
|
||||
+ printf ("new offset = %ld\n", off);
|
||||
+
|
||||
+ fclose (fp);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* This test opens the file for writing, moves the file offset of the
|
||||
+ underlying file, writes out data and then checks if ftell trips on it. */
|
||||
+static int
|
||||
+do_write_test (const char *filename)
|
||||
+{
|
||||
+ FILE *fp = NULL;
|
||||
+ int fd;
|
||||
+ int ret = 0;
|
||||
+ struct test
|
||||
+ {
|
||||
+ const char *mode;
|
||||
+ int fd_mode;
|
||||
+ } test_modes[] = {
|
||||
+ {"w", O_WRONLY},
|
||||
+ {"w+", O_RDWR},
|
||||
+ {"r+", O_RDWR}
|
||||
+ };
|
||||
+
|
||||
+ for (int j = 0; j < 2; j++)
|
||||
+ {
|
||||
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
|
||||
+ {
|
||||
+ printf ("\twrite: %s (file, \"%s\"): ", j == 0 ? "fopen" : "fdopen",
|
||||
+ test_modes[i].mode);
|
||||
+
|
||||
+ if (j == 0)
|
||||
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
|
||||
+ else
|
||||
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
|
||||
+ test_modes[i].mode);
|
||||
+
|
||||
+ if (ret != 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Move offset to just before the end of the file. */
|
||||
+ off_t ret = lseek (fd, file_len - 1, SEEK_SET);
|
||||
+ if (ret == -1)
|
||||
+ {
|
||||
+ printf ("lseek failed: %m\n");
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Write some data. */
|
||||
+ size_t written = fputs_func (data, fp);
|
||||
+
|
||||
+ if (written == EOF)
|
||||
+ {
|
||||
+ printf ("fputs[1] failed to write data\n");
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Verify that the offset points to the end of the file. */
|
||||
+ long offset = ftell (fp);
|
||||
+ file_len = file_len - 1 + data_len;
|
||||
+
|
||||
+ if (offset != file_len)
|
||||
+ {
|
||||
+ printf ("Incorrect offset. Expected %zu, but got %ld\n",
|
||||
+ file_len, offset);
|
||||
+
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+
|
||||
+ printf ("offset = %ld\n", offset);
|
||||
+ fclose (fp);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* This test opens a file in append mode, writes some data, and then verifies
|
||||
+ that ftell does not trip over it. */
|
||||
+static int
|
||||
+do_append_test (const char *filename)
|
||||
+{
|
||||
+ FILE *fp = NULL;
|
||||
+ int ret = 0;
|
||||
+ int fd;
|
||||
+
|
||||
+ struct test
|
||||
+ {
|
||||
+ const char *mode;
|
||||
+ int fd_mode;
|
||||
+ } test_modes[] = {
|
||||
+ {"a", O_WRONLY},
|
||||
+ {"a+", O_RDWR}
|
||||
+ };
|
||||
+
|
||||
+ for (int j = 0; j < 2; j++)
|
||||
+ {
|
||||
+ for (int i = 0; i < sizeof (test_modes) / sizeof (struct test); i++)
|
||||
+ {
|
||||
+ printf ("\tappend: %s (file, \"%s\"): ", j == 0 ? "fopen" : "fdopen",
|
||||
+ test_modes[i].mode);
|
||||
+
|
||||
+ if (j == 0)
|
||||
+ ret = get_handles_fopen (filename, fd, fp, test_modes[i].mode);
|
||||
+ else
|
||||
+ ret = get_handles_fdopen (filename, fd, fp, test_modes[i].fd_mode,
|
||||
+ test_modes[i].mode);
|
||||
+
|
||||
+ if (ret != 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Write some data. */
|
||||
+ size_t written = fputs_func (data, fp);
|
||||
+
|
||||
+ if (written == EOF)
|
||||
+ {
|
||||
+ printf ("fputs[1] failed to write all data\n");
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Verify that the offset points to the end of the file. */
|
||||
+ long offset = ftell (fp);
|
||||
+ file_len += data_len;
|
||||
+
|
||||
+ if (offset != file_len)
|
||||
+ {
|
||||
+ printf ("Incorrect offset. Expected %zu, but got %ld\n",
|
||||
+ file_len, offset);
|
||||
+
|
||||
+ ret |= 1;
|
||||
+ }
|
||||
+
|
||||
+ printf ("offset = %ld\n", offset);
|
||||
+ fclose (fp);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_one_test (const char *filename)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ ret |= do_ftell_test (filename);
|
||||
+ ret |= do_write_test (filename);
|
||||
+ ret |= do_append_test (filename);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ FILE *fp = NULL;
|
||||
+ char *filename;
|
||||
+ size_t written;
|
||||
+ int fd = create_temp_file ("tst-active-handler-tmp.", &filename);
|
||||
+
|
||||
+ if (fd == -1)
|
||||
+ {
|
||||
+ printf ("create_temp_file: %m\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ fp = fdopen (fd, "w");
|
||||
+ if (fp == NULL)
|
||||
+ {
|
||||
+ printf ("fdopen[0]: %m\n");
|
||||
+ close (fd);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ data = char_data;
|
||||
+ data_len = strlen (char_data);
|
||||
+ file_len = strlen (char_data);
|
||||
+ written = fputs (data, fp);
|
||||
+
|
||||
+ if (written == EOF)
|
||||
+ {
|
||||
+ printf ("fputs[1] failed to write data\n");
|
||||
+ ret = 1;
|
||||
+ }
|
||||
+
|
||||
+ fclose (fp);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Tests for regular files. */
|
||||
+ puts ("Regular mode:");
|
||||
+ fputs_func = (fputs_func_t) fputs;
|
||||
+ data = char_data;
|
||||
+ data_len = strlen (char_data);
|
||||
+ ret |= do_one_test (filename);
|
||||
+
|
||||
+ /* Truncate the file before repeating the tests in wide mode. */
|
||||
+ fp = fopen (filename, "w");
|
||||
+ if (fp == NULL)
|
||||
+ {
|
||||
+ printf ("fopen failed %m\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ fclose (fp);
|
||||
+
|
||||
+ /* Tests for wide files. */
|
||||
+ puts ("Wide mode:");
|
||||
+ if (setlocale (LC_ALL, "en_US.UTF-8") == NULL)
|
||||
+ {
|
||||
+ printf ("Cannot set en_US.UTF-8 locale.\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ fputs_func = (fputs_func_t) fputws;
|
||||
+ data = wide_data;
|
||||
+ data_len = wcslen (wide_data);
|
||||
+ ret |= do_one_test (filename);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
diff --git a/libio/wfileops.c b/libio/wfileops.c
|
||||
index 9cebe77..eda7828 100644
|
||||
--- a/libio/wfileops.c
|
||||
+++ b/libio/wfileops.c
|
||||
@@ -596,29 +596,22 @@ done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
-_IO_off64_t
|
||||
-_IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
- _IO_FILE *fp;
|
||||
- _IO_off64_t offset;
|
||||
- int dir;
|
||||
- int mode;
|
||||
+static _IO_off64_t
|
||||
+do_ftell_wide (_IO_FILE *fp)
|
||||
{
|
||||
- _IO_off64_t result;
|
||||
- _IO_off64_t delta, new_offset;
|
||||
- long int count;
|
||||
- /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
|
||||
- offset of the underlying file must be exact. */
|
||||
- int must_be_exact = ((fp->_wide_data->_IO_read_base
|
||||
- == fp->_wide_data->_IO_read_end)
|
||||
- && (fp->_wide_data->_IO_write_base
|
||||
- == fp->_wide_data->_IO_write_ptr));
|
||||
+ _IO_off64_t result, offset = 0;
|
||||
|
||||
- bool was_writing = ((fp->_wide_data->_IO_write_ptr
|
||||
- > fp->_wide_data->_IO_write_base)
|
||||
- || _IO_in_put_mode (fp));
|
||||
-
|
||||
- if (mode == 0)
|
||||
+ /* No point looking for offsets in the buffer if it hasn't even been
|
||||
+ allocated. */
|
||||
+ if (fp->_wide_data->_IO_buf_base != NULL)
|
||||
{
|
||||
+ const wchar_t *wide_read_base;
|
||||
+ const wchar_t *wide_read_ptr;
|
||||
+ const wchar_t *wide_read_end;
|
||||
+ bool was_writing = ((fp->_wide_data->_IO_write_ptr
|
||||
+ > fp->_wide_data->_IO_write_base)
|
||||
+ || _IO_in_put_mode (fp));
|
||||
+
|
||||
/* XXX For wide stream with backup store it is not very
|
||||
reasonable to determine the offset. The pushed-back
|
||||
character might require a state change and we need not be
|
||||
@@ -633,14 +626,117 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
return -1;
|
||||
}
|
||||
|
||||
- /* There is no more data in the backup buffer. We can
|
||||
- switch back. */
|
||||
- _IO_switch_to_main_wget_area (fp);
|
||||
+ /* Nothing in the backup store, so note the backed up pointers
|
||||
+ without changing the state. */
|
||||
+ wide_read_base = fp->_wide_data->_IO_save_base;
|
||||
+ wide_read_ptr = wide_read_base;
|
||||
+ wide_read_end = fp->_wide_data->_IO_save_end;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ wide_read_base = fp->_wide_data->_IO_read_base;
|
||||
+ wide_read_ptr = fp->_wide_data->_IO_read_ptr;
|
||||
+ wide_read_end = fp->_wide_data->_IO_read_end;
|
||||
}
|
||||
|
||||
- dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
|
||||
+ struct _IO_codecvt *cv = fp->_codecvt;
|
||||
+ int clen = (*cv->__codecvt_do_encoding) (cv);
|
||||
+
|
||||
+ if (!was_writing)
|
||||
+ {
|
||||
+ if (clen > 0)
|
||||
+ {
|
||||
+ offset -= (wide_read_end - wide_read_ptr) * clen;
|
||||
+ offset -= fp->_IO_read_end - fp->_IO_read_ptr;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ int nread;
|
||||
+
|
||||
+ size_t delta = wide_read_ptr - wide_read_base;
|
||||
+ __mbstate_t state = fp->_wide_data->_IO_last_state;
|
||||
+ nread = (*cv->__codecvt_do_length) (cv, &state,
|
||||
+ fp->_IO_read_base,
|
||||
+ fp->_IO_read_end, delta);
|
||||
+ offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (clen > 0)
|
||||
+ offset += (fp->_wide_data->_IO_write_ptr
|
||||
+ - fp->_wide_data->_IO_write_base) * clen;
|
||||
+ else
|
||||
+ {
|
||||
+ size_t delta = (fp->_wide_data->_IO_write_ptr
|
||||
+ - fp->_wide_data->_IO_write_base);
|
||||
+
|
||||
+ /* Allocate enough space for the conversion. */
|
||||
+ size_t outsize = delta * sizeof (wchar_t);
|
||||
+ char *out = malloc (outsize);
|
||||
+ char *outstop = out;
|
||||
+ const wchar_t *in = fp->_wide_data->_IO_write_base;
|
||||
+
|
||||
+ enum __codecvt_result status;
|
||||
+
|
||||
+ __mbstate_t state = fp->_wide_data->_IO_last_state;
|
||||
+ status = (*cv->__codecvt_do_out) (cv, &state,
|
||||
+ in, in + delta, &in,
|
||||
+ out, out + outsize, &outstop);
|
||||
+
|
||||
+ /* We don't check for __codecvt_partial because it can be
|
||||
+ returned on one of two conditions: either the output
|
||||
+ buffer is full or the input sequence is incomplete. We
|
||||
+ take care to allocate enough buffer and our input
|
||||
+ sequences must be complete since they are accepted as
|
||||
+ wchar_t; if not, then that is an error. */
|
||||
+ if (__glibc_unlikely (status != __codecvt_ok))
|
||||
+ return WEOF;
|
||||
+
|
||||
+ offset += outstop - out;
|
||||
+ }
|
||||
+
|
||||
+ /* _IO_read_end coincides with fp._offset, so the actual file position
|
||||
+ is fp._offset - (_IO_read_end - new_write_ptr). */
|
||||
+ offset -= fp->_IO_read_end - fp->_IO_write_ptr;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ result = get_file_offset (fp);
|
||||
+
|
||||
+ if (result == EOF)
|
||||
+ return result;
|
||||
+
|
||||
+ result += offset;
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+_IO_off64_t
|
||||
+_IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
+ _IO_FILE *fp;
|
||||
+ _IO_off64_t offset;
|
||||
+ int dir;
|
||||
+ int mode;
|
||||
+{
|
||||
+ _IO_off64_t result;
|
||||
+ _IO_off64_t delta, new_offset;
|
||||
+ long int count;
|
||||
+
|
||||
+ if (mode == 0)
|
||||
+ return do_ftell_wide (fp);
|
||||
+
|
||||
+ /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
|
||||
+ offset of the underlying file must be exact. */
|
||||
+ int must_be_exact = ((fp->_wide_data->_IO_read_base
|
||||
+ == fp->_wide_data->_IO_read_end)
|
||||
+ && (fp->_wide_data->_IO_write_base
|
||||
+ == fp->_wide_data->_IO_write_ptr));
|
||||
+
|
||||
+ bool was_writing = ((fp->_wide_data->_IO_write_ptr
|
||||
+ > fp->_wide_data->_IO_write_base)
|
||||
+ || _IO_in_put_mode (fp));
|
||||
+
|
||||
/* Flush unwritten characters.
|
||||
(This may do an unneeded write if we seek within the buffer.
|
||||
But to be able to switch to reading, we would need to set
|
||||
@@ -648,7 +744,7 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
which assumes file_ptr() is eGptr. Anyway, since we probably
|
||||
end up flushing when we close(), it doesn't make much difference.)
|
||||
FIXME: simulate mem-mapped files. */
|
||||
- else if (was_writing && _IO_switch_to_wget_mode (fp))
|
||||
+ if (was_writing && _IO_switch_to_wget_mode (fp))
|
||||
return WEOF;
|
||||
|
||||
if (fp->_wide_data->_IO_buf_base == NULL)
|
||||
@@ -693,7 +789,6 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
{
|
||||
int nread;
|
||||
|
||||
- flushed:
|
||||
delta = (fp->_wide_data->_IO_read_ptr
|
||||
- fp->_wide_data->_IO_read_base);
|
||||
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
|
||||
@@ -706,80 +801,9 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
|
||||
}
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- char *new_write_ptr = fp->_IO_write_ptr;
|
||||
-
|
||||
- if (clen > 0)
|
||||
- offset += (fp->_wide_data->_IO_write_ptr
|
||||
- - fp->_wide_data->_IO_write_base) / clen;
|
||||
- else
|
||||
- {
|
||||
- enum __codecvt_result status = __codecvt_ok;
|
||||
- delta = (fp->_wide_data->_IO_write_ptr
|
||||
- - fp->_wide_data->_IO_write_base);
|
||||
- const wchar_t *write_base = fp->_wide_data->_IO_write_base;
|
||||
-
|
||||
- /* FIXME: This actually ends up in two iterations of conversion,
|
||||
- one here and the next when the buffer actually gets flushed.
|
||||
- It may be possible to optimize this in future so that
|
||||
- wdo_write identifies already converted content and does not
|
||||
- redo it. In any case, this is much better than having to
|
||||
- flush buffers for every ftell. */
|
||||
- do
|
||||
- {
|
||||
- /* There is not enough space in the buffer to do the entire
|
||||
- conversion, so there is no point trying to avoid the
|
||||
- buffer flush. Just do it and go back to how it was with
|
||||
- the read mode. */
|
||||
- if (status == __codecvt_partial
|
||||
- || (delta > 0 && new_write_ptr == fp->_IO_buf_end))
|
||||
- {
|
||||
- if (_IO_switch_to_wget_mode (fp))
|
||||
- return WEOF;
|
||||
- goto flushed;
|
||||
- }
|
||||
-
|
||||
- const wchar_t *new_wbase = fp->_wide_data->_IO_write_base;
|
||||
- fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
|
||||
- status = (*cv->__codecvt_do_out) (cv,
|
||||
- &fp->_wide_data->_IO_state,
|
||||
- write_base,
|
||||
- write_base + delta,
|
||||
- &new_wbase,
|
||||
- new_write_ptr,
|
||||
- fp->_IO_buf_end,
|
||||
- &new_write_ptr);
|
||||
-
|
||||
- delta -= new_wbase - write_base;
|
||||
-
|
||||
- /* If there was an error, then return WEOF.
|
||||
- TODO: set buffer state. */
|
||||
- if (__glibc_unlikely (status == __codecvt_error))
|
||||
- return WEOF;
|
||||
- }
|
||||
- while (delta > 0);
|
||||
- }
|
||||
-
|
||||
- /* _IO_read_end coincides with fp._offset, so the actual file position
|
||||
- is fp._offset - (_IO_read_end - new_write_ptr). This is fine
|
||||
- even if fp._offset is not set, since fp->_IO_read_end is then at
|
||||
- _IO_buf_base and this adjustment is for unbuffered output. */
|
||||
- offset -= fp->_IO_read_end - new_write_ptr;
|
||||
- }
|
||||
|
||||
if (fp->_offset == _IO_pos_BAD)
|
||||
- {
|
||||
- if (mode != 0)
|
||||
- goto dumb;
|
||||
- else
|
||||
- {
|
||||
- result = _IO_SYSSEEK (fp, 0, dir);
|
||||
- if (result == EOF)
|
||||
- return result;
|
||||
- fp->_offset = result;
|
||||
- }
|
||||
- }
|
||||
+ goto dumb;
|
||||
|
||||
/* Make offset absolute, assuming current pointer is file_ptr(). */
|
||||
offset += fp->_offset;
|
||||
@@ -802,10 +826,6 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
||||
}
|
||||
/* At this point, dir==_IO_seek_set. */
|
||||
|
||||
- /* If we are only interested in the current position we've found it now. */
|
||||
- if (mode == 0)
|
||||
- return offset;
|
||||
-
|
||||
/* If destination is within current buffer, optimize: */
|
||||
if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
|
||||
&& !_IO_in_backup (fp))
|
@ -1,183 +0,0 @@
|
||||
commit 4a68e8ded4fef2b00fbfc6baf1e79e46389871ca
|
||||
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
Date: Thu Feb 20 15:55:16 2014 +0530
|
||||
|
||||
Use cached offset in ftell when reliable
|
||||
|
||||
The cached offset is reliable to use in ftell when the stream handle
|
||||
is active. We can consider a stream as being active when there is
|
||||
unbuffered data. However, even in this case, we can use the cached
|
||||
offset only when the stream is not being written to in a+ mode,
|
||||
because this case may have unbuffered data and a stale offset; the
|
||||
previous read could have sent it off somewhere other than the end of
|
||||
the file.
|
||||
|
||||
There were a couple of adjustments necessary to get this to work.
|
||||
Firstly, fdopen now ceases to use _IO_attach_fd because it sets the
|
||||
offset cache to the current file position. This is not correct
|
||||
because there could be changes to the file descriptor before the
|
||||
stream handle is activated, which would not get reflected.
|
||||
|
||||
A similar offset caching action is done in _IO_fwide, claiming that
|
||||
wide streams have 'problems' with the file offsets. There don't seem
|
||||
to be any obvious problems with not having the offset cache available,
|
||||
other than that it will have to be queried in a subsequent
|
||||
read/write/seek. I have removed this as well.
|
||||
|
||||
The testsuite passes successfully with these changes on x86_64.
|
||||
|
||||
diff --git a/libio/fileops.c b/libio/fileops.c
|
||||
index a177302..c44a5da 100644
|
||||
--- a/libio/fileops.c
|
||||
+++ b/libio/fileops.c
|
||||
@@ -952,12 +952,8 @@ get_file_offset (_IO_FILE *fp)
|
||||
static _IO_off64_t
|
||||
do_ftell (_IO_FILE *fp)
|
||||
{
|
||||
- _IO_off64_t result;
|
||||
-
|
||||
- result = get_file_offset (fp);
|
||||
-
|
||||
- if (result == EOF)
|
||||
- return result;
|
||||
+ _IO_off64_t result = 0;
|
||||
+ bool use_cached_offset = false;
|
||||
|
||||
/* No point looking at unflushed data if we haven't allocated buffers
|
||||
yet. */
|
||||
@@ -971,8 +967,34 @@ do_ftell (_IO_FILE *fp)
|
||||
result -= fp->_IO_read_end - fp->_IO_read_ptr;
|
||||
else
|
||||
result += fp->_IO_write_ptr - fp->_IO_read_end;
|
||||
+
|
||||
+ /* It is safe to use the cached offset when available if there is
|
||||
+ unbuffered data (indicating that the file handle is active) and the
|
||||
+ handle is not for a file open in a+ mode. The latter condition is
|
||||
+ because there could be a scenario where there is a switch from read
|
||||
+ mode to write mode using an fseek to an arbitrary position. In this
|
||||
+ case, there would be unbuffered data due to be appended to the end of
|
||||
+ the file, but the offset may not necessarily be the end of the
|
||||
+ file. It is fine to use the cached offset when the a+ stream is in
|
||||
+ read mode though, since the offset is maintained correctly in that
|
||||
+ case. Note that this is not a comprehensive set of cases when the
|
||||
+ offset is reliable. The offset may be reliable even in some cases
|
||||
+ where there is no buffered input and the handle is active, but it's
|
||||
+ just that we don't have a way to identify that condition reliably. */
|
||||
+ use_cached_offset = (result != 0 && fp->_offset != _IO_pos_BAD
|
||||
+ && ((fp->_flags & (_IO_IS_APPENDING | _IO_NO_READS))
|
||||
+ == (_IO_IS_APPENDING | _IO_NO_READS)
|
||||
+ && was_writing));
|
||||
}
|
||||
|
||||
+ if (use_cached_offset)
|
||||
+ result += fp->_offset;
|
||||
+ else
|
||||
+ result += get_file_offset (fp);
|
||||
+
|
||||
+ if (result == EOF)
|
||||
+ return result;
|
||||
+
|
||||
if (result < 0)
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
diff --git a/libio/iofdopen.c b/libio/iofdopen.c
|
||||
index 066ff19..4525f0f 100644
|
||||
--- a/libio/iofdopen.c
|
||||
+++ b/libio/iofdopen.c
|
||||
@@ -141,9 +141,6 @@ _IO_new_fdopen (fd, mode)
|
||||
#ifdef _IO_MTSAFE_IO
|
||||
new_f->fp.file._lock = &new_f->lock;
|
||||
#endif
|
||||
- /* Set up initially to use the `maybe_mmap' jump tables rather than using
|
||||
- __fopen_maybe_mmap to do it, because we need them in place before we
|
||||
- call _IO_file_attach or else it will allocate a buffer immediately. */
|
||||
_IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd,
|
||||
#ifdef _G_HAVE_MMAP
|
||||
(use_mmap && (read_write & _IO_NO_WRITES))
|
||||
@@ -159,13 +156,10 @@ _IO_new_fdopen (fd, mode)
|
||||
#if !_IO_UNIFIED_JUMPTABLES
|
||||
new_f->fp.vtable = NULL;
|
||||
#endif
|
||||
- if (_IO_file_attach ((_IO_FILE *) &new_f->fp, fd) == NULL)
|
||||
- {
|
||||
- _IO_setb (&new_f->fp.file, NULL, NULL, 0);
|
||||
- _IO_un_link (&new_f->fp);
|
||||
- free (new_f);
|
||||
- return NULL;
|
||||
- }
|
||||
+ /* We only record the fd because _IO_file_init will have unset the offset.
|
||||
+ We don't need to get the current offset in the file now since it could
|
||||
+ change between now and when the handle is activated. */
|
||||
+ new_f->fp.file._fileno = fd;
|
||||
new_f->fp.file._flags &= ~_IO_DELETE_DONT_CLOSE;
|
||||
|
||||
_IO_mask_flags (&new_f->fp.file, read_write,
|
||||
diff --git a/libio/iofwide.c b/libio/iofwide.c
|
||||
index 5cff632..64187e4 100644
|
||||
--- a/libio/iofwide.c
|
||||
+++ b/libio/iofwide.c
|
||||
@@ -199,12 +199,6 @@ _IO_fwide (fp, mode)
|
||||
|
||||
/* From now on use the wide character callback functions. */
|
||||
((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable;
|
||||
-
|
||||
- /* One last twist: we get the current stream position. The wide
|
||||
- char streams have much more problems with not knowing the
|
||||
- current position and so we should disable the optimization
|
||||
- which allows the functions without knowing the position. */
|
||||
- fp->_offset = _IO_SYSSEEK (fp, 0, _IO_seek_cur);
|
||||
}
|
||||
|
||||
/* Set the mode now. */
|
||||
diff --git a/libio/wfileops.c b/libio/wfileops.c
|
||||
index eda7828..651f5ce 100644
|
||||
--- a/libio/wfileops.c
|
||||
+++ b/libio/wfileops.c
|
||||
@@ -600,6 +600,7 @@ static _IO_off64_t
|
||||
do_ftell_wide (_IO_FILE *fp)
|
||||
{
|
||||
_IO_off64_t result, offset = 0;
|
||||
+ bool use_cached_offset = false;
|
||||
|
||||
/* No point looking for offsets in the buffer if it hasn't even been
|
||||
allocated. */
|
||||
@@ -696,13 +697,36 @@ do_ftell_wide (_IO_FILE *fp)
|
||||
offset += outstop - out;
|
||||
}
|
||||
|
||||
- /* _IO_read_end coincides with fp._offset, so the actual file position
|
||||
- is fp._offset - (_IO_read_end - new_write_ptr). */
|
||||
+ /* _IO_read_end coincides with fp._offset, so the actual file
|
||||
+ position is fp._offset - (_IO_read_end - new_write_ptr). */
|
||||
offset -= fp->_IO_read_end - fp->_IO_write_ptr;
|
||||
+
|
||||
}
|
||||
+
|
||||
+ /* It is safe to use the cached offset when available if there is
|
||||
+ unbuffered data (indicating that the file handle is active) and
|
||||
+ the handle is not for a file open in a+ mode. The latter
|
||||
+ condition is because there could be a scenario where there is a
|
||||
+ switch from read mode to write mode using an fseek to an arbitrary
|
||||
+ position. In this case, there would be unbuffered data due to be
|
||||
+ appended to the end of the file, but the offset may not
|
||||
+ necessarily be the end of the file. It is fine to use the cached
|
||||
+ offset when the a+ stream is in read mode though, since the offset
|
||||
+ is maintained correctly in that case. Note that this is not a
|
||||
+ comprehensive set of cases when the offset is reliable. The
|
||||
+ offset may be reliable even in some cases where there is no
|
||||
+ buffered input and the handle is active, but it's just that we
|
||||
+ don't have a way to identify that condition reliably. */
|
||||
+ use_cached_offset = (offset != 0 && fp->_offset != _IO_pos_BAD
|
||||
+ && ((fp->_flags & (_IO_IS_APPENDING | _IO_NO_READS))
|
||||
+ == (_IO_IS_APPENDING | _IO_NO_READS)
|
||||
+ && was_writing));
|
||||
}
|
||||
|
||||
- result = get_file_offset (fp);
|
||||
+ if (use_cached_offset)
|
||||
+ result = fp->_offset;
|
||||
+ else
|
||||
+ result = get_file_offset (fp);
|
||||
|
||||
if (result == EOF)
|
||||
return result;
|
@ -1,3 +1,12 @@
|
||||
Short description: Add syslog.target dependency.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-Fedora: #1070416
|
||||
Upstream status: not-needed
|
||||
|
||||
Fedora-specific changes to the nscd.service file.
|
||||
See also: glibc-nscd-sysconfig.patch.
|
||||
|
||||
--- a/nscd/nscd.service
|
||||
+++ b/nscd/nscd.service
|
||||
@@ -2,6 +2,7 @@
|
||||
|
@ -1,47 +0,0 @@
|
||||
Upstream patch:
|
||||
|
||||
commit ff889b196575c2fbf6aa7130abb1ec862714ea4e
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Feb 19 14:21:34 2016 +0100
|
||||
|
||||
Remove trailing newline from date_fmt in Serbian locales [BZ #19581]
|
||||
|
||||
diff --git a/localedata/locales/sr_ME b/localedata/locales/sr_ME
|
||||
index 4f243dc..dd68df8 100644
|
||||
--- a/localedata/locales/sr_ME
|
||||
+++ b/localedata/locales/sr_ME
|
||||
@@ -119,7 +119,7 @@ am_pm "";""
|
||||
t_fmt_ampm "<U0025><U0054>"
|
||||
date_fmt "<U0025><U0061><U002c><U0020><U0025><U0065><U002E><U0020>/
|
||||
<U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
|
||||
-<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
|
||||
+<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
|
||||
week 7;19971130;4
|
||||
first_weekday 2
|
||||
first_workday 2
|
||||
diff --git a/localedata/locales/sr_RS b/localedata/locales/sr_RS
|
||||
index 2ae085b..ffea86f 100644
|
||||
--- a/localedata/locales/sr_RS
|
||||
+++ b/localedata/locales/sr_RS
|
||||
@@ -300,7 +300,7 @@ am_pm "";""
|
||||
t_fmt_ampm "<U0025><U0054>"
|
||||
date_fmt "<U0025><U0061><U002C><U0020><U0025><U0065><U002E><U0020>/
|
||||
<U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
|
||||
-<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
|
||||
+<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
|
||||
week 7;19971130;4
|
||||
first_weekday 2
|
||||
first_workday 2
|
||||
diff --git a/localedata/locales/sr_RS@latin b/localedata/locales/sr_RS@latin
|
||||
index da6628b..fd10ea6 100644
|
||||
--- a/localedata/locales/sr_RS@latin
|
||||
+++ b/localedata/locales/sr_RS@latin
|
||||
@@ -120,7 +120,7 @@ am_pm "";""
|
||||
t_fmt_ampm "<U0025><U0054>"
|
||||
date_fmt "<U0025><U0061><U002c><U0020><U0025><U0065><U002E><U0020>/
|
||||
<U0025><U0062><U0020><U0025><U0059><U002E><U0020><U0020><U0025><U0048>/
|
||||
-<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U000A>"
|
||||
+<U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A>"
|
||||
week 7;19971130;4
|
||||
first_weekday 2
|
||||
first_workday 2
|
@ -1,408 +0,0 @@
|
||||
Revert this upstream commit:
|
||||
|
||||
commit 2212c1420c92a33b0e0bd9a34938c9814a56c0f7
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Thu Feb 19 15:52:08 2015 +0100
|
||||
|
||||
Simplify handling of nameserver configuration in resolver
|
||||
|
||||
Remove use of ext.nsmap member of struct __res_state and always use
|
||||
an identity mapping betwen the nsaddr_list array and the ext.nsaddrs
|
||||
array. The fact that a nameserver has an IPv6 address is signalled by
|
||||
setting nsaddr_list[].sin_family to zero.
|
||||
|
||||
reverted:
|
||||
Index: b/resolv/res_init.c
|
||||
===================================================================
|
||||
--- a/resolv/res_init.c
|
||||
+++ b/resolv/res_init.c
|
||||
@@ -153,8 +153,10 @@ __res_vinit(res_state statp, int preinit
|
||||
char *cp, **pp;
|
||||
int n;
|
||||
char buf[BUFSIZ];
|
||||
- int nserv = 0; /* number of nameservers read from file */
|
||||
- int have_serv6 = 0;
|
||||
+ int nserv = 0; /* number of IPv4 nameservers read from file */
|
||||
+#ifdef _LIBC
|
||||
+ int nservall = 0; /* number of (IPv4 + IPV6) nameservers read from file */
|
||||
+#endif
|
||||
int haveenv = 0;
|
||||
int havesearch = 0;
|
||||
#ifdef RESOLVSORT
|
||||
@@ -183,9 +185,15 @@ __res_vinit(res_state statp, int preinit
|
||||
statp->_flags = 0;
|
||||
statp->qhook = NULL;
|
||||
statp->rhook = NULL;
|
||||
+ statp->_u._ext.nsinit = 0;
|
||||
statp->_u._ext.nscount = 0;
|
||||
- for (n = 0; n < MAXNS; n++)
|
||||
- statp->_u._ext.nsaddrs[n] = NULL;
|
||||
+#ifdef _LIBC
|
||||
+ statp->_u._ext.nscount6 = 0;
|
||||
+ for (n = 0; n < MAXNS; n++) {
|
||||
+ statp->_u._ext.nsaddrs[n] = NULL;
|
||||
+ statp->_u._ext.nsmap[n] = MAXNS;
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
/* Allow user to override the local domain definition */
|
||||
if ((cp = getenv("LOCALDOMAIN")) != NULL) {
|
||||
@@ -289,7 +297,11 @@ __res_vinit(res_state statp, int preinit
|
||||
continue;
|
||||
}
|
||||
/* read nameservers to query */
|
||||
+#ifdef _LIBC
|
||||
+ if (MATCH(buf, "nameserver") && nservall < MAXNS) {
|
||||
+#else
|
||||
if (MATCH(buf, "nameserver") && nserv < MAXNS) {
|
||||
+#endif
|
||||
struct in_addr a;
|
||||
|
||||
cp = buf + sizeof("nameserver") - 1;
|
||||
@@ -297,12 +309,13 @@ __res_vinit(res_state statp, int preinit
|
||||
cp++;
|
||||
if ((*cp != '\0') && (*cp != '\n')
|
||||
&& __inet_aton(cp, &a)) {
|
||||
- statp->nsaddr_list[nserv].sin_addr = a;
|
||||
- statp->nsaddr_list[nserv].sin_family = AF_INET;
|
||||
- statp->nsaddr_list[nserv].sin_port =
|
||||
+ statp->nsaddr_list[nservall].sin_addr = a;
|
||||
+ statp->nsaddr_list[nservall].sin_family = AF_INET;
|
||||
+ statp->nsaddr_list[nservall].sin_port =
|
||||
htons(NAMESERVER_PORT);
|
||||
nserv++;
|
||||
#ifdef _LIBC
|
||||
+ nservall++;
|
||||
} else {
|
||||
struct in6_addr a6;
|
||||
char *el;
|
||||
@@ -344,11 +357,10 @@ __res_vinit(res_state statp, int preinit
|
||||
}
|
||||
}
|
||||
|
||||
- statp->nsaddr_list[nserv].sin_family = 0;
|
||||
- statp->_u._ext.nsaddrs[nserv] = sa6;
|
||||
- statp->_u._ext.nssocks[nserv] = -1;
|
||||
- have_serv6 = 1;
|
||||
- nserv++;
|
||||
+ statp->_u._ext.nsaddrs[nservall] = sa6;
|
||||
+ statp->_u._ext.nssocks[nservall] = -1;
|
||||
+ statp->_u._ext.nsmap[nservall] = MAXNS + 1;
|
||||
+ nservall++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -403,9 +415,10 @@ __res_vinit(res_state statp, int preinit
|
||||
continue;
|
||||
}
|
||||
}
|
||||
- statp->nscount = nserv;
|
||||
+ statp->nscount = nservall;
|
||||
#ifdef _LIBC
|
||||
- if (have_serv6) {
|
||||
+ if (nservall - nserv > 0) {
|
||||
+ statp->_u._ext.nscount6 = nservall - nserv;
|
||||
/* We try IPv6 servers again. */
|
||||
statp->ipv6_unavail = false;
|
||||
}
|
||||
@@ -594,7 +607,11 @@ __res_iclose(res_state statp, bool free_
|
||||
statp->_vcsock = -1;
|
||||
statp->_flags &= ~(RES_F_VC | RES_F_CONN);
|
||||
}
|
||||
+#ifdef _LIBC
|
||||
+ for (ns = 0; ns < MAXNS; ns++)
|
||||
+#else
|
||||
for (ns = 0; ns < statp->_u._ext.nscount; ns++)
|
||||
+#endif
|
||||
if (statp->_u._ext.nsaddrs[ns]) {
|
||||
if (statp->_u._ext.nssocks[ns] != -1) {
|
||||
close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
|
||||
@@ -605,6 +622,8 @@ __res_iclose(res_state statp, bool free_
|
||||
statp->_u._ext.nsaddrs[ns] = NULL;
|
||||
}
|
||||
}
|
||||
+ if (free_addr)
|
||||
+ statp->_u._ext.nsinit = 0;
|
||||
}
|
||||
libc_hidden_def (__res_iclose)
|
||||
|
||||
Index: b/resolv/res_send.c
|
||||
===================================================================
|
||||
--- a/resolv/res_send.c
|
||||
+++ b/resolv/res_send.c
|
||||
@@ -176,7 +176,6 @@ evNowTime(struct timespec *res) {
|
||||
|
||||
/* Forward. */
|
||||
|
||||
-static struct sockaddr *get_nsaddr (res_state, int);
|
||||
static int send_vc(res_state, const u_char *, int,
|
||||
const u_char *, int,
|
||||
u_char **, int *, int *, int, u_char **,
|
||||
@@ -214,21 +213,20 @@ res_ourserver_p(const res_state statp, c
|
||||
in_port_t port = in4p->sin_port;
|
||||
in_addr_t addr = in4p->sin_addr.s_addr;
|
||||
|
||||
- for (ns = 0; ns < statp->nscount; ns++) {
|
||||
+ for (ns = 0; ns < MAXNS; ns++) {
|
||||
const struct sockaddr_in *srv =
|
||||
- (struct sockaddr_in *) get_nsaddr (statp, ns);
|
||||
+ (struct sockaddr_in *)EXT(statp).nsaddrs[ns];
|
||||
|
||||
- if ((srv->sin_family == AF_INET) &&
|
||||
+ if ((srv != NULL) && (srv->sin_family == AF_INET) &&
|
||||
(srv->sin_port == port) &&
|
||||
(srv->sin_addr.s_addr == INADDR_ANY ||
|
||||
srv->sin_addr.s_addr == addr))
|
||||
return (1);
|
||||
}
|
||||
} else if (inp->sin6_family == AF_INET6) {
|
||||
- for (ns = 0; ns < statp->nscount; ns++) {
|
||||
- const struct sockaddr_in6 *srv
|
||||
- = (struct sockaddr_in6 *) get_nsaddr (statp, ns);
|
||||
- if ((srv->sin6_family == AF_INET6) &&
|
||||
+ for (ns = 0; ns < MAXNS; ns++) {
|
||||
+ const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns];
|
||||
+ if ((srv != NULL) && (srv->sin6_family == AF_INET6) &&
|
||||
(srv->sin6_port == inp->sin6_port) &&
|
||||
!(memcmp(&srv->sin6_addr, &in6addr_any,
|
||||
sizeof (struct in6_addr)) &&
|
||||
@@ -378,48 +376,80 @@ __libc_res_nsend(res_state statp, const
|
||||
* If the ns_addr_list in the resolver context has changed, then
|
||||
* invalidate our cached copy and the associated timing data.
|
||||
*/
|
||||
- if (EXT(statp).nscount != 0) {
|
||||
+ if (EXT(statp).nsinit) {
|
||||
int needclose = 0;
|
||||
|
||||
if (EXT(statp).nscount != statp->nscount)
|
||||
needclose++;
|
||||
else
|
||||
- for (ns = 0; ns < statp->nscount; ns++) {
|
||||
- if (statp->nsaddr_list[ns].sin_family != 0
|
||||
+ for (ns = 0; ns < MAXNS; ns++) {
|
||||
+ unsigned int map = EXT(statp).nsmap[ns];
|
||||
+ if (map < MAXNS
|
||||
&& !sock_eq((struct sockaddr_in6 *)
|
||||
- &statp->nsaddr_list[ns],
|
||||
+ &statp->nsaddr_list[map],
|
||||
EXT(statp).nsaddrs[ns]))
|
||||
{
|
||||
needclose++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
- if (needclose) {
|
||||
+ if (needclose)
|
||||
__res_iclose(statp, false);
|
||||
- EXT(statp).nscount = 0;
|
||||
- }
|
||||
}
|
||||
|
||||
/*
|
||||
* Maybe initialize our private copy of the ns_addr_list.
|
||||
*/
|
||||
- if (EXT(statp).nscount == 0) {
|
||||
- for (ns = 0; ns < statp->nscount; ns++) {
|
||||
- EXT(statp).nssocks[ns] = -1;
|
||||
- if (statp->nsaddr_list[ns].sin_family == 0)
|
||||
- continue;
|
||||
- if (EXT(statp).nsaddrs[ns] == NULL)
|
||||
- EXT(statp).nsaddrs[ns] =
|
||||
+ if (EXT(statp).nsinit == 0) {
|
||||
+ unsigned char map[MAXNS];
|
||||
+
|
||||
+ memset (map, MAXNS, sizeof (map));
|
||||
+ for (n = 0; n < MAXNS; n++) {
|
||||
+ ns = EXT(statp).nsmap[n];
|
||||
+ if (ns < statp->nscount)
|
||||
+ map[ns] = n;
|
||||
+ else if (ns < MAXNS) {
|
||||
+ free(EXT(statp).nsaddrs[n]);
|
||||
+ EXT(statp).nsaddrs[n] = NULL;
|
||||
+ EXT(statp).nsmap[n] = MAXNS;
|
||||
+ }
|
||||
+ }
|
||||
+ n = statp->nscount;
|
||||
+ if (statp->nscount > EXT(statp).nscount)
|
||||
+ for (n = EXT(statp).nscount, ns = 0;
|
||||
+ n < statp->nscount; n++) {
|
||||
+ while (ns < MAXNS
|
||||
+ && EXT(statp).nsmap[ns] != MAXNS)
|
||||
+ ns++;
|
||||
+ if (ns == MAXNS)
|
||||
+ break;
|
||||
+ /* NS never exceeds MAXNS, but gcc 4.9 somehow
|
||||
+ does not see this. */
|
||||
+ DIAG_PUSH_NEEDS_COMMENT;
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (4.9,
|
||||
+ "-Warray-bounds");
|
||||
+ EXT(statp).nsmap[ns] = n;
|
||||
+ DIAG_POP_NEEDS_COMMENT;
|
||||
+ map[n] = ns++;
|
||||
+ }
|
||||
+ EXT(statp).nscount = n;
|
||||
+ for (ns = 0; ns < EXT(statp).nscount; ns++) {
|
||||
+ n = map[ns];
|
||||
+ if (EXT(statp).nsaddrs[n] == NULL)
|
||||
+ EXT(statp).nsaddrs[n] =
|
||||
malloc(sizeof (struct sockaddr_in6));
|
||||
- if (EXT(statp).nsaddrs[ns] != NULL)
|
||||
- memset (mempcpy(EXT(statp).nsaddrs[ns],
|
||||
+ if (EXT(statp).nsaddrs[n] != NULL) {
|
||||
+ memset (mempcpy(EXT(statp).nsaddrs[n],
|
||||
&statp->nsaddr_list[ns],
|
||||
sizeof (struct sockaddr_in)),
|
||||
'\0',
|
||||
sizeof (struct sockaddr_in6)
|
||||
- sizeof (struct sockaddr_in));
|
||||
+ EXT(statp).nssocks[n] = -1;
|
||||
+ n++;
|
||||
+ }
|
||||
}
|
||||
- EXT(statp).nscount = statp->nscount;
|
||||
+ EXT(statp).nsinit = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -428,37 +458,44 @@ __libc_res_nsend(res_state statp, const
|
||||
*/
|
||||
if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) &&
|
||||
(statp->options & RES_BLAST) == 0) {
|
||||
- struct sockaddr_in ina;
|
||||
- struct sockaddr_in6 *inp;
|
||||
- int lastns = statp->nscount - 1;
|
||||
- int fd;
|
||||
-
|
||||
- inp = EXT(statp).nsaddrs[0];
|
||||
- ina = statp->nsaddr_list[0];
|
||||
- fd = EXT(statp).nssocks[0];
|
||||
- for (ns = 0; ns < lastns; ns++) {
|
||||
- EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1];
|
||||
- statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
|
||||
- EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
|
||||
- }
|
||||
- EXT(statp).nsaddrs[lastns] = inp;
|
||||
- statp->nsaddr_list[lastns] = ina;
|
||||
- EXT(statp).nssocks[lastns] = fd;
|
||||
+ struct sockaddr_in6 *ina;
|
||||
+ unsigned int map;
|
||||
+
|
||||
+ n = 0;
|
||||
+ while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS)
|
||||
+ n++;
|
||||
+ if (n < MAXNS) {
|
||||
+ ina = EXT(statp).nsaddrs[n];
|
||||
+ map = EXT(statp).nsmap[n];
|
||||
+ for (;;) {
|
||||
+ ns = n + 1;
|
||||
+ while (ns < MAXNS
|
||||
+ && EXT(statp).nsmap[ns] == MAXNS)
|
||||
+ ns++;
|
||||
+ if (ns == MAXNS)
|
||||
+ break;
|
||||
+ EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns];
|
||||
+ EXT(statp).nsmap[n] = EXT(statp).nsmap[ns];
|
||||
+ n = ns;
|
||||
+ }
|
||||
+ EXT(statp).nsaddrs[n] = ina;
|
||||
+ EXT(statp).nsmap[n] = map;
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
* Send request, RETRY times, or until successful.
|
||||
*/
|
||||
for (try = 0; try < statp->retry; try++) {
|
||||
- for (ns = 0; ns < statp->nscount; ns++)
|
||||
+ for (ns = 0; ns < MAXNS; ns++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
char tmpbuf[40];
|
||||
#endif
|
||||
-#if defined USE_HOOKS || defined DEBUG
|
||||
- struct sockaddr *nsap = get_nsaddr (statp, ns);
|
||||
-#endif
|
||||
+ struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
|
||||
|
||||
+ if (nsap == NULL)
|
||||
+ goto next_ns;
|
||||
same_ns:
|
||||
#ifdef USE_HOOKS
|
||||
if (__glibc_unlikely (statp->qhook != NULL)) {
|
||||
@@ -615,21 +652,6 @@ libresolv_hidden_def (res_nsend)
|
||||
|
||||
/* Private */
|
||||
|
||||
-static struct sockaddr *
|
||||
-get_nsaddr (res_state statp, int n)
|
||||
-{
|
||||
-
|
||||
- if (statp->nsaddr_list[n].sin_family == 0 && EXT(statp).nsaddrs[n] != NULL)
|
||||
- /* EXT(statp).nsaddrs[n] holds an address that is larger than
|
||||
- struct sockaddr, and user code did not update
|
||||
- statp->nsaddr_list[n]. */
|
||||
- return (struct sockaddr *) EXT(statp).nsaddrs[n];
|
||||
- else
|
||||
- /* User code updated statp->nsaddr_list[n], or statp->nsaddr_list[n]
|
||||
- has the same content as EXT(statp).nsaddrs[n]. */
|
||||
- return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
|
||||
-}
|
||||
-
|
||||
static int
|
||||
send_vc(res_state statp,
|
||||
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
|
||||
@@ -644,7 +666,7 @@ send_vc(res_state statp,
|
||||
// XXX REMOVE
|
||||
// int anssiz = *anssizp;
|
||||
HEADER *anhp = (HEADER *) ans;
|
||||
- struct sockaddr *nsap = get_nsaddr (statp, ns);
|
||||
+ struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
|
||||
int truncating, connreset, n;
|
||||
/* On some architectures compiler might emit a warning indicating
|
||||
'resplen' may be used uninitialized. However if buf2 == NULL
|
||||
@@ -677,8 +699,8 @@ send_vc(res_state statp,
|
||||
|
||||
if (getpeername(statp->_vcsock,
|
||||
(struct sockaddr *)&peer, &size) < 0 ||
|
||||
- !sock_eq(&peer, (struct sockaddr_in6 *) nsap)) {
|
||||
- __res_iclose(statp, false);
|
||||
+ !sock_eq(&peer, nsap)) {
|
||||
+ __res_iclose(statp, false);
|
||||
statp->_flags &= ~RES_F_VC;
|
||||
}
|
||||
}
|
||||
@@ -687,19 +709,20 @@ send_vc(res_state statp,
|
||||
if (statp->_vcsock >= 0)
|
||||
__res_iclose(statp, false);
|
||||
|
||||
- statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
|
||||
+ statp->_vcsock = socket(nsap->sin6_family, SOCK_STREAM, 0);
|
||||
if (statp->_vcsock < 0) {
|
||||
*terrno = errno;
|
||||
Perror(statp, stderr, "socket(vc)", errno);
|
||||
return (-1);
|
||||
}
|
||||
__set_errno (0);
|
||||
- if (connect(statp->_vcsock, nsap,
|
||||
- nsap->sa_family == AF_INET
|
||||
+ if (connect(statp->_vcsock, (struct sockaddr *)nsap,
|
||||
+ nsap->sin6_family == AF_INET
|
||||
? sizeof (struct sockaddr_in)
|
||||
: sizeof (struct sockaddr_in6)) < 0) {
|
||||
*terrno = errno;
|
||||
- Aerror(statp, stderr, "connect/vc", errno, nsap);
|
||||
+ Aerror(statp, stderr, "connect/vc", errno,
|
||||
+ (struct sockaddr *) nsap);
|
||||
__res_iclose(statp, false);
|
||||
return (0);
|
||||
}
|
||||
@@ -906,7 +929,8 @@ static int
|
||||
reopen (res_state statp, int *terrno, int ns)
|
||||
{
|
||||
if (EXT(statp).nssocks[ns] == -1) {
|
||||
- struct sockaddr *nsap = get_nsaddr (statp, ns);
|
||||
+ struct sockaddr *nsap
|
||||
+ = (struct sockaddr *) EXT(statp).nsaddrs[ns];
|
||||
socklen_t slen;
|
||||
|
||||
/* only try IPv6 if IPv6 NS and if not failed before */
|
22
glibc-rh1615608.patch
Normal file
22
glibc-rh1615608.patch
Normal file
@ -0,0 +1,22 @@
|
||||
Please see the following bug for a complete summary:
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1615608
|
||||
|
||||
Index: glibc-2.28/manual/startup.texi
|
||||
===================================================================
|
||||
--- glibc-2.28.orig/manual/startup.texi
|
||||
+++ glibc-2.28/manual/startup.texi
|
||||
@@ -1005,14 +1005,6 @@ This function actually terminates the pr
|
||||
intercept this signal; see @ref{Signal Handling}.
|
||||
@end deftypefun
|
||||
|
||||
-@c Put in by rms. Don't remove.
|
||||
-@cartouche
|
||||
-@strong{Future Change Warning:} Proposed Federal censorship regulations
|
||||
-may prohibit us from giving you information about the possibility of
|
||||
-calling this function. We would be required to say that this is not an
|
||||
-acceptable way of terminating a program.
|
||||
-@end cartouche
|
||||
-
|
||||
@node Termination Internals
|
||||
@subsection Termination Internals
|
||||
|
@ -1,3 +1,14 @@
|
||||
Short description: Add UCS-2 aliases.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #697421
|
||||
Upstream status: https://sourceware.org/ml/libc-alpha/2012-12/msg00103.html
|
||||
|
||||
This is a Fedora-specific change to include new aliases for UCS-2
|
||||
data for gconv used by a certain class of users. This should be
|
||||
revisited at some point to determine if those users are just using
|
||||
UTF-8 at this point.
|
||||
|
||||
diff -rup a/iconvdata/gconv-modules b/iconvdata/gconv-modules
|
||||
--- a/iconvdata/gconv-modules 2010-05-04 05:27:23.000000000 -0600
|
||||
+++ b/iconvdata/gconv-modules 2012-01-26 10:58:24.181895489 -0700
|
||||
|
@ -1,3 +1,14 @@
|
||||
Short description: Work ld.so --verify crash on debuginfo files.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #741105, #767146
|
||||
Upstream status: not-needed
|
||||
|
||||
This change is designed to work around running ld.so on a debuginfo
|
||||
file. This is the wrong fix for this problem and should be dropped.
|
||||
The correct solution is to mark debuginfo files as new types of
|
||||
ELF files.
|
||||
|
||||
Index: glibc-2.22-386-g95e8397/elf/dl-load.c
|
||||
===================================================================
|
||||
--- glibc-2.22-386-g95e8397.orig/elf/dl-load.c
|
||||
|
@ -1,3 +1,16 @@
|
||||
Short description: fnmatch() fails with MBCS.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #819430, #826149, #826151
|
||||
Bug-Upstream: #14185
|
||||
Upstream status: not-submitted
|
||||
|
||||
fnmatch() fails when '*' wildcard is applied on the file name
|
||||
containing multi-byte character(s)
|
||||
|
||||
This needs to be reviewed thoroughly and go upstream with a
|
||||
new test case.
|
||||
|
||||
diff -Nrup a/posix/fnmatch.c b/posix/fnmatch.c
|
||||
--- a/posix/fnmatch.c 2012-01-01 07:16:32.000000000 -0500
|
||||
+++ b/posix/fnmatch.c 2012-05-23 14:14:29.099461189 -0400
|
||||
|
@ -1,13 +0,0 @@
|
||||
diff -rup a/manual/Makefile b/manual/Makefile
|
||||
--- a/manual/Makefile 2012-05-20 19:47:38.000000000 -0600
|
||||
+++ b/manual/Makefile 2012-05-29 22:23:33.920428631 -0600
|
||||
@@ -129,7 +129,8 @@ $(objpfx)%.c.texi: examples/%.c
|
||||
mv -f $@.new $@
|
||||
|
||||
$(objpfx)%.info: %.texinfo
|
||||
- LANGUAGE=C LC_ALL=C $(MAKEINFO) -P $(objpfx) --output=$@ $<
|
||||
+ LANGUAGE=C LC_ALL=C $(MAKEINFO) -P $(objpfx) --output=`basename $@` $<
|
||||
+ mv `basename $@`* $(objpfx)
|
||||
|
||||
$(objpfx)%.dvi: %.texinfo
|
||||
cd $(objpfx);$(TEXI2DVI) -I $(shell cd $(<D) && pwd) --output=$@ \
|
@ -1,5 +1,15 @@
|
||||
2012-06-14 Jeff Law <law@redhat.com>
|
||||
Short description: Fix newlocale error return.
|
||||
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
|
||||
Origin: PATCH
|
||||
Bug-RHEL: #832516
|
||||
Bug-Fedora: #827510
|
||||
Bug-Upstream: #14247
|
||||
Upstream status: not-submitted
|
||||
|
||||
This needs to go upstream right away to fix the error case for
|
||||
newlocale not correctly returning an error.
|
||||
|
||||
2012-06-14 Jeff Law <law@redhat.com>
|
||||
|
||||
* locale/loadlocale.c (_nl_load_locale): Delay setting
|
||||
file->decided until we have successfully loaded the file's
|
||||
@ -16,7 +26,7 @@ index e3fa187..9fd9216 100644
|
||||
- file->decided = 1;
|
||||
file->data = NULL;
|
||||
|
||||
fd = open_not_cancel_2 (file->filename, O_RDONLY | O_CLOEXEC);
|
||||
fd = __open_nocancel (file->filename, O_RDONLY | O_CLOEXEC);
|
||||
@@ -278,6 +277,7 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
|
||||
newdata->alloc = alloc;
|
||||
|
||||
|
@ -1,181 +0,0 @@
|
||||
#
|
||||
# Red Hat BZ:
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=816647
|
||||
#
|
||||
# ChangeLog
|
||||
#
|
||||
#2013-04-30 Patsy Franklin <pfrankli@redhat.com>
|
||||
#
|
||||
# * iconv/gconv_cache.c (find_module): Demangle init_fct before
|
||||
# checking for NULL. Mangle __btowc_fct if init_fct is non-NULL.
|
||||
# * iconv/gconv_db.c (free_derivation): Check that __shlib_handle
|
||||
# is non-NULL before demangling the end_fct. Check for NULL
|
||||
# end_fct after demangling.
|
||||
# (__gconv_release_step): Demangle the end_fct before checking
|
||||
# it for NULL. Remove assert on __shlibc_handle != NULL.
|
||||
# (gen_steps): Don't check btowc_fct for NULL before mangling.
|
||||
# Demangle init_fct before checking for NULL.
|
||||
# (increment_counter): Likewise
|
||||
# * gconv_dl.c (__gconv_find_shlib): Don't check init_fct or
|
||||
# end_fct for NULL before mangling.
|
||||
# * wcsmbs/btowc.c (__btowc): Demangle btowc_fct before checking
|
||||
# for NULL.
|
||||
#
|
||||
diff -Nrup a/iconv/gconv_cache.c b/iconv/gconv_cache.c
|
||||
--- a/iconv/gconv_cache.c 2012-12-24 22:02:13.000000000 -0500
|
||||
+++ b/iconv/gconv_cache.c 2013-04-30 06:43:24.788684270 -0400
|
||||
@@ -207,17 +207,16 @@ find_module (const char *directory, cons
|
||||
result->__data = NULL;
|
||||
|
||||
/* Call the init function. */
|
||||
- if (result->__init_fct != NULL)
|
||||
- {
|
||||
- __gconv_init_fct init_fct = result->__init_fct;
|
||||
+ __gconv_init_fct init_fct = result->__init_fct;
|
||||
#ifdef PTR_DEMANGLE
|
||||
- PTR_DEMANGLE (init_fct);
|
||||
+ PTR_DEMANGLE (init_fct);
|
||||
#endif
|
||||
+ if (init_fct != NULL)
|
||||
+ {
|
||||
status = DL_CALL_FCT (init_fct, (result));
|
||||
|
||||
#ifdef PTR_MANGLE
|
||||
- if (result->__btowc_fct != NULL)
|
||||
- PTR_MANGLE (result->__btowc_fct);
|
||||
+ PTR_MANGLE (result->__btowc_fct);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
diff -Nrup a/iconv/gconv_db.c b/iconv/gconv_db.c
|
||||
--- a/iconv/gconv_db.c 2012-12-24 22:02:13.000000000 -0500
|
||||
+++ b/iconv/gconv_db.c 2013-04-30 06:37:16.886521576 -0400
|
||||
@@ -179,16 +179,15 @@ free_derivation (void *p)
|
||||
size_t cnt;
|
||||
|
||||
for (cnt = 0; cnt < deriv->nsteps; ++cnt)
|
||||
- if (deriv->steps[cnt].__counter > 0
|
||||
- && deriv->steps[cnt].__end_fct != NULL)
|
||||
+ if ((deriv->steps[cnt].__counter > 0)
|
||||
+ && (deriv->steps[cnt].__shlib_handle != NULL))
|
||||
{
|
||||
- assert (deriv->steps[cnt].__shlib_handle != NULL);
|
||||
-
|
||||
__gconv_end_fct end_fct = deriv->steps[cnt].__end_fct;
|
||||
#ifdef PTR_DEMANGLE
|
||||
PTR_DEMANGLE (end_fct);
|
||||
#endif
|
||||
- DL_CALL_FCT (end_fct, (&deriv->steps[cnt]));
|
||||
+ if (end_fct != NULL)
|
||||
+ DL_CALL_FCT (end_fct, (&deriv->steps[cnt]));
|
||||
}
|
||||
|
||||
/* Free the name strings. */
|
||||
@@ -212,16 +211,12 @@ __gconv_release_step (struct __gconv_ste
|
||||
if (step->__shlib_handle != NULL && --step->__counter == 0)
|
||||
{
|
||||
/* Call the destructor. */
|
||||
- if (step->__end_fct != NULL)
|
||||
- {
|
||||
- assert (step->__shlib_handle != NULL);
|
||||
-
|
||||
- __gconv_end_fct end_fct = step->__end_fct;
|
||||
+ __gconv_end_fct end_fct = step->__end_fct;
|
||||
#ifdef PTR_DEMANGLE
|
||||
- PTR_DEMANGLE (end_fct);
|
||||
+ PTR_DEMANGLE (end_fct);
|
||||
#endif
|
||||
- DL_CALL_FCT (end_fct, (step));
|
||||
- }
|
||||
+ if (end_fct != NULL)
|
||||
+ DL_CALL_FCT (end_fct, (step));
|
||||
|
||||
#ifndef STATIC_GCONV
|
||||
/* Release the loaded module. */
|
||||
@@ -293,13 +288,11 @@ gen_steps (struct derivation_step *best,
|
||||
|
||||
/* Call the init function. */
|
||||
__gconv_init_fct init_fct = result[step_cnt].__init_fct;
|
||||
- if (init_fct != NULL)
|
||||
- {
|
||||
- assert (result[step_cnt].__shlib_handle != NULL);
|
||||
-
|
||||
# ifdef PTR_DEMANGLE
|
||||
- PTR_DEMANGLE (init_fct);
|
||||
+ PTR_DEMANGLE (init_fct);
|
||||
# endif
|
||||
+ if (init_fct != NULL)
|
||||
+ {
|
||||
status = DL_CALL_FCT (init_fct, (&result[step_cnt]));
|
||||
|
||||
if (__builtin_expect (status, __GCONV_OK) != __GCONV_OK)
|
||||
@@ -312,8 +305,7 @@ gen_steps (struct derivation_step *best,
|
||||
}
|
||||
|
||||
# ifdef PTR_MANGLE
|
||||
- if (result[step_cnt].__btowc_fct != NULL)
|
||||
- PTR_MANGLE (result[step_cnt].__btowc_fct);
|
||||
+ PTR_MANGLE (result[step_cnt].__btowc_fct);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
@@ -393,16 +385,15 @@ increment_counter (struct __gconv_step *
|
||||
|
||||
/* Call the init function. */
|
||||
__gconv_init_fct init_fct = step->__init_fct;
|
||||
- if (init_fct != NULL)
|
||||
- {
|
||||
#ifdef PTR_DEMANGLE
|
||||
- PTR_DEMANGLE (init_fct);
|
||||
+ PTR_DEMANGLE (init_fct);
|
||||
#endif
|
||||
+ if (init_fct != NULL)
|
||||
+ {
|
||||
DL_CALL_FCT (init_fct, (step));
|
||||
|
||||
#ifdef PTR_MANGLE
|
||||
- if (step->__btowc_fct != NULL)
|
||||
- PTR_MANGLE (step->__btowc_fct);
|
||||
+ PTR_MANGLE (step->__btowc_fct);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
diff -Nrup a/iconv/gconv_dl.c b/iconv/gconv_dl.c
|
||||
--- a/iconv/gconv_dl.c 2012-12-24 22:02:13.000000000 -0500
|
||||
+++ b/iconv/gconv_dl.c 2013-04-30 06:37:16.889521601 -0400
|
||||
@@ -132,10 +132,8 @@ __gconv_find_shlib (const char *name)
|
||||
|
||||
#ifdef PTR_MANGLE
|
||||
PTR_MANGLE (found->fct);
|
||||
- if (found->init_fct != NULL)
|
||||
- PTR_MANGLE (found->init_fct);
|
||||
- if (found->end_fct != NULL)
|
||||
- PTR_MANGLE (found->end_fct);
|
||||
+ PTR_MANGLE (found->init_fct);
|
||||
+ PTR_MANGLE (found->end_fct);
|
||||
#endif
|
||||
|
||||
/* We have succeeded in loading the shared object. */
|
||||
diff -Nrup a/wcsmbs/btowc.c b/wcsmbs/btowc.c
|
||||
--- a/wcsmbs/btowc.c 2012-12-24 22:02:13.000000000 -0500
|
||||
+++ b/wcsmbs/btowc.c 2013-04-30 06:37:16.891521619 -0400
|
||||
@@ -47,15 +47,15 @@ __btowc (c)
|
||||
/* Get the conversion functions. */
|
||||
fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE));
|
||||
__gconv_btowc_fct btowc_fct = fcts->towc->__btowc_fct;
|
||||
+#ifdef PTR_DEMANGLE
|
||||
+ if (fcts->towc->__shlib_handle != NULL)
|
||||
+ PTR_DEMANGLE (btowc_fct);
|
||||
+#endif
|
||||
|
||||
if (__builtin_expect (fcts->towc_nsteps == 1, 1)
|
||||
&& __builtin_expect (btowc_fct != NULL, 1))
|
||||
{
|
||||
/* Use the shortcut function. */
|
||||
-#ifdef PTR_DEMANGLE
|
||||
- if (fcts->towc->__shlib_handle != NULL)
|
||||
- PTR_DEMANGLE (btowc_fct);
|
||||
-#endif
|
||||
return DL_CALL_FCT (btowc_fct, (fcts->towc, (unsigned char) c));
|
||||
}
|
||||
else
|
4293
glibc.spec
4293
glibc.spec
File diff suppressed because it is too large
Load Diff
@ -1,340 +0,0 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <dirent.h>
|
||||
#include <stddef.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <elf.h>
|
||||
|
||||
#define verbose_exec(failcode, path...) \
|
||||
do \
|
||||
{ \
|
||||
char *const arr[] = { path, NULL }; \
|
||||
vexec (failcode, arr); \
|
||||
} while (0)
|
||||
|
||||
__attribute__((noinline)) void vexec (int failcode, char *const path[]);
|
||||
__attribute__((noinline)) void says (const char *str);
|
||||
__attribute__((noinline)) void sayn (long num);
|
||||
__attribute__((noinline)) void message (char *const path[]);
|
||||
__attribute__((noinline)) int check_elf (const char *name);
|
||||
|
||||
#ifdef __i386__
|
||||
static int
|
||||
is_ia64 (void)
|
||||
{
|
||||
unsigned int fl1, fl2;
|
||||
|
||||
/* See if we can use cpuid. */
|
||||
__asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
|
||||
"pushl %0; popfl; pushfl; popl %0; popfl"
|
||||
: "=&r" (fl1), "=&r" (fl2)
|
||||
: "i" (0x00200000));
|
||||
if (((fl1 ^ fl2) & 0x00200000) == 0)
|
||||
return 0;
|
||||
|
||||
/* Host supports cpuid. See if cpuid gives capabilities, try
|
||||
CPUID(0). Preserve %ebx and %ecx; cpuid insn clobbers these, we
|
||||
don't need their CPUID values here, and %ebx may be the PIC
|
||||
register. */
|
||||
__asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
|
||||
: "=a" (fl1) : "0" (0) : "edx", "cc");
|
||||
if (fl1 == 0)
|
||||
return 0;
|
||||
|
||||
/* Invoke CPUID(1), return %edx; caller can examine bits to
|
||||
determine what's supported. */
|
||||
__asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
|
||||
: "=d" (fl2), "=a" (fl1) : "1" (1) : "cc");
|
||||
return (fl2 & (1 << 30)) != 0;
|
||||
}
|
||||
#else
|
||||
#define is_ia64() 0
|
||||
#endif
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
struct stat statbuf;
|
||||
char initpath[256];
|
||||
|
||||
char buffer[4096];
|
||||
struct pref {
|
||||
char *p;
|
||||
int len;
|
||||
} prefix[] = { { "libc-", 5 }, { "libm-", 5 },
|
||||
{ "librt-", 6 }, { "libpthread-", 11 },
|
||||
{ "librtkaio-", 10 }, { "libthread_db-", 13 } };
|
||||
int i, j, fd;
|
||||
off_t base;
|
||||
ssize_t ret;
|
||||
#ifdef __i386__
|
||||
const char *remove_dirs[] = { "/lib/tls", "/lib/i686", "/lib/tls/i486", "/lib/tls/i586", "/lib/tls/i686" };
|
||||
#else
|
||||
#ifndef LIBTLS
|
||||
#define LIBTLS "/lib/tls"
|
||||
#endif
|
||||
const char *remove_dirs[] = { LIBTLS };
|
||||
#endif
|
||||
for (j = 0; j < sizeof (remove_dirs) / sizeof (remove_dirs[0]); ++j)
|
||||
{
|
||||
size_t rmlen = strlen (remove_dirs[j]);
|
||||
fd = open (remove_dirs[j], O_RDONLY);
|
||||
if (fd >= 0
|
||||
&& (ret = getdirentries (fd, buffer, sizeof (buffer), &base))
|
||||
>= (ssize_t) offsetof (struct dirent, d_name))
|
||||
{
|
||||
for (base = 0; base + offsetof (struct dirent, d_name) < ret; )
|
||||
{
|
||||
struct dirent *d = (struct dirent *) (buffer + base);
|
||||
|
||||
for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++)
|
||||
if (! strncmp (d->d_name, prefix[i].p, prefix[i].len))
|
||||
{
|
||||
char *p = d->d_name + prefix[i].len;
|
||||
|
||||
while (*p == '.' || (*p >= '0' && *p <= '9')) p++;
|
||||
if (p[0] == 's' && p[1] == 'o' && p[2] == '\0'
|
||||
&& p + 3 - d->d_name
|
||||
< sizeof (initpath) - rmlen - 1)
|
||||
{
|
||||
memcpy (initpath, remove_dirs[j], rmlen);
|
||||
initpath[rmlen] = '/';
|
||||
strcpy (initpath + rmlen + 1, d->d_name);
|
||||
unlink (initpath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
base += d->d_reclen;
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
|
||||
int ldsocfd = open (LD_SO_CONF, O_RDONLY);
|
||||
struct stat ldsocst;
|
||||
if (ldsocfd >= 0 && fstat (ldsocfd, &ldsocst) >= 0)
|
||||
{
|
||||
char p[ldsocst.st_size + 1];
|
||||
if (read (ldsocfd, p, ldsocst.st_size) == ldsocst.st_size)
|
||||
{
|
||||
p[ldsocst.st_size] = '\0';
|
||||
if (strstr (p, "include ld.so.conf.d/*.conf") == NULL)
|
||||
{
|
||||
close (ldsocfd);
|
||||
ldsocfd = open (LD_SO_CONF, O_WRONLY | O_TRUNC);
|
||||
if (ldsocfd >= 0)
|
||||
{
|
||||
size_t slen = strlen ("include ld.so.conf.d/*.conf\n");
|
||||
if (write (ldsocfd, "include ld.so.conf.d/*.conf\n", slen)
|
||||
!= slen
|
||||
|| write (ldsocfd, p, ldsocst.st_size) != ldsocst.st_size)
|
||||
_exit (109);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ldsocfd >= 0)
|
||||
close (ldsocfd);
|
||||
}
|
||||
|
||||
/* If installing bi-arch glibc, rpm sometimes doesn't unpack all files
|
||||
before running one of the lib's %post scriptlet. /sbin/ldconfig will
|
||||
then be run by the other arch's %post. */
|
||||
if (! access ("/sbin/ldconfig", X_OK))
|
||||
verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig");
|
||||
|
||||
if (! utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL))
|
||||
{
|
||||
#ifndef ICONVCONFIG
|
||||
#define ICONVCONFIG "/usr/sbin/iconvconfig"
|
||||
#endif
|
||||
char *iconv_cache = GCONV_MODULES_DIR"/gconv-modules.cache";
|
||||
char *iconv_dir = GCONV_MODULES_DIR;
|
||||
if (is_ia64 ())
|
||||
{
|
||||
iconv_cache = "/emul/ia32-linux"GCONV_MODULES_DIR"/gconv-modules.cache";
|
||||
iconv_dir = "/emul/ia32-linux"GCONV_MODULES_DIR;
|
||||
}
|
||||
verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig",
|
||||
"-o", iconv_cache,
|
||||
"--nostdlib", iconv_dir);
|
||||
}
|
||||
|
||||
/* Check if telinit is available and either SysVInit fifo,
|
||||
or upstart telinit. */
|
||||
if (access ("/sbin/telinit", X_OK)
|
||||
|| ((!!access ("/dev/initctl", F_OK))
|
||||
^ !access ("/sbin/initctl", X_OK)))
|
||||
_exit (0);
|
||||
|
||||
/* Check if we are not inside of some chroot, because we'd just
|
||||
timeout and leave /etc/initrunlvl.
|
||||
|
||||
On more modern systems this test is not sufficient to detect
|
||||
if we're in a chroot. */
|
||||
if (readlink ("/proc/1/exe", initpath, 256) <= 0 ||
|
||||
readlink ("/proc/1/root", initpath, 256) <= 0)
|
||||
_exit (0);
|
||||
|
||||
/* Here's another well known way to detect chroot, at least on an
|
||||
ext and xfs filesystems and assuming nothing mounted on the chroot's
|
||||
root. */
|
||||
if (stat ("/", &statbuf) != 0
|
||||
|| (statbuf.st_ino != 2
|
||||
&& statbuf.st_ino != 128))
|
||||
_exit (0);
|
||||
|
||||
if (check_elf ("/proc/1/exe"))
|
||||
verbose_exec (116, "/sbin/telinit", "/sbin/telinit", "u");
|
||||
|
||||
/* Check if we can safely condrestart sshd. */
|
||||
if (access ("/sbin/service", X_OK) == 0
|
||||
&& access ("/usr/sbin/sshd", X_OK) == 0
|
||||
&& access ("/etc/rc.d/init.d/sshd", X_OK) == 0
|
||||
&& access ("/bin/bash", X_OK) == 0)
|
||||
{
|
||||
if (check_elf ("/usr/sbin/sshd"))
|
||||
verbose_exec (-121, "/sbin/service", "/sbin/service", "sshd", "condrestart");
|
||||
}
|
||||
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
vexec (int failcode, char *const path[])
|
||||
{
|
||||
pid_t pid;
|
||||
int status, save_errno;
|
||||
int devnull = 0;
|
||||
|
||||
if (failcode < 0)
|
||||
{
|
||||
devnull = 1;
|
||||
failcode = -failcode;
|
||||
}
|
||||
pid = vfork ();
|
||||
if (pid == 0)
|
||||
{
|
||||
int fd;
|
||||
if (devnull && (fd = open ("/dev/null", O_WRONLY)) >= 0)
|
||||
{
|
||||
dup2 (fd, 1);
|
||||
dup2 (fd, 2);
|
||||
close (fd);
|
||||
}
|
||||
execv (path[0], path + 1);
|
||||
save_errno = errno;
|
||||
message (path);
|
||||
says (" exec failed with errno ");
|
||||
sayn (save_errno);
|
||||
says ("\n");
|
||||
_exit (failcode);
|
||||
}
|
||||
else if (pid < 0)
|
||||
{
|
||||
save_errno = errno;
|
||||
message (path);
|
||||
says (" fork failed with errno ");
|
||||
sayn (save_errno);
|
||||
says ("\n");
|
||||
_exit (failcode + 1);
|
||||
}
|
||||
if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
|
||||
{
|
||||
message (path);
|
||||
says (" child terminated abnormally\n");
|
||||
_exit (failcode + 2);
|
||||
}
|
||||
if (WEXITSTATUS (status))
|
||||
{
|
||||
message (path);
|
||||
says (" child exited with exit code ");
|
||||
sayn (WEXITSTATUS (status));
|
||||
says ("\n");
|
||||
_exit (WEXITSTATUS (status));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
says (const char *str)
|
||||
{
|
||||
write (1, str, strlen (str));
|
||||
}
|
||||
|
||||
void
|
||||
sayn (long num)
|
||||
{
|
||||
char string[sizeof (long) * 3 + 1];
|
||||
char *p = string + sizeof (string) - 1;
|
||||
|
||||
*p = '\0';
|
||||
if (num == 0)
|
||||
*--p = '0';
|
||||
else
|
||||
while (num)
|
||||
{
|
||||
*--p = '0' + num % 10;
|
||||
num = num / 10;
|
||||
}
|
||||
|
||||
says (p);
|
||||
}
|
||||
|
||||
void
|
||||
message (char *const path[])
|
||||
{
|
||||
says ("/usr/sbin/glibc_post_upgrade: While trying to execute ");
|
||||
says (path[0]);
|
||||
}
|
||||
|
||||
int
|
||||
check_elf (const char *name)
|
||||
{
|
||||
/* Play safe, if we can't open or read, assume it might be
|
||||
ELF for the current arch. */
|
||||
int ret = 1;
|
||||
int fd = open (name, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
Elf32_Ehdr ehdr;
|
||||
if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version))
|
||||
== offsetof (Elf32_Ehdr, e_version))
|
||||
{
|
||||
ret = 0;
|
||||
if (ehdr.e_ident[EI_CLASS]
|
||||
== (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32))
|
||||
{
|
||||
#if defined __i386__
|
||||
ret = ehdr.e_machine == EM_386;
|
||||
#elif defined __x86_64__
|
||||
ret = ehdr.e_machine == EM_X86_64;
|
||||
#elif defined __ia64__
|
||||
ret = ehdr.e_machine == EM_IA_64;
|
||||
#elif defined __powerpc64__
|
||||
ret = ehdr.e_machine == EM_PPC64;
|
||||
#elif defined __powerpc__
|
||||
ret = ehdr.e_machine == EM_PPC;
|
||||
#elif defined __s390__ || defined __s390x__
|
||||
ret = ehdr.e_machine == EM_S390;
|
||||
#elif defined __x86_64__
|
||||
ret = ehdr.e_machine == EM_X86_64;
|
||||
#elif defined __sparc__
|
||||
if (sizeof (long) == 8)
|
||||
ret = ehdr.e_machine == EM_SPARCV9;
|
||||
else
|
||||
ret = (ehdr.e_machine == EM_SPARC
|
||||
|| ehdr.e_machine == EM_SPARC32PLUS);
|
||||
#else
|
||||
ret = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
return ret;
|
||||
}
|
340
libc-lock.h
340
libc-lock.h
@ -1,340 +0,0 @@
|
||||
/* libc-internal interface for mutex locks. LinuxThreads version.
|
||||
Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public License as
|
||||
published by the Free Software Foundation; either version 2.1 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _BITS_LIBC_LOCK_H
|
||||
#define _BITS_LIBC_LOCK_H 1
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* Mutex type. */
|
||||
#ifdef _IO_MTSAFE_IO
|
||||
typedef pthread_mutex_t __libc_lock_t;
|
||||
typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t;
|
||||
# ifdef __USE_UNIX98
|
||||
typedef pthread_rwlock_t __libc_rwlock_t;
|
||||
# else
|
||||
typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
|
||||
# endif
|
||||
typedef __libc_lock_recursive_t __rtld_lock_recursive_t;
|
||||
#else
|
||||
typedef struct __libc_lock_opaque__ __libc_lock_t;
|
||||
typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
|
||||
typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
|
||||
#endif
|
||||
|
||||
/* Type for key to thread-specific data. */
|
||||
typedef pthread_key_t __libc_key_t;
|
||||
|
||||
/* Define a lock variable NAME with storage class CLASS. The lock must be
|
||||
initialized with __libc_lock_init before it can be used (or define it
|
||||
with __libc_lock_define_initialized, below). Use `extern' for CLASS to
|
||||
declare a lock defined in another module. In public structure
|
||||
definitions you must use a pointer to the lock structure (i.e., NAME
|
||||
begins with a `*'), because its storage size will not be known outside
|
||||
of libc. */
|
||||
#define __libc_lock_define(CLASS,NAME) \
|
||||
CLASS __libc_lock_t NAME;
|
||||
#define __libc_rwlock_define(CLASS,NAME) \
|
||||
CLASS __libc_rwlock_t NAME;
|
||||
#define __libc_lock_define_recursive(CLASS,NAME) \
|
||||
CLASS __libc_lock_recursive_t NAME;
|
||||
#define __rtld_lock_define_recursive(CLASS,NAME) \
|
||||
CLASS __rtld_lock_recursive_t NAME;
|
||||
|
||||
/* Define an initialized lock variable NAME with storage class CLASS.
|
||||
|
||||
For the C library we take a deeper look at the initializer. For
|
||||
this implementation all fields are initialized to zero. Therefore
|
||||
we don't initialize the variable which allows putting it into the
|
||||
BSS section. (Except on PA-RISC and other odd architectures, where
|
||||
initialized locks must be set to one due to the lack of normal
|
||||
atomic operations.) */
|
||||
|
||||
#if __LT_SPINLOCK_INIT == 0
|
||||
# define __libc_lock_define_initialized(CLASS,NAME) \
|
||||
CLASS __libc_lock_t NAME;
|
||||
#else
|
||||
# define __libc_lock_define_initialized(CLASS,NAME) \
|
||||
CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
#define __libc_rwlock_define_initialized(CLASS,NAME) \
|
||||
CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
|
||||
|
||||
/* Define an initialized recursive lock variable NAME with storage
|
||||
class CLASS. */
|
||||
#define __libc_lock_define_initialized_recursive(CLASS,NAME) \
|
||||
CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
|
||||
#define _LIBC_LOCK_RECURSIVE_INITIALIZER \
|
||||
{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
|
||||
|
||||
#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
|
||||
CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER;
|
||||
#define _RTLD_LOCK_RECURSIVE_INITIALIZER \
|
||||
{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
|
||||
|
||||
#if defined __PIC__
|
||||
# define __libc_maybe_call(FUNC, ARGS, ELSE) \
|
||||
(__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
|
||||
_fn != NULL ? (*_fn) ARGS : ELSE; }))
|
||||
#else
|
||||
# define __libc_maybe_call(FUNC, ARGS, ELSE) \
|
||||
(FUNC != NULL ? FUNC ARGS : ELSE)
|
||||
#endif
|
||||
#define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE)
|
||||
|
||||
/* Initialize the named lock variable, leaving it in a consistent, unlocked
|
||||
state. */
|
||||
#define __libc_lock_init(NAME) \
|
||||
(__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0))
|
||||
#define __libc_rwlock_init(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0));
|
||||
|
||||
/* Same as last but this time we initialize a recursive mutex. */
|
||||
#define __libc_lock_init_recursive(NAME) \
|
||||
do { \
|
||||
if (__pthread_mutex_init != NULL) \
|
||||
{ \
|
||||
pthread_mutexattr_t __attr; \
|
||||
__pthread_mutexattr_init (&__attr); \
|
||||
__pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \
|
||||
__pthread_mutex_init (&(NAME).mutex, &__attr); \
|
||||
__pthread_mutexattr_destroy (&__attr); \
|
||||
} \
|
||||
} while (0);
|
||||
#define __rtld_lock_init_recursive(NAME) \
|
||||
__libc_lock_init_recursive (NAME)
|
||||
|
||||
/* Finalize the named lock variable, which must be locked. It cannot be
|
||||
used again until __libc_lock_init is called again on it. This must be
|
||||
called on a lock variable before the containing storage is reused. */
|
||||
#define __libc_lock_fini(NAME) \
|
||||
(__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0));
|
||||
#define __libc_rwlock_fini(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0));
|
||||
|
||||
/* Finalize recursive named lock. */
|
||||
#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex)
|
||||
#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME)
|
||||
|
||||
/* Lock the named lock variable. */
|
||||
#define __libc_lock_lock(NAME) \
|
||||
(__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0));
|
||||
#define __libc_rwlock_rdlock(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0));
|
||||
#define __libc_rwlock_wrlock(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0));
|
||||
|
||||
/* Lock the recursive named lock variable. */
|
||||
#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex)
|
||||
|
||||
/* Try to lock the named lock variable. */
|
||||
#define __libc_lock_trylock(NAME) \
|
||||
(__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0))
|
||||
#define __libc_rwlock_tryrdlock(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0))
|
||||
#define __libc_rwlock_trywrlock(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0))
|
||||
|
||||
/* Try to lock the recursive named lock variable. */
|
||||
#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex)
|
||||
#define __rtld_lock_trylock_recursive(NAME) \
|
||||
__libc_lock_trylock_recursive (NAME)
|
||||
|
||||
/* Unlock the named lock variable. */
|
||||
#define __libc_lock_unlock(NAME) \
|
||||
(__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0));
|
||||
#define __libc_rwlock_unlock(NAME) \
|
||||
(__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0));
|
||||
|
||||
/* Unlock the recursive named lock variable. */
|
||||
#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex)
|
||||
|
||||
#define __rtld_lock_lock_recursive(NAME) __libc_lock_lock_recursive (NAME)
|
||||
#define __rtld_lock_unlock_recursive(NAME) __libc_lock_unlock_recursive (NAME)
|
||||
|
||||
/* Define once control variable. */
|
||||
#if PTHREAD_ONCE_INIT == 0
|
||||
/* Special case for static variables where we can avoid the initialization
|
||||
if it is zero. */
|
||||
# define __libc_once_define(CLASS, NAME) \
|
||||
CLASS pthread_once_t NAME
|
||||
#else
|
||||
# define __libc_once_define(CLASS, NAME) \
|
||||
CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
|
||||
#endif
|
||||
|
||||
/* Call handler iff the first call. */
|
||||
#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
|
||||
do { \
|
||||
if (__pthread_once != NULL) \
|
||||
__pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \
|
||||
else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \
|
||||
INIT_FUNCTION (); \
|
||||
(ONCE_CONTROL) = 2; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Start critical region with cleanup. */
|
||||
#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
|
||||
{ struct _pthread_cleanup_buffer _buffer; \
|
||||
int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \
|
||||
if (_avail) { \
|
||||
_pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \
|
||||
}
|
||||
|
||||
/* End critical region with cleanup. */
|
||||
#define __libc_cleanup_region_end(DOIT) \
|
||||
if (_avail) { \
|
||||
_pthread_cleanup_pop_restore (&_buffer, (DOIT)); \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Sometimes we have to exit the block in the middle. */
|
||||
#define __libc_cleanup_end(DOIT) \
|
||||
if (_avail) { \
|
||||
_pthread_cleanup_pop_restore (&_buffer, (DOIT)); \
|
||||
}
|
||||
|
||||
#define __libc_cleanup_push(fct, arg) \
|
||||
{ struct _pthread_cleanup_buffer _buffer; \
|
||||
__libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0)
|
||||
|
||||
#define __libc_cleanup_pop(execute) \
|
||||
__libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0); \
|
||||
}
|
||||
|
||||
/* Create thread-specific key. */
|
||||
#define __libc_key_create(KEY, DESTRUCTOR) \
|
||||
(__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1))
|
||||
|
||||
/* Get thread-specific data. */
|
||||
#define __libc_getspecific(KEY) \
|
||||
(__libc_maybe_call (__pthread_getspecific, (KEY), NULL))
|
||||
|
||||
/* Set thread-specific data. */
|
||||
#define __libc_setspecific(KEY, VALUE) \
|
||||
(__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0))
|
||||
|
||||
|
||||
/* Register handlers to execute before and after `fork'. */
|
||||
#define __libc_atfork(PREPARE, PARENT, CHILD) \
|
||||
(__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0))
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer,
|
||||
void (*__routine) (void *),
|
||||
void *__arg) __THROW;
|
||||
|
||||
extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer,
|
||||
int __execute) __THROW;
|
||||
|
||||
|
||||
/* Functions that are used by this file and are internal to the GNU C
|
||||
library. */
|
||||
|
||||
extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
|
||||
__const pthread_mutexattr_t *__mutex_attr);
|
||||
|
||||
extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
|
||||
|
||||
extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
|
||||
|
||||
extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
|
||||
|
||||
extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
|
||||
|
||||
extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr);
|
||||
|
||||
extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
|
||||
|
||||
extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
|
||||
int __kind);
|
||||
|
||||
#ifdef __USE_UNIX98
|
||||
extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
|
||||
__const pthread_rwlockattr_t *__attr);
|
||||
|
||||
extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
|
||||
|
||||
extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
|
||||
|
||||
extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
|
||||
|
||||
extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
|
||||
|
||||
extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
|
||||
|
||||
extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
|
||||
#endif
|
||||
|
||||
extern int __pthread_key_create (pthread_key_t *__key,
|
||||
void (*__destr_function) (void *));
|
||||
|
||||
extern int __pthread_setspecific (pthread_key_t __key,
|
||||
__const void *__pointer);
|
||||
|
||||
extern void *__pthread_getspecific (pthread_key_t __key);
|
||||
|
||||
extern int __pthread_once (pthread_once_t *__once_control,
|
||||
void (*__init_routine) (void));
|
||||
|
||||
extern int __pthread_atfork (void (*__prepare) (void),
|
||||
void (*__parent) (void),
|
||||
void (*__child) (void));
|
||||
|
||||
__END_DECLS
|
||||
|
||||
/* Make the pthread functions weak so that we can elide them from
|
||||
single-threaded processes. */
|
||||
#ifndef __NO_WEAK_PTHREAD_ALIASES
|
||||
# pragma weak __pthread_mutex_init
|
||||
# pragma weak __pthread_mutex_destroy
|
||||
# pragma weak __pthread_mutex_lock
|
||||
# pragma weak __pthread_mutex_trylock
|
||||
# pragma weak __pthread_mutex_unlock
|
||||
# pragma weak __pthread_mutexattr_init
|
||||
# pragma weak __pthread_mutexattr_destroy
|
||||
# pragma weak __pthread_mutexattr_settype
|
||||
# pragma weak __pthread_rwlock_destroy
|
||||
# pragma weak __pthread_rwlock_rdlock
|
||||
# pragma weak __pthread_rwlock_tryrdlock
|
||||
# pragma weak __pthread_rwlock_wrlock
|
||||
# pragma weak __pthread_rwlock_trywrlock
|
||||
# pragma weak __pthread_rwlock_unlock
|
||||
# pragma weak __pthread_key_create
|
||||
# pragma weak __pthread_setspecific
|
||||
# pragma weak __pthread_getspecific
|
||||
# pragma weak __pthread_once
|
||||
# pragma weak __pthread_initialize
|
||||
# pragma weak __pthread_atfork
|
||||
# pragma weak _pthread_cleanup_push_defer
|
||||
# pragma weak _pthread_cleanup_pop_restore
|
||||
# pragma weak _pthread_cleanup_push
|
||||
# pragma weak _pthread_cleanup_pop
|
||||
#endif
|
||||
|
||||
/* We need portable names for some functions. E.g., when they are
|
||||
used as argument to __libc_cleanup_region_start. */
|
||||
#define __libc_mutex_unlock __pthread_mutex_unlock
|
||||
|
||||
#endif /* bits/libc-lock.h */
|
@ -1,62 +0,0 @@
|
||||
#
|
||||
# /etc/nsswitch.conf
|
||||
#
|
||||
# An example Name Service Switch config file. This file should be
|
||||
# sorted with the most-used services at the beginning.
|
||||
#
|
||||
# The entry '[NOTFOUND=return]' means that the search for an
|
||||
# entry should stop if the search in the previous entry turned
|
||||
# up nothing. Note that if the search failed due to some other reason
|
||||
# (like no NIS server responding) then the search continues with the
|
||||
# next entry.
|
||||
#
|
||||
# Valid entries include:
|
||||
#
|
||||
# nisplus Use NIS+ (NIS version 3)
|
||||
# nis Use NIS (NIS version 2), also called YP
|
||||
# dns Use DNS (Domain Name Service)
|
||||
# files Use the local files
|
||||
# db Use the local database (.db) files
|
||||
# compat Use NIS on compat mode
|
||||
# hesiod Use Hesiod for user lookups
|
||||
# [NOTFOUND=return] Stop searching if not found so far
|
||||
#
|
||||
|
||||
# To use db, put the "db" in front of "files" for entries you want to be
|
||||
# looked up first in the databases
|
||||
#
|
||||
# Example:
|
||||
#passwd: db files nisplus nis
|
||||
#shadow: db files nisplus nis
|
||||
#group: db files nisplus nis
|
||||
|
||||
passwd: files sss
|
||||
shadow: files sss
|
||||
group: files sss
|
||||
|
||||
#hosts: db files nisplus nis dns
|
||||
hosts: files dns
|
||||
|
||||
# Example - obey only what nisplus tells us...
|
||||
#services: nisplus [NOTFOUND=return] files
|
||||
#networks: nisplus [NOTFOUND=return] files
|
||||
#protocols: nisplus [NOTFOUND=return] files
|
||||
#rpc: nisplus [NOTFOUND=return] files
|
||||
#ethers: nisplus [NOTFOUND=return] files
|
||||
#netmasks: nisplus [NOTFOUND=return] files
|
||||
|
||||
bootparams: nisplus [NOTFOUND=return] files
|
||||
|
||||
ethers: files
|
||||
netmasks: files
|
||||
networks: files
|
||||
protocols: files
|
||||
rpc: files
|
||||
services: files sss
|
||||
|
||||
netgroup: nisplus sss
|
||||
|
||||
publickey: nisplus
|
||||
|
||||
automount: files nisplus
|
||||
aliases: files nisplus
|
@ -3,8 +3,8 @@
|
||||
export QUILT_PATCHES=$PWD
|
||||
# Extract source file name from sources file,
|
||||
# and assume it's the same name as the directory.
|
||||
source=`cat sources | sed -e 's,^.* ,,g'`
|
||||
srcdir=${source%.tar.gz}
|
||||
source=`awk -F '[() ]+' '/^[A-Z0-9]+ /{print $2}; /^[0-9a-f]+ /{print $2}' sources`
|
||||
srcdir=${source%.tar.xz}
|
||||
if [ "$1" == "-f" ] && [ -d "$srcdir" ]; then
|
||||
echo Cleaning up $srcdir
|
||||
rm -rf $srcdir
|
||||
@ -14,7 +14,7 @@ if [ -d "$srcdir" ]; then
|
||||
echo "ERROR: Source directory $srcdir already exists. Use -f to force cleanup step."
|
||||
exit 1
|
||||
fi
|
||||
tar zxvf $source
|
||||
tar Jxvf $source
|
||||
echo "Entering $srcdir"
|
||||
pushd $srcdir
|
||||
# Apply all patches.
|
||||
|
43
series
43
series
@ -1,43 +0,0 @@
|
||||
glibc-fedora-nscd.patch -p1 --fuzz=0
|
||||
glibc-fedora-ldd.patch -p1 --fuzz=0
|
||||
glibc-fedora-ppc-unwind.patch -p1 --fuzz=0
|
||||
glibc-rh825061.patch -p1 --fuzz=0
|
||||
glibc-arm-hardfloat-3.patch -p1 --fuzz=0
|
||||
glibc-rh697421.patch -p1 --fuzz=0
|
||||
glibc-fedora-include-bits-ldbl.patch -p1 --fuzz=0
|
||||
glibc-fedora-linux-tcsetattr.patch -p1 --fuzz=0
|
||||
glibc-rh741105.patch -p1 --fuzz=0
|
||||
glibc-fedora-nptl-linklibc.patch -p1 --fuzz=0
|
||||
glibc-fedora-localedef.patch -p1 --fuzz=0
|
||||
glibc-fedora-i386-tls-direct-seg-refs.patch -p1 --fuzz=0
|
||||
glibc-fedora-nis-rh188246.patch -p1 --fuzz=0
|
||||
glibc-fedora-manual-dircategory.patch -p1 --fuzz=0
|
||||
glibc-rh827510.patch -p1 --fuzz=0
|
||||
glibc-fedora-locarchive.patch -p1 --fuzz=0
|
||||
glibc-fedora-streams-rh436349.patch -p1 --fuzz=0
|
||||
glibc-rh819430.patch -p1 --fuzz=0
|
||||
glibc-fedora-localedata-rh61908.patch -p1 --fuzz=0
|
||||
glibc-fedora-uname-getrlimit.patch -p1 --fuzz=0
|
||||
glibc-fedora-__libc_multiple_libcs.patch -p1 --fuzz=0
|
||||
glibc-fedora-elf-ORIGIN.patch -p1 --fuzz=0
|
||||
glibc-rh952799.patch -p1 --fuzz=0
|
||||
glibc-rh1009145.patch -p1 --fuzz=0
|
||||
glibc-rh1013801.patch -p1 --fuzz=0
|
||||
glibc-rh1070416.patch -p1 --fuzz=0
|
||||
glibc-nscd-sysconfig.patch -p1 --fuzz=0
|
||||
glibc-aarch64-tls-fixes.patch -p1 --fuzz=0
|
||||
glibc-aarch64-workaround-nzcv-clobber-in-tlsdesc.patch -p1 --fuzz=0
|
||||
glibc-disable-rwlock-elision.patch -p1 --fuzz=0
|
||||
glibc-cs-path.patch -p1 --fuzz=0
|
||||
glibc-bench-build.patch -p1 --fuzz=0
|
||||
glibc-res-hconf-gcc5.patch -p1 --fuzz=0
|
||||
glibc-ld-ctype-gcc5.patch -p1 --fuzz=0
|
||||
glibc-gethnamaddr-gcc5.patch -p1 --fuzz=0
|
||||
glibc-dns-host-gcc5.patch -p1 --fuzz=0
|
||||
glibc-bug-regex-gcc5.patch -p1 --fuzz=0
|
||||
glibc-c-utf8-locale.patch -p1 --fuzz=0
|
||||
glibc-nsswitch-Add-group-merging-support.patch -p1 --fuzz=0
|
||||
glibc-gcc-PR69537.patch -p1 --fuzz=0
|
||||
glibc-isinf-cxx11.patch -p1 --fuzz=0
|
||||
glibc-rh1252570.patch -p1 --fuzz=0
|
||||
glibc-CVE-2015-7547.patch -p1 --fuzz=0
|
2
sources
2
sources
@ -1 +1 @@
|
||||
59f24ea4c6c662c064f54a64fca055a6 glibc-2.22-719-g1233be7.tar.gz
|
||||
SHA512 (glibc-2.30.9000-100-g1a6566094d.tar.xz) = e6054a8f1367fde262f023c76f7eaf5ce588613c4894b8d577c7e1c3159a2dfcefb7c60e301340b823cd8e6d2f8d264d7da83e61034b9180836d392d5db4c5ba
|
||||
|
@ -1,98 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Given a git source repo, generate a tarball from the desired branch, modify
|
||||
# the spec file and upload it to lookaside cache if the tarball unpacks and
|
||||
# gets patched cleanly.
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# 1. Invoke the script as follows:
|
||||
#
|
||||
# ./sync-upstream.sh upstream-repo
|
||||
#
|
||||
# where upstream-repo is the path to the synced upstream git repo.
|
||||
#
|
||||
# 2. Watch the script run. If it proceeds to building the package, then
|
||||
# everything seems good and you just need to test the build after it
|
||||
# is complete. If it exits before the build (you'll know if you read
|
||||
# the output of the script) then manual intervention is required to
|
||||
# complete the sync. This will typically happen when a patch fails
|
||||
# to apply on the new sources.
|
||||
|
||||
set -e
|
||||
|
||||
# We want to sync from master by default. Change this if you want to sync from
|
||||
# another branch.
|
||||
branch=master
|
||||
|
||||
# We can't do anything without an upstream repo
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: $0 <path-to-upstream-repo>" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
upstream=$1
|
||||
|
||||
srcdir=$(git --git-dir=$upstream/.git describe $branch)
|
||||
cursrc=$(sed -ne 's/^%define glibcsrcdir \(.*\)/\1/p' glibc.spec)
|
||||
|
||||
# Upstream has not moved forward since the last sync.
|
||||
# TODO: Some time in the future, we might want to only sync when upstream has
|
||||
# advanced more than a certain number of commits, say, 42.
|
||||
if [ "$cursrc" = "$srcdir" ]; then
|
||||
echo "+ Already in sync with upstream."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Generate and gzip the tarball from the desired branch of the repository.
|
||||
echo "+ Generating tarball."
|
||||
git --git-dir="$upstream/.git" archive --prefix="$srcdir/" "$branch" \
|
||||
> "$srcdir.tar"
|
||||
gzip -9 "$srcdir.tar"
|
||||
echo "+ Created $srcdir.tar.gz"
|
||||
|
||||
# Our changelog header
|
||||
cldate=$(date +'%a %b %d %Y')
|
||||
clname=$(git config --get user.name)
|
||||
clemail=$(git config --get user.email | sed 's/@/\\@/')
|
||||
|
||||
# Getting our version and release number from the spec file.
|
||||
nv=$(perl -ne 's/^%define glibcversion (.+)/printf("%s-", $1)/e;' \
|
||||
-e 's/^%define glibcrelease ([0-9]+).*/printf("%d\n", $1 + 1)/e;' \
|
||||
glibc.spec)
|
||||
|
||||
# Our changelog entry.
|
||||
changelog="* $cldate $clname <$clemail> - $nv\n- Auto-sync with upstream $branch.\n"
|
||||
|
||||
# Change the glibcsrcdir variable, bump up the release number and add an extra
|
||||
# entry to the changelog.
|
||||
echo "+ Updating spec file."
|
||||
perl -pi \
|
||||
-e "s/^(%define glibcsrcdir ).+/\$1$srcdir/;
|
||||
s/^(%define glibcrelease )(\d+)/print(\$1); print(\$2 + 1);'';/e;
|
||||
s/^(%changelog)$/\$1\n$changelog/" \
|
||||
glibc.spec
|
||||
|
||||
function prep_failed {
|
||||
# fedpkg prep failed.
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "+ Source prep failed."
|
||||
echo "+ Check the output in $tmpfile and fix things before committing."
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
echo "+ Testing if fedpkg prep works."
|
||||
tmpfile=$(mktemp fedpkg-prep.out-XXXX)
|
||||
|
||||
trap prep_failed EXIT
|
||||
fedpkg prep > "$tmpfile" 2>&1
|
||||
# Remove mess created by fedpkg prep
|
||||
rm -f "$tmpfile"
|
||||
rm -rf "$srcdir"
|
||||
echo "+ Source prep is clean, so we're good to go."
|
||||
fedpkg new-sources "$srcdir.tar.gz"
|
||||
git commit -a -m "Auto-sync with upstream $branch."
|
||||
exit 0
|
||||
fedpkg push
|
||||
fedpkg build
|
||||
echo "+ Done!"
|
@ -5,7 +5,7 @@ Origin: <Source repo(s) where it came from or keyword "PATCH" if this is simply
|
||||
Bug-RHEL: <Rhel bug #'s, comma separated e.g. #XXX, #YYY, #ZZZ>
|
||||
Bug-Fedora: <Fedora bug #'s, comma separated e.g. #XXX, #YYY, #ZZZ>
|
||||
Bug-Upstream: <Upstream bug#'s, comma separated e.g. #XXX, #YYY, #ZZZ>
|
||||
Upstream status: <[Patchwork URL|not-needed|not-submitted|committed] for each commit>
|
||||
# <Additional descriptive text in comment block>
|
||||
Upstream status: <[Patchwork URL|libc-alpha URL|not-needed|not-submitted|committed] for each commit>
|
||||
# <Additional descriptive text follows 'Upstream status:' line>
|
||||
<If upstream status == committed then a copy of the upstream commit log follows>
|
||||
<Patch>
|
||||
|
Loading…
Reference in New Issue
Block a user