diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9743564
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+SOURCES/libuser-0.60.tar.xz
diff --git a/.libuser.metadata b/.libuser.metadata
new file mode 100644
index 0000000..8f7331a
--- /dev/null
+++ b/.libuser.metadata
@@ -0,0 +1 @@
+8aa1cd4d7d6a0c3a43a59679efe53fb203409033 SOURCES/libuser-0.60.tar.xz
diff --git a/SOURCES/libuser-0.60-ja.po b/SOURCES/libuser-0.60-ja.po
new file mode 100644
index 0000000..ebd2938
--- /dev/null
+++ b/SOURCES/libuser-0.60-ja.po
@@ -0,0 +1,1480 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Red Hat, Inc.
+# This file is distributed under the same license as the PACKAGE package.
+# 
+# Translators:
+# Hajime Taira <htaira@redhat.com>, 2011-2012
+# Hirofumi Saito <hi_saito@yk.rim.or.jp>, 2004, 2005, 2006
+# hyuugabaru <hyu_gabaru@yahoo.co.jp>, 2007, 2009
+# Kiyoto Hashida <khashida@redhat.com>, 2002
+# Kiyoto Hashida <khashida@redhat.com>, 2009
+# Makoto Mizukami <mmk9060@aol.com>, 2008
+# Miloslav Trmač <mitr@volny.cz>, 2011
+# Noriko Mizumoto <noriko@redhat.com>, 2007, 2008, 2009
+# Tomoyuki KATO <tomo@dream.daynight.jp>, 2011-2013
+# 高一人参 @欠陥遺伝子 <www.carrotsoft@gmail.com>, 2011
+# Yukihiro Nakai <ynakai@redhat.com>, 2001
+# amoewaki <amoewaki@redhat.com>, 2017. #zanata
+# ljanda <ljanda@redhat.com>, 2017. #zanata
+# amoewaki <amoewaki@redhat.com>, 2018. #zanata
+msgid ""
+msgstr ""
+"Project-Id-Version: libuser 0.60\n"
+"Report-Msgid-Bugs-To: http://bugzilla.redhat.com/bugzilla/\n"
+"POT-Creation-Date: 2018-01-02 13:27+0100\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"PO-Revision-Date: 2018-01-09 01:19+0000\n"
+"Last-Translator: amoewaki <amoewaki@redhat.com>\n"
+"Language-Team: Japanese (http://www.transifex.com/projects/p/fedora/language/"
+"ja/)\n"
+"Language: ja\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Zanata 4.3.2\n"
+
+#: apps/apputil.c:197 apps/apputil.c:201
+#, c-format
+msgid "Failed to drop privileges.\n"
+msgstr "特権の停止に失敗しました。\n"
+
+#: apps/apputil.c:210
+#, c-format
+msgid "Internal error.\n"
+msgstr "内部エラーです。\n"
+
+#: apps/apputil.c:231
+#, c-format
+msgid "%s is not authorized to change the finger info of %s\n"
+msgstr "%s が %s の finger 情報を変更するのは許可されていません\n"
+
+#: apps/apputil.c:233
+msgid "Unknown user context"
+msgstr "不明なユーザーのコンテキスト"
+
+#: apps/apputil.c:241
+#, c-format
+msgid "Can't set default context for /etc/passwd\n"
+msgstr "/etc/passwd 用のデフォルトのコンテキストが設定できません\n"
+
+#: apps/apputil.c:250
+#, c-format
+msgid "Error initializing PAM.\n"
+msgstr "PAM の初期化に失敗\n"
+
+#: apps/apputil.c:260 apps/apputil.c:287
+#, c-format
+msgid "Authentication failed for %s.\n"
+msgstr "%s の認証に失敗しました。\n"
+
+#: apps/apputil.c:268
+#, c-format
+msgid "Internal PAM error `%s'.\n"
+msgstr "内部 PAM エラー `%s'\n"
+
+#: apps/apputil.c:273
+#, c-format
+msgid "Unknown user authenticated.\n"
+msgstr "不明なユーザー認証です。\n"
+
+#: apps/apputil.c:277
+#, c-format
+msgid "User mismatch.\n"
+msgstr "ユーザーが一致しませんでした。\n"
+
+#: apps/lchage.c:84 apps/lchfn.c:53 apps/lchsh.c:44 apps/lgroupadd.c:47
+#: apps/lgroupdel.c:42 apps/lgroupmod.c:54 apps/lid.c:115 apps/lnewusers.c:45
+#: apps/lpasswd.c:47 apps/luseradd.c:55 apps/luserdel.c:45 apps/lusermod.c:56
+msgid "prompt for all information"
+msgstr "すべての情報について入力確認する"
+
+#: apps/lchage.c:86
+msgid "list aging parameters for the user"
+msgstr "ユーザーのエージングパラメーターを一覧表示する"
+
+#: apps/lchage.c:88
+msgid "minimum days between password changes"
+msgstr "パスワード変更間隔の最小日数"
+
+#: apps/lchage.c:88 apps/lchage.c:90 apps/lchage.c:93 apps/lchage.c:96
+#: apps/lchage.c:99 apps/lchage.c:102
+msgid "DAYS"
+msgstr "日数"
+
+#: apps/lchage.c:90
+msgid "maximum days between password changes"
+msgstr "パスワード変更後の有効日数"
+
+#: apps/lchage.c:92
+msgid "date of last password change in days since 1/1/70"
+msgstr "パスワード変更日 (1970/1/1 からの日数)"
+
+#: apps/lchage.c:95
+msgid ""
+"number of days after password expiration date when account is considered "
+"inactive"
+msgstr "パスワード失効後、アカウントが無効であるとみなされるまでの日数"
+
+#: apps/lchage.c:98
+msgid "password expiration date in days since 1/1/70"
+msgstr "パスワード失効日 (1970/1/1 からの日数)"
+
+#: apps/lchage.c:101
+msgid "days before expiration to begin warning user"
+msgstr "ユーザーに警告を開始する、パスワード失効までの日数"
+
+#: apps/lchage.c:114 apps/lid.c:130 apps/lpasswd.c:68 apps/luseradd.c:100
+#: apps/luserdel.c:59 apps/lusermod.c:101
+msgid "[OPTION...] user"
+msgstr "[オプション...] ユーザー"
+
+#: apps/lchage.c:117 apps/lchfn.c:70 apps/lchsh.c:58 apps/lgroupadd.c:65
+#: apps/lgroupdel.c:56 apps/lgroupmod.c:85 apps/lid.c:133 apps/lnewusers.c:66
+#: apps/lpasswd.c:71 apps/luseradd.c:103 apps/luserdel.c:62 apps/lusermod.c:104
+#, c-format
+msgid "Error parsing arguments: %s.\n"
+msgstr "引数の構文解析に失敗: %s\n"
+
+#: apps/lchage.c:126 apps/lpasswd.c:85 apps/luseradd.c:118 apps/luserdel.c:70
+#: apps/lusermod.c:115
+#, c-format
+msgid "No user name specified.\n"
+msgstr "ユーザー名が指定されていません。\n"
+
+#: apps/lchage.c:138 apps/lchfn.c:103 apps/lchsh.c:91 apps/lgroupadd.c:102
+#: apps/lgroupdel.c:77 apps/lgroupmod.c:119 apps/lid.c:179 apps/lnewusers.c:79
+#: apps/lpasswd.c:97 apps/luseradd.c:143 apps/luserdel.c:81 apps/lusermod.c:157
+#: samples/enum.c:56 samples/testuser.c:71
+#, c-format
+msgid "Error initializing %s: %s.\n"
+msgstr "%s の初期化に失敗: %s\n"
+
+#: apps/lchage.c:147 apps/lchfn.c:114 apps/lchsh.c:102 apps/lpasswd.c:148
+#: apps/luserdel.c:89 apps/lusermod.c:171
+#, c-format
+msgid "User %s does not exist.\n"
+msgstr "ユーザー %s は存在しません。\n"
+
+#: apps/lchage.c:160
+#, c-format
+msgid "Account is locked.\n"
+msgstr "アカウントはロックされています。\n"
+
+#: apps/lchage.c:162
+#, c-format
+msgid "Account is not locked.\n"
+msgstr "アカウントはロックされていません。\n"
+
+#: apps/lchage.c:166
+#, c-format
+msgid "Minimum:	%ld\n"
+msgstr "最小:	%ld\n"
+
+#: apps/lchage.c:170
+#, c-format
+msgid "Maximum:	%ld\n"
+msgstr "最大:	%ld\n"
+
+#: apps/lchage.c:172
+#, c-format
+msgid "Maximum:	None\n"
+msgstr "最大値:	なし\n"
+
+#: apps/lchage.c:175
+#, c-format
+msgid "Warning:	%ld\n"
+msgstr "警告:	%ld\n"
+
+#: apps/lchage.c:180
+#, c-format
+msgid "Inactive:	%ld\n"
+msgstr "無効:	%ld\n"
+
+#: apps/lchage.c:182
+#, c-format
+msgid "Inactive:	Never\n"
+msgstr "無効化:	なし\n"
+
+#: apps/lchage.c:186 apps/lchage.c:194 apps/lchage.c:204
+msgid "Must change password on next login"
+msgstr "次回ログイン時に必ずパスワードを変更"
+
+#: apps/lchage.c:188 apps/lchage.c:196 apps/lchage.c:206 apps/lchage.c:215
+msgid "Never"
+msgstr "なし"
+
+#: apps/lchage.c:191
+#, c-format
+msgid "Last Change:	%s\n"
+msgstr "最終更新: 	%s\n"
+
+#: apps/lchage.c:201
+#, c-format
+msgid "Password Expires:	%s\n"
+msgstr "パスワード期限切れ:	%s\n"
+
+#: apps/lchage.c:213
+#, c-format
+msgid "Password Inactive:	%s\n"
+msgstr "パスワード無効:	%s\n"
+
+#: apps/lchage.c:219
+#, c-format
+msgid "Account Expires:	%s\n"
+msgstr "アカウント期限切れ:	%s\n"
+
+#: apps/lchage.c:240
+#, c-format
+msgid "Failed to modify aging information for %s: %s\n"
+msgstr "%s のエージング情報の更新に失敗しました: %s\n"
+
+#: apps/lchfn.c:67 apps/lchsh.c:55
+msgid "[OPTION...] [user]"
+msgstr "[オプション...] [ユーザー]"
+
+#: apps/lchfn.c:86 apps/lchsh.c:74 apps/lid.c:164
+#, c-format
+msgid "No user name specified, no name for uid %d.\n"
+msgstr "ユーザー名が未指定で、uid %d の名前がありません。\n"
+
+#: apps/lchfn.c:96
+#, c-format
+msgid "Changing finger information for %s.\n"
+msgstr "%s 用の finger 情報を変更しています。\n"
+
+#: apps/lchfn.c:136
+msgid "Full Name"
+msgstr "フルネーム"
+
+#: apps/lchfn.c:146
+msgid "Surname"
+msgstr "姓"
+
+#: apps/lchfn.c:157
+msgid "Given Name"
+msgstr "名"
+
+#: apps/lchfn.c:167
+msgid "Office"
+msgstr "勤務先"
+
+#: apps/lchfn.c:176
+msgid "Office Phone"
+msgstr "勤務先電話番号"
+
+#: apps/lchfn.c:185
+msgid "Home Phone"
+msgstr "自宅電話番号"
+
+#: apps/lchfn.c:195
+msgid "E-Mail Address"
+msgstr "メールアドレス"
+
+#: apps/lchfn.c:208
+#, c-format
+msgid "Finger information not changed:  input error.\n"
+msgstr "Finger 情報は変更されていません: 入力エラー\n"
+
+#: apps/lchfn.c:270
+msgid "Finger information changed.\n"
+msgstr "Finger 情報が変更されました。\n"
+
+#: apps/lchfn.c:273
+#, c-format
+msgid "Finger information not changed: %s.\n"
+msgstr "Finger 情報は変更されていません: %s\n"
+
+#: apps/lchsh.c:84
+#, c-format
+msgid "Changing shell for %s.\n"
+msgstr "%s 用にシェルを変更中\n"
+
+#: apps/lchsh.c:114
+msgid "New Shell"
+msgstr "新規のシェル"
+
+#: apps/lchsh.c:121 apps/lchsh.c:136
+#, c-format
+msgid "Shell not changed: %s\n"
+msgstr "シェル変更不可能: %s\n"
+
+#: apps/lchsh.c:133
+msgid "Shell changed.\n"
+msgstr "シェル変更済み\n"
+
+#: apps/lgroupadd.c:49
+msgid "gid for new group"
+msgstr "新しいグループの GID"
+
+#: apps/lgroupadd.c:49 apps/lgroupmod.c:56 apps/lpasswd.c:56 apps/lpasswd.c:59
+#: apps/luseradd.c:67 apps/lusermod.c:66 apps/lusermod.c:68
+msgid "NUM"
+msgstr "番号"
+
+#: apps/lgroupadd.c:51
+msgid "create a system group"
+msgstr "システムグループを作成します"
+
+#: apps/lgroupadd.c:62 apps/lgroupdel.c:53 apps/lgroupmod.c:82
+msgid "[OPTION...] group"
+msgstr "[オプション...] グループ"
+
+#: apps/lgroupadd.c:74 apps/lgroupdel.c:65 apps/lgroupmod.c:93
+#, c-format
+msgid "No group name specified.\n"
+msgstr "グループ名は指定されていません。\n"
+
+#: apps/lgroupadd.c:87 apps/lgroupmod.c:105 apps/lnewusers.c:172
+#: apps/luseradd.c:164 apps/lusermod.c:127
+#, c-format
+msgid "Invalid group ID %s\n"
+msgstr "無効なグループ ID: %s\n"
+
+#: apps/lgroupadd.c:119
+#, c-format
+msgid "Group creation failed: %s\n"
+msgstr "グループの作成に失敗しました: %s\n"
+
+#: apps/lgroupdel.c:85 apps/lgroupmod.c:132 apps/lpasswd.c:153
+#, c-format
+msgid "Group %s does not exist.\n"
+msgstr "グループ %s は存在しません。\n"
+
+#: apps/lgroupdel.c:91
+#, c-format
+msgid "Group %s could not be deleted: %s\n"
+msgstr "グループ %s は削除できませんでした: %s\n"
+
+#: apps/lgroupmod.c:56
+msgid "set GID for group"
+msgstr "グループの GID を設定します"
+
+#: apps/lgroupmod.c:58
+msgid "change group to have given name"
+msgstr "グループを、指定された名前に変更する"
+
+#: apps/lgroupmod.c:58
+msgid "NAME"
+msgstr "名前"
+
+#: apps/lgroupmod.c:60 apps/luseradd.c:75
+msgid "plaintext password for use with group"
+msgstr "グループに用いる平文パスワード"
+
+#: apps/lgroupmod.c:60 apps/lgroupmod.c:62 apps/lgroupmod.c:64
+#: apps/lgroupmod.c:66 apps/lgroupmod.c:68 apps/lgroupmod.c:70
+#: apps/lpasswd.c:51 apps/lpasswd.c:53 apps/luseradd.c:59 apps/luseradd.c:61
+#: apps/luseradd.c:63 apps/luseradd.c:65 apps/luseradd.c:69 apps/luseradd.c:75
+#: apps/luseradd.c:77 apps/luseradd.c:79 apps/luseradd.c:81 apps/luseradd.c:83
+#: apps/luseradd.c:85 apps/luseradd.c:87 apps/luseradd.c:89 apps/lusermod.c:58
+#: apps/lusermod.c:60 apps/lusermod.c:64 apps/lusermod.c:70 apps/lusermod.c:72
+#: apps/lusermod.c:74 apps/lusermod.c:80 apps/lusermod.c:82 apps/lusermod.c:84
+#: apps/lusermod.c:86 apps/lusermod.c:88 apps/lusermod.c:90
+msgid "STRING"
+msgstr "文字列"
+
+#: apps/lgroupmod.c:62 apps/luseradd.c:77
+msgid "pre-hashed password for use with group"
+msgstr "グループに用いるハッシュ化パスワード"
+
+#: apps/lgroupmod.c:64
+msgid "list of administrators to add"
+msgstr "追加する管理者の一覧"
+
+#: apps/lgroupmod.c:66
+msgid "list of administrators to remove"
+msgstr "削除する管理者の一覧"
+
+#: apps/lgroupmod.c:68
+msgid "list of group members to add"
+msgstr "追加するグループメンバーの一覧"
+
+#: apps/lgroupmod.c:70
+msgid "list of group members to remove"
+msgstr "削除するグループメンバーの一覧"
+
+#: apps/lgroupmod.c:71
+msgid "lock group"
+msgstr "グループをロックします"
+
+#: apps/lgroupmod.c:72
+msgid "unlock group"
+msgstr "グループのロックを解除します"
+
+#: apps/lgroupmod.c:125 apps/lusermod.c:164
+#, c-format
+msgid "Both -L and -U specified.\n"
+msgstr "-L と -U の両方のオプションが指定されています。\n"
+
+#: apps/lgroupmod.c:139 apps/lgroupmod.c:148
+#, c-format
+msgid "Failed to set password for group %s: %s\n"
+msgstr "グループ %s のパスワード設定に失敗しました: %s\n"
+
+#: apps/lgroupmod.c:157
+#, c-format
+msgid "Group %s could not be locked: %s\n"
+msgstr "グループ %s はロックされませんでした: %s\n"
+
+#: apps/lgroupmod.c:166
+#, c-format
+msgid "Group %s could not be unlocked: %s\n"
+msgstr "グループ %s はロック解除できませんでした: %s\n"
+
+#: apps/lgroupmod.c:242 apps/lgroupmod.c:257
+#, c-format
+msgid "Group %s could not be modified: %s\n"
+msgstr "グループ %s は修正できませんでした: %s\n"
+
+#: apps/lid.c:42 apps/lid.c:74 apps/lid.c:188
+#, c-format
+msgid "Error looking up %s: %s\n"
+msgstr "%s の検索に失敗: %s\n"
+
+#: apps/lid.c:117
+msgid ""
+"list members of a named group instead of the group memberships for the named "
+"user"
+msgstr "指定された名前のユーザーがメンバーであるグループの代わりに、指定された名前のグループのメンバーを一覧表示します"
+
+#: apps/lid.c:120
+msgid "only list membership information by name, and not UID/GID"
+msgstr "UID/GID ではなく、名前でのみメンバー情報を一覧表示する"
+
+#: apps/lid.c:146
+#, c-format
+msgid "No group name specified, using %s.\n"
+msgstr "グループ名は未指定です。%s を使用中\n"
+
+#: apps/lid.c:150
+#, c-format
+msgid "No group name specified, no name for gid %d.\n"
+msgstr "グループ名は未指定です。gid %d の名前は未設定\n"
+
+#: apps/lid.c:160
+#, c-format
+msgid "No user name specified, using %s.\n"
+msgstr "ユーザー名が未指定です。%s を使用中\n"
+
+#: apps/lid.c:192
+#, c-format
+msgid "%s does not exist\n"
+msgstr "%s は存在しません。\n"
+
+#: apps/lnewusers.c:47
+msgid "file with user information records"
+msgstr "ユーザー情報レコードを持つファイル"
+
+#: apps/lnewusers.c:47
+msgid "PATH"
+msgstr "パス"
+
+#: apps/lnewusers.c:49
+msgid "don't create home directories"
+msgstr "ホームディレクトリーを作成しない"
+
+#: apps/lnewusers.c:51
+msgid "don't create mail spools"
+msgstr "メールスプールを作成しない"
+
+#: apps/lnewusers.c:63
+msgid "[OPTION...]"
+msgstr "[オプション...]"
+
+#: apps/lnewusers.c:88
+#, c-format
+msgid "Error opening `%s': %s.\n"
+msgstr "%s の読み込みエラー: %s\n"
+
+#: apps/lnewusers.c:118
+#, c-format
+msgid "Error creating account for `%s': line improperly formatted.\n"
+msgstr "`%s' 用のアカウント作成に失敗:  不正な書式が含まれています。\n"
+
+#: apps/lnewusers.c:129 apps/luseradd.c:128 apps/lusermod.c:142
+#, c-format
+msgid "Invalid user ID %s\n"
+msgstr "無効なユーザー ID %s\n"
+
+#: apps/lnewusers.c:136
+msgid "Refusing to create account with UID 0.\n"
+msgstr "UID:0 でのアカウント作成を拒否中です。\n"
+
+#: apps/lnewusers.c:206
+#, c-format
+msgid "Error creating group for `%s' with GID %jd: %s\n"
+msgstr "%s 用に、GID %jd でグループの作成中にエラーが発生しました: %s\n"
+
+#: apps/lnewusers.c:246
+#, c-format
+msgid "Refusing to use dangerous home directory `%s' for %s by default\n"
+msgstr "デフォルトで、%s 用の危険なホームディレクトリー %s の使用を拒否中です\n"
+
+#: apps/lnewusers.c:257
+#, c-format
+msgid "Error creating home directory for %s: %s\n"
+msgstr "%s 用の新規ホームディレクトリー作成に失敗しました: %s\n"
+
+#: apps/lnewusers.c:270
+#, c-format
+msgid "Error creating mail spool for %s: %s\n"
+msgstr "%s のメールスプールの作成中にエラーが発生しました: %s\n"
+
+#: apps/lnewusers.c:285
+#, c-format
+msgid "Error setting initial password for %s: %s\n"
+msgstr "%s 用の初期パスワード設定中にエラーが発生しました: %s\n"
+
+#: apps/lnewusers.c:295
+#, c-format
+msgid "Error creating user account for %s: %s\n"
+msgstr "%s 用のユーザーアカウント作成に失敗しました: %s。\n"
+
+#: apps/lpasswd.c:49
+msgid "set group password instead of user password"
+msgstr "ユーザーのパスワードの代わりにグループのパスワードを設定します"
+
+#: apps/lpasswd.c:51
+msgid "new plain password"
+msgstr "新しい平文パスワード"
+
+#: apps/lpasswd.c:53
+msgid "new crypted password"
+msgstr "新しい暗号文パスワード"
+
+#: apps/lpasswd.c:55
+msgid "read new plain password from given descriptor"
+msgstr "指定された記述子から新しい平文パスワードを読み込みます"
+
+#: apps/lpasswd.c:58
+msgid "read new crypted password from given descriptor"
+msgstr "指定された記述子から新しい暗号パスワードを読み込みます"
+
+#: apps/lpasswd.c:83
+#, c-format
+msgid "Changing password for %s.\n"
+msgstr "%s のパスワード変更中にエラー。\n"
+
+#: apps/lpasswd.c:111
+msgid "New password"
+msgstr "新規パスワード"
+
+#: apps/lpasswd.c:114
+msgid "New password (confirm)"
+msgstr "新規パスワード (確認)"
+
+#: apps/lpasswd.c:128
+#, c-format
+msgid "Passwords do not match, try again.\n"
+msgstr "パスワードが一致しません。もう一度やり直してください。\n"
+
+#: apps/lpasswd.c:133
+#, c-format
+msgid "Password change canceled.\n"
+msgstr "パスワード変更は取り消されました。\n"
+
+#: apps/lpasswd.c:165 apps/lpasswd.c:182
+#, c-format
+msgid "Error reading from file descriptor %d.\n"
+msgstr "エラー: ファイルディスクリプター %d から読み込めません。\n"
+
+#: apps/lpasswd.c:203 apps/luseradd.c:302 apps/luseradd.c:311
+#, c-format
+msgid "Error setting password for user %s: %s.\n"
+msgstr "ユーザー %s のパスワード設定に失敗: %s。\n"
+
+#: apps/lpasswd.c:212
+#, c-format
+msgid "Error setting password for group %s: %s.\n"
+msgstr "グループ %s のパスワード設定中にエラーが発生しました: %s 。\n"
+
+#: apps/lpasswd.c:224
+#, c-format
+msgid "Password changed.\n"
+msgstr "パスワード変更済み。\n"
+
+#: apps/luseradd.c:57
+msgid "create a system user"
+msgstr "システムユーザーを作成する"
+
+#: apps/luseradd.c:59
+msgid "GECOS information for new user"
+msgstr "新しいユーザーの GECOS 情報"
+
+#: apps/luseradd.c:61
+msgid "home directory for new user"
+msgstr "新しいユーザーのホームディレクトリー"
+
+#: apps/luseradd.c:63
+msgid "directory with files for the new user"
+msgstr "新しいユーザー向けファイルを持つディレクトリー"
+
+#: apps/luseradd.c:65
+msgid "shell for new user"
+msgstr "新しいユーザーのシェル"
+
+#: apps/luseradd.c:67
+msgid "uid for new user"
+msgstr "新しいユーザーの UID"
+
+#: apps/luseradd.c:69
+msgid "group for new user"
+msgstr "新しいユーザーのグループ"
+
+#: apps/luseradd.c:71
+msgid "don't create home directory for user"
+msgstr "ユーザーのホームディレクトリーを作成しない"
+
+#: apps/luseradd.c:73
+msgid "don't create group with same name as user"
+msgstr "ユーザーと同じ名前のグループを作成しない"
+
+#: apps/luseradd.c:79
+msgid "common name for new user"
+msgstr "新しいユーザーの一般名"
+
+#: apps/luseradd.c:81
+msgid "given name for new user"
+msgstr "新しいユーザーの名"
+
+#: apps/luseradd.c:83
+msgid "surname for new user"
+msgstr "新しいユーザーの姓"
+
+#: apps/luseradd.c:85
+msgid "room number for new user"
+msgstr "新しいユーザーの部屋番号"
+
+#: apps/luseradd.c:87
+msgid "telephone number for new user"
+msgstr "新しいユーザーの電話番号"
+
+#: apps/luseradd.c:89
+msgid "home telephone number for new user"
+msgstr "新しいユーザーの自宅電話番号"
+
+#: apps/luseradd.c:189
+#, c-format
+msgid "Group %jd does not exist\n"
+msgstr "グループ %jd は存在しません\n"
+
+#: apps/luseradd.c:207 apps/luseradd.c:220
+#, c-format
+msgid "Error creating group `%s': %s\n"
+msgstr "グループ `%s' の作成に失敗: %s\n"
+
+#: apps/luseradd.c:260
+#, c-format
+msgid "Account creation failed: %s.\n"
+msgstr "アカウントの作成に失敗しました: %s。\n"
+
+#: apps/luseradd.c:283
+#, c-format
+msgid "Error creating %s: %s.\n"
+msgstr "%s の作成に失敗: %s。\n"
+
+#: apps/luseradd.c:290
+#, c-format
+msgid "Error creating mail spool: %s\n"
+msgstr "メールスプールの作成中にエラーが発生しました: %s\n"
+
+#: apps/luserdel.c:47
+msgid "don't remove the user's private group, if the user has one"
+msgstr "ユーザーがプライベートグループを持っていても、それを削除しません。"
+
+#: apps/luserdel.c:50
+msgid "remove the user's home directory"
+msgstr "ユーザーのホームディレクトリーを削除する"
+
+#: apps/luserdel.c:94
+#, c-format
+msgid "User %s could not be deleted: %s.\n"
+msgstr "ユーザー %s は削除できませんでした: %s。\n"
+
+#: apps/luserdel.c:108
+#, c-format
+msgid "%s did not have a gid number.\n"
+msgstr "%s には GID 番号がありません。\n"
+
+#: apps/luserdel.c:114
+#, c-format
+msgid "No group with GID %jd exists, not removing.\n"
+msgstr "GID %jd のグループが存在しないため、削除しません。\n"
+
+#: apps/luserdel.c:120
+#, c-format
+msgid "Group with GID %jd did not have a group name.\n"
+msgstr "GID %jd のグループにはグループ名がありません。\n"
+
+#: apps/luserdel.c:126
+#, c-format
+msgid "Group %s could not be deleted: %s.\n"
+msgstr "グループ %s は削除できませんでした: %s。\n"
+
+#: apps/luserdel.c:139
+#, c-format
+msgid "Error removing home directory: %s.\n"
+msgstr "ホームディレクトリーの削除中にエラーが発生しました: %s\n"
+
+#: apps/luserdel.c:145
+#, c-format
+msgid "Error removing mail spool: %s"
+msgstr "メールスプールの削除中にエラーが発生しました: %s"
+
+#: apps/lusermod.c:58
+msgid "GECOS information"
+msgstr "GECOS の情報"
+
+#: apps/lusermod.c:60
+msgid "home directory"
+msgstr "ホームディレクトリー"
+
+#: apps/lusermod.c:62
+msgid "move home directory contents"
+msgstr "ホームディレクトリーの内容を移動する"
+
+#: apps/lusermod.c:64
+msgid "set shell for user"
+msgstr "ユーザーのシェルを設定する"
+
+#: apps/lusermod.c:66
+msgid "set UID for user"
+msgstr "ユーザーの UID を設定する"
+
+#: apps/lusermod.c:68
+msgid "set primary GID for user"
+msgstr "ユーザーのプライマリー GID を設定する"
+
+#: apps/lusermod.c:70
+msgid "change login name for user"
+msgstr "ユーザーのログイン名を変更する"
+
+#: apps/lusermod.c:72
+msgid "plaintext password for the user"
+msgstr "ユーザーの平文パスワード"
+
+#: apps/lusermod.c:74
+msgid "pre-hashed password for the user"
+msgstr "ユーザーのハッシュ済みパスワード"
+
+#: apps/lusermod.c:75
+msgid "lock account"
+msgstr "アカウントをロックする"
+
+#: apps/lusermod.c:78
+msgid "unlock account"
+msgstr "アカウントのロックを解除する"
+
+#: apps/lusermod.c:80
+msgid "set common name for user"
+msgstr "ユーザーの一般名を設定する"
+
+#: apps/lusermod.c:82
+msgid "set given name for user"
+msgstr "ユーザーの名を設定する"
+
+#: apps/lusermod.c:84
+msgid "set surname for user"
+msgstr "ユーザーの姓を設定する"
+
+#: apps/lusermod.c:86
+msgid "set room number for user"
+msgstr "ユーザーの部屋番号を設定する"
+
+#: apps/lusermod.c:88
+msgid "set telephone number for user"
+msgstr "ユーザーの電話番号を設定する"
+
+#: apps/lusermod.c:90
+msgid "set home telephone number for user"
+msgstr "ユーザーの自宅電話番号を設定する"
+
+#: apps/lusermod.c:180 apps/lusermod.c:193
+#, c-format
+msgid "Failed to set password for user %s: %s.\n"
+msgstr "ユーザーのパスワード設定に失敗 %s: %s。\n"
+
+#: apps/lusermod.c:203
+#, c-format
+msgid "User %s could not be locked: %s.\n"
+msgstr "ユーザー %s はロックできませんでした: %s。\n"
+
+#: apps/lusermod.c:211
+#, c-format
+msgid "User %s could not be unlocked: %s.\n"
+msgstr "ユーザー %s のロックを解除できませんでした: %s。\n"
+
+#: apps/lusermod.c:232
+#, c-format
+msgid "Warning: Group with ID %jd does not exist.\n"
+msgstr "警告: グループ ID %jd は存在しません。\n"
+
+#: apps/lusermod.c:275
+#, c-format
+msgid "User %s could not be modified: %s.\n"
+msgstr "ユーザー %s は編集できませんでした: %s\n"
+
+#: apps/lusermod.c:326
+#, c-format
+msgid "Group %s could not be modified: %s.\n"
+msgstr "グループ %s は修正できませんでした:%s\n"
+
+#: apps/lusermod.c:342
+#, c-format
+msgid "No old home directory for %s.\n"
+msgstr "%s には、古いホームディレクトリーがありません。\n"
+
+#: apps/lusermod.c:347
+#, c-format
+msgid "No new home directory for %s.\n"
+msgstr "%s には、新しいホームディレクトリーがありません。\n"
+
+#: apps/lusermod.c:353
+#, c-format
+msgid "Error moving %s to %s: %s.\n"
+msgstr "%s を %s に移動できませんでした: %s\n"
+"\n"
+
+#: lib/config.c:128
+#, c-format
+msgid "could not open configuration file `%s': %s"
+msgstr "設定ファイル `%s' を開けませんでした: %s"
+
+#: lib/config.c:134
+#, c-format
+msgid "could not stat configuration file `%s': %s"
+msgstr "設定ファイル `%s' を stat できませんでした: %s"
+
+#: lib/config.c:143
+#, c-format
+msgid "configuration file `%s' is too large"
+msgstr "設定ファイル `%s' が大きすぎます"
+
+#: lib/config.c:159
+#, c-format
+msgid "could not read configuration file `%s': %s"
+msgstr "設定ファイル `%s' を開けませんでした: %s"
+
+#: lib/error.c:62
+msgid "success"
+msgstr "成功"
+
+#: lib/error.c:64
+msgid "module disabled by configuration"
+msgstr "モジュールが設定で無効になっています。"
+
+#: lib/error.c:66
+msgid "generic error"
+msgstr "一般エラー"
+
+#: lib/error.c:68
+msgid "not enough privileges"
+msgstr "権限がありません"
+
+#: lib/error.c:70
+msgid "access denied"
+msgstr "アクセスが拒否されました"
+
+#: lib/error.c:72
+msgid "bad user/group name"
+msgstr "正しくないユーザー名/グループ名"
+
+#: lib/error.c:74
+msgid "bad user/group id"
+msgstr "正しくないユーザー ID/グループ ID"
+
+#: lib/error.c:76
+msgid "user/group name in use"
+msgstr "ユーザー名/グループ名は使われています"
+
+#: lib/error.c:78
+msgid "user/group id in use"
+msgstr "ユーザー ID/グループ ID は使われています"
+
+#: lib/error.c:80
+msgid "error manipulating terminal attributes"
+msgstr "端末属性の取得にエラーが発生しました"
+
+#: lib/error.c:82
+msgid "error opening file"
+msgstr "ファイルの読み込みに失敗"
+
+#: lib/error.c:84
+msgid "error locking file"
+msgstr "ファイルのロックに失敗"
+
+#: lib/error.c:86
+msgid "error statting file"
+msgstr "ファイルの stat 情報取得に失敗"
+
+#: lib/error.c:88
+msgid "error reading file"
+msgstr "ファイルの読み込み中にエラーが発生しました"
+
+#: lib/error.c:90
+msgid "error writing to file"
+msgstr "ファイルへの書き込み中にエラーが発生しました"
+
+#: lib/error.c:92
+msgid "data not found in file"
+msgstr "ファイルでデータが見つかりませんでした"
+
+#: lib/error.c:94
+msgid "internal initialization error"
+msgstr "内部の初期化に失敗"
+
+#: lib/error.c:96
+msgid "error loading module"
+msgstr "モジュールのロードに失敗"
+
+#: lib/error.c:98
+msgid "error resolving symbol in module"
+msgstr "モジュールのシンボル解決に失敗しました。"
+
+#: lib/error.c:100
+msgid "library/module version mismatch"
+msgstr "ライブラリー/モジュールのバージョン不一致"
+
+#: lib/error.c:102
+msgid "unlocking would make the password field empty"
+msgstr "ロックを解除するとパスワード領域は空になります"
+
+#: lib/error.c:105
+msgid "invalid attribute value"
+msgstr "無効な属性の値です"
+
+#: lib/error.c:107
+msgid "invalid module combination"
+msgstr "無効なモジュールの組み合わせです"
+
+#: lib/error.c:109
+msgid "user's home directory not owned by them"
+msgstr "所有されていないユーザーのホームディレクトリー"
+
+#: lib/error.c:115
+msgid "unknown error"
+msgstr "不明なエラーが発生しました"
+
+#: lib/misc.c:240
+msgid "invalid number"
+msgstr "無効な番号"
+
+#: lib/misc.c:254
+msgid "invalid ID"
+msgstr "無効な ID"
+
+#: lib/modules.c:61
+#, c-format
+msgid "no initialization function %s in `%s'"
+msgstr "`%s' の関数 %s で初期化できません"
+
+#: lib/modules.c:79
+#, c-format
+msgid "module version mismatch in `%s'"
+msgstr "`%s' のモジュールバージョンの不一致"
+
+#: lib/modules.c:92
+#, c-format
+msgid "module `%s' does not define `%s'"
+msgstr "モジュール `%s' が `%s' を定義していません"
+
+#: lib/prompt.c:88
+msgid "error reading terminal attributes"
+msgstr "端末属性の読み込み中にエラーが発生しました"
+
+#: lib/prompt.c:95 lib/prompt.c:107
+msgid "error setting terminal attributes"
+msgstr "端末属性の設定中にエラーが発生しました"
+
+#: lib/prompt.c:101
+msgid "error reading from terminal"
+msgstr "端末から読み込み中にエラーが発生しました"
+
+#: lib/user.c:218
+msgid "name is not set"
+msgstr "名前が設定されていません"
+
+#: lib/user.c:223
+msgid "name is too short"
+msgstr "名前が短すぎます"
+
+#: lib/user.c:228
+#, c-format
+msgid "name is too long (%zu > %d)"
+msgstr "名前が長すぎます (%zu > %d)"
+
+#: lib/user.c:235
+msgid "name contains non-ASCII characters"
+msgstr "名前に ASCII 以外の文字があります"
+
+#: lib/user.c:242
+msgid "name contains control characters"
+msgstr "名前が制御文字を含んでいます"
+
+#: lib/user.c:249
+msgid "name contains whitespace"
+msgstr "名前に空白があります"
+
+#: lib/user.c:261
+msgid "name starts with a hyphen"
+msgstr "名前がハイフンから始まっています"
+
+#: lib/user.c:272
+#, c-format
+msgid "name contains invalid char `%c'"
+msgstr "名前に無効な文字 `%c' があります"
+
+#: lib/user.c:308 lib/user.c:360
+#, c-format
+msgid "user %s has no UID"
+msgstr "ユーザー %s には UID がありません。"
+
+#: lib/user.c:310
+#, c-format
+msgid "user %s not found"
+msgstr "ユーザー %s が見つかりませんでした"
+
+#: lib/user.c:333 lib/user.c:361
+#, c-format
+msgid "group %s has no GID"
+msgstr "グループ %s には GID がありません。"
+
+#: lib/user.c:335
+#, c-format
+msgid "group %s not found"
+msgstr "グループ %s が見つかりませんでした"
+
+#: lib/user.c:355
+#, c-format
+msgid "user %jd has no name"
+msgstr "ユーザー %jd には名前がありません。"
+
+#: lib/user.c:356
+#, c-format
+msgid "group %jd has no name"
+msgstr "グループ %jd には名前がありません。"
+
+#: lib/user.c:364
+msgid "user has neither a name nor an UID"
+msgstr "ユーザーには、名前もしくは UID がありません。"
+
+#: lib/user.c:365
+msgid "group has neither a name nor a GID"
+msgstr "グループには、名前もしくは GID がありません。"
+
+#: lib/user.c:1311
+#, c-format
+msgid "Refusing to use dangerous home directory `%s' by default"
+msgstr "デフォルトで危険なホームディレクトリ `%s' の使用を拒否中です"
+
+#: lib/user.c:2310
+#, c-format
+msgid "Invalid default value of field %s: %s"
+msgstr "領域 %s の値は無効なデフォルト値です: %s"
+
+#: lib/util.c:300 modules/files.c:374
+#, c-format
+msgid "error locking file: %s"
+msgstr "ファイルのロック中にエラーが発生しました: %s"
+
+#: lib/util.c:706
+#, c-format
+msgid "couldn't get default security context: %s"
+msgstr "デフォルトのセキュリティーコンテキストを取得できません: %s"
+
+#: lib/util.c:733 lib/util.c:759 lib/util.c:785
+#, c-format
+msgid "couldn't get security context of `%s': %s"
+msgstr "`%s' のセキュリティーコンテキストを取得できません: %s"
+
+#: lib/util.c:739 lib/util.c:765 lib/util.c:791 lib/util.c:823
+#, c-format
+msgid "couldn't set default security context to `%s': %s"
+msgstr "`%s' にデフォルトのセキュリティーコンテキストを設定できません: %s"
+
+#: lib/util.c:815
+#, c-format
+msgid "couldn't determine security context for `%s': %s"
+msgstr "`%s' のセキュリティーコンテキストを決定できません: %s"
+
+#: modules/files.c:129 modules/files.c:692 modules/files.c:1585
+#: modules/files.c:1920 modules/files.c:1930 modules/files.c:2012
+#: modules/files.c:2023 modules/files.c:2089 modules/files.c:2101
+#: modules/files.c:2191 modules/files.c:2200 modules/files.c:2255
+#: modules/files.c:2264 modules/files.c:2359 modules/files.c:2368
+#, c-format
+msgid "couldn't open `%s': %s"
+msgstr "`%s' を開けません: %s"
+
+#: modules/files.c:137 modules/files.c:994 modules/files.c:1187
+#: modules/files.c:1329
+#, c-format
+msgid "couldn't stat `%s': %s"
+msgstr "`%s' の stat 情報を取得できません: %s"
+
+#: modules/files.c:161
+#, c-format
+msgid "error creating `%s': %s"
+msgstr "`%s' の作成中にエラーが発生しました: %s"
+
+#: modules/files.c:169
+#, c-format
+msgid "Error changing owner of `%s': %s"
+msgstr "`%s' の所有者変更に失敗: %s"
+
+#: modules/files.c:175
+#, c-format
+msgid "Error changing mode of `%s': %s"
+msgstr "エラー: `%s' のモードを変更できません: %s "
+
+#: modules/files.c:191
+#, c-format
+msgid "Error reading `%s': %s"
+msgstr "`%s'の読み込みに失敗: %s"
+
+#: modules/files.c:206 modules/files.c:217 modules/files.c:305
+#: modules/files.c:467
+#, c-format
+msgid "Error writing `%s': %s"
+msgstr "`%s'の書き込みに失敗: %s"
+
+#: modules/files.c:247 modules/files.c:1005 modules/files.c:1195
+#: modules/files.c:1338
+#, c-format
+msgid "couldn't read from `%s': %s"
+msgstr "`%s' から読み込めません: %s"
+
+#: modules/files.c:256
+#, c-format
+msgid "Invalid contents of lock `%s'"
+msgstr "ロック `%s' の内容が無効です。"
+
+#: modules/files.c:261
+#, c-format
+msgid "The lock %s is held by process %ju"
+msgstr "ロック %s は、プロセス %ju に保持されています。"
+
+#: modules/files.c:269
+#, c-format
+msgid "Error removing stale lock `%s': %s"
+msgstr "古いロック `%s' を削除する際にエラーが発生しました: %s"
+
+#: modules/files.c:297
+#, c-format
+msgid "error opening temporary file for `%s': %s"
+msgstr "`%s' の一時ファイルを開く際にエラーが発生しました: %s"
+
+#: modules/files.c:321
+#, c-format
+msgid "Cannot obtain lock `%s': %s"
+msgstr "ロック `%s' を取得できません: %s"
+
+#: modules/files.c:434
+#, c-format
+msgid "Error resolving `%s': %s"
+msgstr "`%s' を解決する際にエラーが発生しました: %s"
+
+#: modules/files.c:442
+#, c-format
+msgid "Error replacing `%s': %s"
+msgstr "`%s' を置き換える際にエラーが発生しました: %s"
+
+#: modules/files.c:903
+#, c-format
+msgid "%s value `%s': `\\n' not allowed"
+msgstr "%s 値 `%s': `\\n' は許可されていません"
+
+#: modules/files.c:910
+#, c-format
+msgid "%s value `%s': `:' not allowed"
+msgstr "%s 値 `%s': `:' は許可されていません"
+
+#: modules/files.c:1014
+msgid "entry already present in file"
+msgstr "エントリーは、ファイルに存在します"
+
+#: modules/files.c:1021 modules/files.c:1031 modules/files.c:1041
+#: modules/files.c:1393 modules/files.c:1401 modules/files.c:1409
+#, c-format
+msgid "couldn't write to `%s': %s"
+msgstr "`%s' に書き込めません: %s"
+
+#: modules/files.c:1173
+#, c-format
+msgid "entity object has no %s attribute"
+msgstr "エンティティーオブジェクトに %s 属性がありません"
+
+#: modules/files.c:1215
+msgid "entry with conflicting name already present in file"
+msgstr "競合する名前のエントリーは、ファイルに存在します"
+
+#: modules/files.c:1803
+msgid "`:' and `\\n' not allowed in encrypted password"
+msgstr "`:' および `\\n' は、暗号化パスワードでは許可されていません"
+
+#: modules/files.c:1815 modules/ldap.c:1543 modules/ldap.c:1812
+msgid "error encrypting password"
+msgstr "パスワードの暗号化中にエラーが発生しました"
+
+#: modules/files.c:2517 modules/ldap.c:2410
+#, c-format
+msgid "the `%s' and `%s' modules can not be combined"
+msgstr "`%s' と `%s' のモジュールは、組み合わせることができません。"
+
+#: modules/files.c:2601 modules/files.c:2679
+msgid "not executing with superuser privileges"
+msgstr "スーパーユーザー特権で実行できません"
+
+#: modules/files.c:2692
+msgid "no shadow file present -- disabling"
+msgstr "shadow ファイルはありません。無効になっています"
+
+#: modules/krb5.c:100
+#, c-format
+msgid ""
+"error connecting to the kadm5 server for service `%s' in realm `%s': %s"
+msgstr "レルム `%s' のサービス `%s' で、kadm5 サーバーに接続できません: %s"
+
+#: modules/krb5.c:132 modules/krb5.c:198 modules/krb5.c:297 modules/krb5.c:385
+#: modules/krb5.c:437 modules/krb5.c:525 modules/krb5.c:591
+msgid "error initializing kerberos library"
+msgstr "kerberos ライブラリーの初期化でエラーが発生しました"
+
+#: modules/krb5.c:139 modules/krb5.c:219 modules/krb5.c:329 modules/krb5.c:337
+#: modules/krb5.c:405 modules/krb5.c:458 modules/krb5.c:546 modules/krb5.c:608
+#, c-format
+msgid "error parsing user name `%s' for kerberos"
+msgstr "kerberos のユーザー名 `%s' で、構文解析エラーが発生しました"
+
+#: modules/krb5.c:209 modules/krb5.c:396 modules/krb5.c:448 modules/krb5.c:536
+#, c-format
+msgid "entity structure has no %s or %s attributes"
+msgstr "エンティティー構造体には、%s 属性および %s 属性がありません。"
+
+#: modules/krb5.c:307
+#, c-format
+msgid "entity has no %s or %s attributes"
+msgstr "エンティティーには、%s 属性および %s 属性がありません。"
+
+#: modules/krb5.c:320
+#, c-format
+msgid "entity was created with no %s or %s attributes"
+msgstr "エンティティーは、%s 属性や %s 属性を含まずに作成されました"
+
+#: modules/krb5.c:471 modules/krb5.c:559
+#, c-format
+msgid "error reading information for `%s' from kerberos"
+msgstr "kerberos から `%s' の情報を読み込んでいる時に、エラーが発生しました"
+
+#: modules/krb5.c:600
+#, c-format
+msgid "entity has no %s attribute"
+msgstr "エンティティーには、 %s 属性がありません"
+
+#: modules/krb5.c:638
+#, c-format
+msgid "error setting password for `%s'"
+msgstr "`%s' のパスワード設定中にエラーが発生しました"
+
+#: modules/krb5.c:764
+msgid "Kerberos Realm"
+msgstr "kerberos レルム"
+
+#: modules/krb5.c:771
+msgid "Kerberos Admin Principal"
+msgstr "kerberos 管理プリンシパル"
+
+#: modules/krb5.c:793
+msgid "Kerberos Password for Admin Principal"
+msgstr "管理プリンシパルの kerberos パスワード"
+
+#: modules/ldap.c:199
+msgid "error initializing ldap library"
+msgstr "LDAP ライブラリーの初期化時にエラー"
+
+#: modules/ldap.c:210
+#, c-format
+msgid "could not set LDAP protocol to version %d"
+msgstr "LDAP プロトコルをバージョン %d に設定できませんでした"
+
+#: modules/ldap.c:229
+msgid "could not negotiate TLS with LDAP server"
+msgstr "LDAP サーバーと TLS ネゴシエートできませんでした"
+
+#: modules/ldap.c:424
+msgid "could not bind to LDAP server"
+msgstr "LDAP サーバーとバインドできませんでした"
+
+#: modules/ldap.c:427
+#, c-format
+msgid "could not bind to LDAP server, first attempt as `%s': %s"
+msgstr "LDAP サーバーとバインドできませんでした。最初に `%s' として試みます: %s"
+
+#: modules/ldap.c:1315
+#, c-format
+msgid "user object had no %s attribute"
+msgstr "ユーザーオブジェクトには、%s 属性がありません"
+
+#: modules/ldap.c:1324
+#, c-format
+msgid "user object was created with no `%s'"
+msgstr "ユーザーオブジェクトは、`%s' を含まずに生成されました"
+
+#: modules/ldap.c:1344
+#, c-format
+msgid "error creating a LDAP directory entry: %s"
+msgstr "LDAP ディレクトリーエントリーの作成時にエラーが発生しました: %s"
+
+#: modules/ldap.c:1370 modules/ldap.c:1604
+#, c-format
+msgid "error modifying LDAP directory entry: %s"
+msgstr "LDAP ディレクトリーエントリーの変更時にエラーが発生しました: %s"
+
+#: modules/ldap.c:1395
+#, c-format
+msgid "error renaming LDAP directory entry: %s"
+msgstr "LDAP ディレクトリーエントリーの名前変更でエラー: %s"
+
+#: modules/ldap.c:1440
+#, c-format
+msgid "object had no %s attribute"
+msgstr "オブジェクトには、%s 属性がありません"
+
+#: modules/ldap.c:1456
+#, c-format
+msgid "error removing LDAP directory entry: %s"
+msgstr "LDAP ディレクトリーエントリーの削除時にエラー: %s"
+
+#: modules/ldap.c:1506 modules/ldap.c:1521 modules/ldap.c:1635
+#: modules/ldap.c:1730
+#, c-format
+msgid "object has no %s attribute"
+msgstr "オブジェクトには、%s 属性がありません"
+
+#: modules/ldap.c:1533
+msgid "unsupported password encryption scheme"
+msgstr "サポートされていないパスワード暗号化スキームです"
+
+#: modules/ldap.c:1658
+msgid "no such object in LDAP directory"
+msgstr "LDAP ディレクトリーには、そのようなオブジェクトがありません"
+
+#: modules/ldap.c:1670
+#, c-format
+msgid "no `%s' attribute found"
+msgstr "`%s' 属性は見つかりませんでした"
+
+#: modules/ldap.c:1843
+#, c-format
+msgid "error setting password in LDAP directory for %s: %s"
+msgstr "%s の LDAP ディレクトリーのパスワード設定でエラー: %s"
+
+#: modules/ldap.c:2446
+msgid "LDAP Server Name"
+msgstr "LDAP サーバー名"
+
+#: modules/ldap.c:2452
+msgid "LDAP Search Base DN"
+msgstr "LDAP 検索ベース DN"
+
+#: modules/ldap.c:2458
+msgid "LDAP Bind DN"
+msgstr "LDAP バインド DN"
+
+#: modules/ldap.c:2465
+msgid "LDAP Bind Password"
+msgstr "LDAP バインドパスワード"
+
+#: modules/ldap.c:2471
+msgid "LDAP SASL User"
+msgstr "LDAP SASL ユーザー"
+
+#: modules/ldap.c:2478
+msgid "LDAP SASL Authorization User"
+msgstr "LDAP SASL 認証ユーザー"
+
+#: modules/sasldb.c:132
+#, c-format
+msgid "Cyrus SASL error creating user: %s"
+msgstr "ユーザーの作成時に Cyrus SASL エラー: %s"
+
+#: modules/sasldb.c:136
+#, c-format
+msgid "Cyrus SASL error removing user: %s"
+msgstr "ユーザーの削除時に Cyrus SASL エラー: %s"
+
+#: modules/sasldb.c:503 modules/sasldb.c:511
+#, c-format
+msgid "error initializing Cyrus SASL: %s"
+msgstr "Cyrus SASL の初期化に失敗: %s"
+
+#: python/admin.c:518
+msgid "error creating home directory for user"
+msgstr "ユーザー用のホームディレクトリー作成に失敗しました"
+
+#: python/admin.c:557 python/admin.c:596
+msgid "error removing home directory for user"
+msgstr "ユーザーのホームディレクトリー削除に失敗しました"
+
+#: python/admin.c:667
+msgid "error moving home directory for user"
+msgstr "ユーザーのホームディレクトリー移動に失敗しました"
+
+#: samples/lookup.c:63
+#, c-format
+msgid "Error initializing %s: %s\n"
+msgstr "%s の初期化に失敗: %s\n"
+
+#: samples/lookup.c:76
+#, c-format
+msgid "Invalid ID %s\n"
+msgstr "無効な ID %s\n"
+
+#: samples/lookup.c:88
+#, c-format
+msgid "Searching for group with ID %jd.\n"
+msgstr "ID %jd のグループを検索中。\n"
+
+#: samples/lookup.c:92
+#, c-format
+msgid "Searching for group named %s.\n"
+msgstr "名前が %s のグループを検索中。\n"
+
+#: samples/lookup.c:99
+#, c-format
+msgid "Searching for user with ID %jd.\n"
+msgstr "ID %jd のユーザーを検索中。\n"
+
+#: samples/lookup.c:103
+#, c-format
+msgid "Searching for user named %s.\n"
+msgstr "名前が %s のユーザーを検索中。\n"
+
+#: samples/lookup.c:117
+msgid "Entry not found.\n"
+msgstr "エントリーは見つかりませんでした。\n"
+
+#: samples/prompt.c:48
+msgid "Prompts succeeded.\n"
+msgstr "指示成功。\n"
+
+#: samples/prompt.c:58
+msgid "Prompts failed.\n"
+msgstr "指示失敗。\n"
+
+#: samples/testuser.c:76
+msgid "Default user object classes:\n"
+msgstr "デフォルトユーザーオブジェクトクラス:\n"
+
+#: samples/testuser.c:82
+msgid "Default user attribute names:\n"
+msgstr "デフォルトユーザー属性名:\n"
+
+#: samples/testuser.c:88
+msgid "Getting default user attributes:\n"
+msgstr "デフォルトユーザー属性を取得中:\n"
+
+#: samples/testuser.c:95
+msgid "Copying user structure:\n"
+msgstr "ユーザー構造体をコピー中:\n"
+
diff --git a/SOURCES/libuser-CVE-2015-3246.patch b/SOURCES/libuser-CVE-2015-3246.patch
new file mode 100644
index 0000000..ca58b47
--- /dev/null
+++ b/SOURCES/libuser-CVE-2015-3246.patch
@@ -0,0 +1,1530 @@
+2015-06-26  Miloslav Trmač  <mitr@redhat.com>
+
+        * modules/files.c (open_and_copy_file): Replace and heavily modify  ...
+        (lu_files_create_backup): ... this.
+        (lock_file_handle_existing, lock_file_create, lock_file_remove)
+        (struct editing, editing_open, replace_file_or_symlink)
+        (editing_close): New functions.
+        (generic_lookup, generic_is_locked, lu_files_enumerate)
+        (lu_files_users_enumerate_by_group, lu_files_groups_enumerate_by_user)
+        (lu_files_enumerate_full): Remove locking on read-only operations.
+        (generic_add, generic_mod, generic_del, generic_lock)
+        (generic_setpass): Use struct editing instead of dealing with locking,
+        backups, SELinux individually.
+
+        * lib/user_private.h (lu_util_lock_obtain, lu_util_lock_free): Mark
+        as deprecated.
+
+        * lib/util.c (lu_util_field_write): Fail on an incomplete write().
+
+2015-06-25  Miloslav Trmač  <mitr@redhat.com>
+
+        * modules/files.c (format_generic, generic_setpass): Refuse to write
+        field values which contain \n.
+        * tests/files_test.py (Tests.testUserAdd9, Tests.testUserMod8)
+        (tests.testUserSetpass5, tests.testGroupAdd6, tests.testGroupMod7)
+        (tests.testGroupSetpass4): New tests.
+
+diff -up libuser-0.60/lib/user_private.h.CVE-2015-3246 libuser-0.60/lib/user_private.h
+--- libuser-0.60/lib/user_private.h.CVE-2015-3246	2013-10-12 23:56:07.000000000 +0200
++++ libuser-0.60/lib/user_private.h	2015-07-08 15:15:14.060544103 +0200
+@@ -330,9 +330,11 @@ typedef char lu_security_context_t; /* "
+   ((void)(PATH), (void)(MODE), (void)(ERROR), TRUE)
+ #endif
+ 
+-/* Lock a file. */
++#ifndef LU_DISABLE_DEPRECATED
++/* Lock a file. Deprecated. */
+ gpointer lu_util_lock_obtain(int fd, struct lu_error **error);
+ void lu_util_lock_free(gpointer lock);
++#endif
+ 
+ /* Manipulate a colon-delimited flat text file. */
+ char *lu_util_line_get_matching1(int fd, const char *firstpart,
+diff -up libuser-0.60/lib/util.c.CVE-2015-3246 libuser-0.60/lib/util.c
+--- libuser-0.60/lib/util.c.CVE-2015-3246	2013-10-12 23:56:07.000000000 +0200
++++ libuser-0.60/lib/util.c	2015-07-08 15:15:14.060544103 +0200
+@@ -632,7 +632,7 @@ lu_util_field_write(int fd, const char *
+ 		goto err;
+ 	}
+ 	len = strlen(buf);
+-	if (write(fd, buf, len) == -1) {
++	if (write(fd, buf, len) != len) {
+ 		lu_error_new(error, lu_error_write, NULL);
+ 		ret = FALSE;
+ 		goto err;
+diff -up libuser-0.60/modules/files.c.CVE-2015-3246 libuser-0.60/modules/files.c
+--- libuser-0.60/modules/files.c.CVE-2015-3246	2013-10-12 23:56:07.000000000 +0200
++++ libuser-0.60/modules/files.c	2015-07-08 15:16:41.014981429 +0200
+@@ -25,6 +25,7 @@
+ #include <fcntl.h>
+ #include <fnmatch.h>
+ #include <limits.h>
++#include <shadow.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -101,82 +102,79 @@ module_filename(struct lu_module *module
+ 	return g_strconcat(dir, file_suffix, NULL);
+ }
+ 
+-/* Create a backup copy of "filename" named "filename-". */
+-static gboolean
+-lu_files_create_backup(const char *filename,
+-		       struct lu_error **error)
++/* Copy contents of INPUT_FILENAME to OUTPUT_FILENAME, exclusively creating it
++ * if EXCLUSIVE.
++ * Return the file descriptor for OUTPUT_FILENAME, open for reading and writing,
++ * or -1 on error.
++ * Note that this does no locking and assumes the directories hosting the files
++ * are not being manipulated by an attacker. */
++static int
++open_and_copy_file(const char *input_filename, const char *output_filename,
++		   gboolean exclusive, struct lu_error **error)
+ {
+ 	int ifd, ofd;
+-	gpointer ilock, olock;
+-	char *backupname;
+-	struct stat ist, ost;
+-	off_t offset;
+-	gboolean res = FALSE;
++	struct stat st;
++	int res = -1;
++	int flags;
+ 
+-	g_assert(filename != NULL);
+-	g_assert(strlen(filename) > 0);
++	g_assert(input_filename != NULL);
++	g_assert(strlen(input_filename) > 0);
++	g_assert(output_filename != NULL);
++	g_assert(strlen(output_filename) > 0);
+ 
+-	/* Open the original file. */
+-	ifd = open(filename, O_RDONLY);
++	/* Open the input file. */
++	ifd = open(input_filename, O_RDONLY);
+ 	if (ifd == -1) {
+ 		lu_error_new(error, lu_error_open,
+-			     _("couldn't open `%s': %s"), filename,
++			     _("couldn't open `%s': %s"), input_filename,
+ 			     strerror(errno));
+ 		goto err;
+ 	}
+ 
+-	/* Lock the input file. */
+-	if ((ilock = lu_util_lock_obtain(ifd, error)) == NULL)
+-		goto err_ifd;
+-
+ 	/* Read the input file's size. */
+-	if (fstat(ifd, &ist) == -1) {
++	if (fstat(ifd, &st) == -1) {
+ 		lu_error_new(error, lu_error_stat,
+-			     _("couldn't stat `%s': %s"), filename,
++			     _("couldn't stat `%s': %s"), input_filename,
+ 			     strerror(errno));
+-		goto err_ilock;
++		goto err_ifd;
+ 	}
+ 
+-	/* Generate the backup file's name and open it, creating it if it
+-	 * doesn't already exist. */
+-	backupname = g_strconcat(filename, "-", NULL);
+-	ofd = open(backupname, O_WRONLY | O_CREAT, ist.st_mode);
++	/* We only need O_WRONLY, but the caller needs RDWR if ofd will be
++	 * used as e->new_fd. */
++	flags = O_RDWR | O_CREAT;
++	if (exclusive) {
++		/* This ensures that if there is a concurrent writer which is
++		 * not doing locking for some reason, we will not truncate their
++		 * temporary file. Still, the other writer may truncate our
++		 * file, and ultimately the rename() committing the changes will
++		 * lose one or the other set of changes. */
++		(void)unlink(output_filename);
++		flags |= O_EXCL;
++	} else
++		flags |= O_TRUNC;
++	/* Start with absolutely restrictive permissions to make sure nobody
++	 * can get a file descriptor for this file until we are done resetting
++	 * ownership. */
++	ofd = open(output_filename, flags, 0);
+ 	if (ofd == -1) {
+ 		lu_error_new(error, lu_error_open,
+-			     _("error creating `%s': %s"), backupname,
++			     _("error creating `%s': %s"), output_filename,
+ 			     strerror(errno));
+-		goto err_backupname;
+-	}
+-
+-	/* If we can't read its type, or it's not a normal file, bail. */
+-	if (fstat(ofd, &ost) == -1) {
+-		lu_error_new(error, lu_error_stat, _("couldn't stat `%s': %s"),
+-			     backupname, strerror(errno));
+-		goto err_ofd;
+-	}
+-	if (!S_ISREG(ost.st_mode)) {
+-		lu_error_new(error, lu_error_open,
+-			     _("backup file `%s' exists and is not a regular file"),
+-			     backupname);
+-		goto err_ofd;
++		goto err_ifd;
+ 	}
+ 
+-	/* Now lock the output file. */
+-	if ((olock = lu_util_lock_obtain(ofd, error)) == NULL)
+-		goto err_ofd;
+-
+ 	/* Set the permissions on the new file to match the old one. */
+-	if (fchown(ofd, ist.st_uid, ist.st_gid) == -1 && errno != EPERM) {
++	if (fchown(ofd, st.st_uid, st.st_gid) == -1 && errno != EPERM) {
+ 		lu_error_new(error, lu_error_generic,
+-			     _("Error changing owner of `%s': %s"), backupname,
+-			     strerror(errno));
+-		goto err_olock;
++			     _("Error changing owner of `%s': %s"),
++			     output_filename, strerror(errno));
++		goto err_ofd;
+ 	}
+-	if (fchmod(ofd, ist.st_mode) == -1) {
++	if (fchmod(ofd, st.st_mode) == -1) {
+ 		lu_error_new(error, lu_error_generic,
+-			     _("Error changing mode of `%s': %s"), backupname,
+-			     strerror(errno));
+-		goto err_olock;
++			     _("Error changing mode of `%s': %s"),
++			     output_filename, strerror(errno));
++		goto err_ofd;
+ 	}
+ 
+ 	/* Copy the data, block by block. */
+@@ -190,9 +188,9 @@ lu_files_create_backup(const char *filen
+ 			if (errno == EINTR)
+ 				continue;
+ 			lu_error_new(error, lu_error_read,
+-				     _("Error reading `%s': %s"), filename,
+-				     strerror(errno));
+-			goto err_olock;
++				     _("Error reading `%s': %s"),
++				     input_filename, strerror(errno));
++			goto err_ofd;
+ 		}
+ 		if (left == 0)
+ 			break;
+@@ -206,55 +204,297 @@ lu_files_create_backup(const char *filen
+ 					continue;
+ 				lu_error_new(error, lu_error_write,
+ 					     _("Error writing `%s': %s"),
+-					     backupname, strerror(errno));
+-				goto err_olock;
++					     output_filename, strerror(errno));
++				goto err_ofd;
+ 			}
+ 			p += out;
+ 			left -= out;
+ 		}
+ 	}
+ 
+-	/* Flush data to disk, and truncate at the current offset.  This is
+-	 * necessary if the file existed before we opened it. */
+-	fsync(ofd);
+-	offset = lseek(ofd, 0, SEEK_CUR);
+-	if (offset == -1 || ftruncate(ofd, offset) == -1) {
+-		lu_error_new(error, lu_error_generic,
+-			     _("Error writing `%s': %s"), backupname,
+-			     strerror(errno));
+-		goto err_olock;
+-	}
+-
+-	/* Re-read data about the output file. */
+-	if (fstat(ofd, &ost) == -1) {
+-		lu_error_new(error, lu_error_stat,
+-			     _("couldn't stat `%s': %s"), backupname,
+-			     strerror(errno));
+-		goto err_olock;
+-	}
+-
+-	/* Complain if the files are somehow not the same. */
+-	if (ist.st_size != ost.st_size) {
+-		lu_error_new(error, lu_error_generic,
+-			     _("backup file size mismatch"));
+-		goto err_olock;
++	/* Flush data to disk. */
++	if (fsync(ofd) != 0 || lseek(ofd, 0, SEEK_SET) == -1) {
++		lu_error_new(error, lu_error_write, _("Error writing `%s': %s"),
++			     output_filename, strerror(errno));
++		goto err_ofd;
+ 	}
+-	res = TRUE;
++	res = ofd;
++	goto err_ifd; /* Do not close ofd */
+ 
+- err_olock:
+-	lu_util_lock_free(olock);
+  err_ofd:
+ 	close(ofd);
+- err_backupname:
+-	g_free(backupname);
+- err_ilock:
+-	lu_util_lock_free(ilock);
+  err_ifd:
+ 	close(ifd);
+  err:
+ 	return res;
+ }
+ 
++/* Deal with an existing LOCK_FILENAME.
++ * Return TRUE if the caller should try again. */
++static gboolean
++lock_file_handle_existing(const char *lock_filename, struct lu_error **error)
++{
++	gchar *lock_contents;
++	GError *gerror;
++	gboolean ret = FALSE;
++	uintmax_t pid;
++	char *p;
++
++	gerror = NULL;
++	if (g_file_get_contents(lock_filename, &lock_contents, NULL, &gerror)
++	    == FALSE) {
++		lu_error_new(error, lu_error_read,
++			     _("couldn't read from `%s': %s"), lock_filename,
++			     gerror->message);
++		g_error_free(gerror);
++		goto err;
++	}
++	errno = 0;
++	pid = strtoumax(lock_contents, &p, 10);
++	if (errno != 0 || *p != 0 || p == lock_contents || (pid_t)pid != pid) {
++		lu_error_new(error, lu_error_lock,
++			     _("Invalid contents of lock `%s'"), lock_filename);
++		goto err_lock_contents;
++	}
++	if (kill(pid, 0) == 0 || errno != ESRCH) {
++		lu_error_new(error, lu_error_lock,
++			     _("The lock %s is held by process %ju"),
++			     lock_filename, pid);
++		goto err_lock_contents;
++	}
++	/* This is unfixably racy, but that should matter only if a genuine
++	 * lock owner crashes. */
++	if (unlink(lock_filename) != 0) {
++		lu_error_new(error, lu_error_lock,
++		     _("Error removing stale lock `%s': %s"), lock_filename,
++		     strerror(errno));
++		goto err_lock_contents;
++	}
++	ret = TRUE;
++	/* Fall through */
++
++err_lock_contents:
++	g_free(lock_contents);
++err:
++	return ret;
++}
++
++/* Create a lock file for FILENAME. */
++static gboolean
++lock_file_create(const char *filename, struct lu_error **error)
++{
++	char *lock_filename, *tmp_filename;
++	char pid_string[sizeof (pid_t) * CHAR_BIT + 1];
++	int fd;
++	gboolean ret = FALSE;
++
++	lock_filename = g_strconcat(filename, ".lock", NULL);
++	tmp_filename = g_strdup_printf("%s.lock.XXXXXX", filename);
++
++	fd = mkstemp(tmp_filename);
++	if (fd == -1) {
++		lu_error_new(error, lu_error_open,
++			     _("error opening temporary file for `%s': %s"),
++			     lock_filename, strerror(errno));
++		goto err_tmp_filename;
++	}
++	if (snprintf(pid_string, sizeof(pid_string), "%ju", (uintmax_t)getpid())
++	    >= sizeof(pid_string))
++		g_assert_not_reached();
++	if (write(fd, pid_string, strlen(pid_string)) != strlen(pid_string)) {
++		lu_error_new(error, lu_error_write, _("Error writing `%s': %s"),
++			     tmp_filename, strerror(errno));
++		close(fd);
++		goto err_tmp_file;
++	}
++	close(fd);
++
++	if (link(tmp_filename, lock_filename) != 0) {
++		if (errno == EEXIST) {
++			if (lock_file_handle_existing(lock_filename, error)
++			    == FALSE)
++				goto err_tmp_file;
++			if (link(tmp_filename, lock_filename) == 0)
++				goto got_link;
++		}
++		lu_error_new(error, lu_error_lock,
++			     _("Cannot obtain lock `%s': %s"), lock_filename,
++			     strerror(errno));
++		goto err_tmp_file;
++	}
++got_link:
++	ret = TRUE;
++	/* Fall through */
++
++err_tmp_file:
++	(void)unlink(tmp_filename);
++err_tmp_filename:
++	g_free(tmp_filename);
++	g_free(lock_filename);
++	return ret;
++}
++
++/* Remove the lock file for FILENAME. */
++static void
++lock_file_remove(const char *filename)
++{
++	char *lock_file;
++
++	lock_file = g_strconcat(filename, ".lock", NULL);
++	(void)unlink(lock_file);
++	g_free(lock_file);
++}
++
++/* State related to a file currently open for editing. */
++struct editing {
++	char *filename;
++	lu_security_context_t fscreate;
++	char *new_filename;
++	int new_fd;
++};
++
++/* Open and lock FILE_SUFFIX in MODULE for editing.
++ * Return editing state, or NULL on error. */
++static struct editing *
++editing_open(struct lu_module *module, const char *file_suffix,
++	     struct lu_error **error)
++{
++	struct editing *e;
++	char *backup_name;
++	int fd;
++
++	e = g_malloc0(sizeof (*e));
++	e->filename = module_filename(module, file_suffix);
++	/* Make sure this all works if e->filename is a symbolic link, at least
++	 * as long as it points to the same file system. */
++
++	if (geteuid() == 0) {
++		if (lckpwdf() != 0) {
++			lu_error_new(error, lu_error_lock,
++				     _("error locking file: %s"),
++				     strerror(errno));
++			goto err_filename;
++		}
++	}
++	if (lock_file_create(e->filename, error) == FALSE)
++		goto err_lckpwdf;
++
++	if (!lu_util_fscreate_save(&e->fscreate, error))
++		goto err_locked;
++	if (!lu_util_fscreate_from_file(e->filename, error))
++		goto err_fscreate;
++
++	backup_name = g_strconcat(e->filename, "-", NULL);
++	fd = open_and_copy_file(e->filename, backup_name, FALSE, error);
++	g_free (backup_name);
++	close(fd);
++	if (fd == -1)
++		goto err_fscreate;
++
++	e->new_filename = g_strconcat(e->filename, "+", NULL);
++	e->new_fd = open_and_copy_file(e->filename, e->new_filename, TRUE,
++			       	       error);
++	if (e->new_fd == -1)
++		goto err_new_filename;
++
++	return e;
++
++err_new_filename:
++ 	g_free(e->new_filename);
++err_fscreate:
++	lu_util_fscreate_restore(e->fscreate);
++
++err_locked:
++	(void)lock_file_remove(e->filename);
++err_lckpwdf:
++	if (geteuid() == 0)
++		(void)ulckpwdf();
++
++err_filename:
++ 	g_free(e->filename);
++ 	g_free(e);
++ 	return NULL;
++}
++
++
++/* Replace DESTINATION with SOURCE, even if DESTINATION is a symbolic link. */
++static gboolean
++replace_file_or_symlink(const char *source, const char *destination,
++		        struct lu_error **error)
++{
++	struct stat st;
++	char *tmp;
++	gboolean ret = FALSE;
++
++	tmp = NULL;
++	if (lstat(destination, &st) == 0 && S_ISLNK(st.st_mode)) {
++		tmp = realpath(destination, NULL);
++		if (tmp == NULL) {
++			lu_error_new(error, lu_error_generic,
++				     _("Error resolving `%s': %s"), destination,
++				     strerror(errno));
++			goto err;
++		}
++		destination = tmp;
++	}
++	if (rename(source, destination) != 0) {
++		lu_error_new(error, lu_error_write,
++			     _("Error replacing `%s': %s"), destination,
++			     strerror(errno));
++		goto err;
++	}
++	ret = TRUE;
++	/* Fall through */
++
++err:
++	free(tmp);
++	return ret;
++}
++
++/* Finish editing E, commit edits if COMMIT.
++ * Return true only if RET_INPUT and everything went OK; suggested usage is
++ *  ret = editing_close(e, commit, ret, error); */
++static gboolean
++editing_close(struct editing *e, gboolean commit, gboolean ret_input,
++	      struct lu_error **error)
++{
++	gboolean ret = FALSE;
++	gboolean unlink_new_filename = TRUE;
++
++	g_assert(e != NULL);
++
++	if (commit && fsync(e->new_fd) != 0) {
++		lu_error_new(error, lu_error_write, _("Error writing `%s': %s"),
++			     e->new_filename, strerror(errno));
++		close(e->new_fd);
++		goto err;
++	}
++	close(e->new_fd);
++
++	if (commit) {
++		if (replace_file_or_symlink(e->new_filename, e->filename,
++					    error) == FALSE)
++			goto err;
++		unlink_new_filename = FALSE;
++	}
++	ret = ret_input;
++
++err:
++	if (unlink_new_filename)
++		(void)unlink(e->new_filename);
++	g_free(e->new_filename);
++	lu_util_fscreate_restore(e->fscreate);
++
++	(void)lock_file_remove(e->filename);
++	if (geteuid() == 0)
++		(void)ulckpwdf();
++
++	g_free(e->filename);
++	g_free(e);
++	return ret;
++}
++
++
+ /* Read a line from the file, no matter how long it is, and return it as a
+  * newly-allocated string, with the terminator intact. */
+ static char *
+@@ -435,7 +675,6 @@ generic_lookup(struct lu_module *module,
+ {
+ 	gboolean ret;
+ 	int fd = -1;
+-	gpointer lock;
+ 	char *line, *filename;
+ 
+ 	g_assert(module != NULL);
+@@ -446,7 +685,7 @@ generic_lookup(struct lu_module *module,
+ 
+ 	filename = module_filename(module, file_suffix);
+ 
+-	/* Open the file and lock it. */
++	/* Open the file. */
+ 	fd = open(filename, O_RDONLY);
+ 	if (fd == -1) {
+ 		lu_error_new(error, lu_error_open,
+@@ -457,15 +696,9 @@ generic_lookup(struct lu_module *module,
+ 	}
+ 	g_free(filename);
+ 
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL) {
+-		close(fd);
+-		return FALSE;
+-	}
+-
+ 	/* Search for the entry in this file. */
+ 	line = lu_util_line_get_matchingx(fd, name, field, error);
+ 	if (line == NULL) {
+-		lu_util_lock_free(lock);
+ 		close(fd);
+ 		return FALSE;
+ 	}
+@@ -473,7 +706,6 @@ generic_lookup(struct lu_module *module,
+ 	/* If we found data, parse it and then free the data. */
+ 	ret = parser(line, ent);
+ 	g_free(line);
+-	lu_util_lock_free(lock);
+ 	close(fd);
+ 
+ 	return ret;
+@@ -666,6 +898,13 @@ format_generic(struct lu_ent *ent, const
+ 		char *field;
+ 
+ 		field = format_field(ent, formats + i);
++		if (strchr(field, '\n') != NULL) {
++			lu_error_new(error, lu_error_invalid_attribute_value,
++				     _("%s value `%s': `\\n' not allowed"),
++				     formats[i].attribute, field);
++			g_free(field);
++			goto err;
++		}
+ 		if (i != format_count - 1 && strchr(field, ':') != NULL) {
+ 			lu_error_new(error, lu_error_invalid_attribute_value,
+ 				     _("%s value `%s': `:' not allowed"),
+@@ -729,11 +968,9 @@ generic_add(struct lu_module *module, co
+ 	    const struct format_specifier *formats, size_t format_count,
+ 	    struct lu_ent *ent, struct lu_error **error)
+ {
+-	lu_security_context_t fscreate;
+-	char *line, *filename, *contents;
+-	int fd;
++	struct editing *e;
++	char *line, *contents;
+ 	ssize_t r;
+-	gpointer lock;
+ 	struct stat st;
+ 	off_t offset;
+ 	gboolean ret = FALSE;
+@@ -743,50 +980,30 @@ generic_add(struct lu_module *module, co
+ 	g_assert(format_count > 0);
+ 	g_assert(ent != NULL);
+ 
+-	filename = module_filename(module, file_suffix);
+-
+ 	line = format_generic(ent, formats, format_count, error);
+ 	if (line == NULL)
+-		goto err_filename;
++		goto err;
+ 
+-	if (!lu_util_fscreate_save(&fscreate, error))
++	e = editing_open(module, file_suffix, error);
++	if (e == NULL)
+ 		goto err_line;
+-	if (!lu_util_fscreate_from_file(filename, error))
+-		goto err_fscreate;
+-
+-	/* Create a backup copy of the file we're about to modify. */
+-	if (lu_files_create_backup(filename, error) == FALSE)
+-		goto err_fscreate;
+-
+-	/* Open the file. */
+-	fd = open(filename, O_RDWR);
+-	if (fd == -1) {
+-		lu_error_new(error, lu_error_open,
+-			     _("couldn't open `%s': %s"), filename,
+-			     strerror(errno));
+-		goto err_fscreate;
+-	}
+-
+-	/* Lock the file. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL)
+-		goto err_fd;
+ 
+ 	/* Read the file's size. */
+-	if (fstat(fd, &st) == -1) {
++	if (fstat(e->new_fd, &st) == -1) {
+ 		lu_error_new(error, lu_error_stat,
+-			     _("couldn't stat `%s': %s"), filename,
++			     _("couldn't stat `%s': %s"), e->new_filename,
+ 			     strerror(errno));
+-		goto err_lock;
++		goto err_editing;
+ 	}
+ 
+ 	/* Read the entire file in.  There's some room for improvement here,
+ 	 * but at least we still have the lock, so it's not going to get
+ 	 * funky on us. */
+ 	contents = g_malloc0(st.st_size + 1);
+-	if (read(fd, contents, st.st_size) != st.st_size) {
++	if (read(e->new_fd, contents, st.st_size) != st.st_size) {
+ 		lu_error_new(error, lu_error_read,
+ 			     _("couldn't read from `%s': %s"),
+-			     filename, strerror(errno));
++			     e->new_filename, strerror(errno));
+ 		goto err_contents;
+ 	}
+ 
+@@ -798,54 +1015,43 @@ generic_add(struct lu_module *module, co
+ 		goto err_contents;
+ 	}
+ 	/* Hooray, we can add this entry at the end of the file. */
+-	offset = lseek(fd, 0, SEEK_END);
++	offset = lseek(e->new_fd, 0, SEEK_END);
+ 	if (offset == -1) {
+ 		lu_error_new(error, lu_error_write,
+ 			     _("couldn't write to `%s': %s"),
+-			     filename, strerror(errno));
++			     e->new_filename, strerror(errno));
+ 		goto err_contents;
+ 	}
+ 	/* If the last byte in the file isn't a newline, add one, and silently
+ 	 * curse people who use text editors (which shall remain unnamed) which
+ 	 * allow saving of the file without a final line terminator. */
+ 	if ((st.st_size > 0) && (contents[st.st_size - 1] != '\n')) {
+-		if (write(fd, "\n", 1) != 1) {
++		if (write(e->new_fd, "\n", 1) != 1) {
+ 			lu_error_new(error, lu_error_write,
+ 				     _("couldn't write to `%s': %s"),
+-				     filename,
+-				     strerror(errno));
++				     e->new_filename, strerror(errno));
+ 			goto err_contents;
+ 		}
+ 	}
+ 	/* Attempt to write the entire line to the end. */
+-	r = write(fd, line, strlen(line));
++	r = write(e->new_fd, line, strlen(line));
+ 	if ((size_t)r != strlen(line)) {
+ 		/* Oh, come on! */
+ 		lu_error_new(error, lu_error_write,
+-			     _("couldn't write to `%s': %s"),
+-			     filename,
++			     _("couldn't write to `%s': %s"), e->new_filename,
+ 			     strerror(errno));
+-		/* Truncate off whatever we actually managed to write and
+-		 * give up. */
+-		(void)ftruncate(fd, offset);
+ 		goto err_contents;
+ 	}
+-	/* Hey, it succeeded. */
+ 	ret = TRUE;
+ 	/* Fall through */
+ 
+ err_contents:
+ 	g_free(contents);
+-err_lock:
+-	lu_util_lock_free(lock);
+-err_fd:
+-	close(fd);
+-err_fscreate:
+-	lu_util_fscreate_restore(fscreate);
++err_editing:
++	ret = editing_close(e, ret, ret, error); /* Commit/rollback happens here. */
+ err_line:
+ 	g_free(line);
+-err_filename:
+-	g_free(filename);
++err:
+ 	return ret;
+ }
+ 
+@@ -938,11 +1144,9 @@ generic_mod(struct lu_module *module, co
+ 	    const struct format_specifier *formats, size_t format_count,
+ 	    struct lu_ent *ent, struct lu_error **error)
+ {
+-	lu_security_context_t fscreate;
+-	char *filename, *new_line, *contents, *line, *rest;
++	struct editing *e;
++	char *new_line, *contents, *line, *rest;
+ 	char *current_name, *fragment;
+-	int fd;
+-	gpointer lock;
+ 	const char *name_attribute;
+ 	gboolean ret = FALSE;
+ 	struct stat st;
+@@ -971,43 +1175,24 @@ generic_mod(struct lu_module *module, co
+ 		return FALSE;
+ 	}
+ 
+-	filename = module_filename(module, file_suffix);
+-
+ 	new_line = format_generic(ent, formats, format_count, error);
+ 	if (new_line == NULL)
+-		goto err_filename;
++		goto err_current_name;
+ 
+-	if (!lu_util_fscreate_save(&fscreate, error))
++	e = editing_open(module, file_suffix, error);
++	if (e == NULL)
+ 		goto err_new_line;
+-	if (!lu_util_fscreate_from_file(filename, error))
+-		goto err_fscreate;
+-	/* Create a backup file. */
+-	if (lu_files_create_backup(filename, error) == FALSE)
+-		goto err_fscreate;
+ 
+-	/* Open the file to be modified. */
+-	fd = open(filename, O_RDWR);
+-	if (fd == -1) {
+-		lu_error_new(error, lu_error_open,
+-			     _("couldn't open `%s': %s"), filename,
+-			     strerror(errno));
+-		goto err_fscreate;
+-	}
+-
+-	/* Lock the file. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL)
+-		goto err_fd;
+-
+-	if (fstat(fd, &st) == -1) {
++	if (fstat(e->new_fd, &st) == -1) {
+ 		lu_error_new(error, lu_error_stat, _("couldn't stat `%s': %s"),
+-			     filename, strerror(errno));
+-		goto err_lock;
++			     e->new_filename, strerror(errno));
++		goto err_editing;
+ 	}
+ 
+ 	contents = g_malloc(st.st_size + 1 + strlen(new_line));
+-	if (read(fd, contents, st.st_size) != st.st_size) {
++	if (read(e->new_fd, contents, st.st_size) != st.st_size) {
+ 		lu_error_new(error, lu_error_read,
+-			     _("couldn't read from `%s': %s"), filename,
++			     _("couldn't read from `%s': %s"), e->new_filename,
+ 			     strerror(errno));
+ 		goto err_contents;
+ 	}
+@@ -1045,16 +1230,16 @@ generic_mod(struct lu_module *module, co
+ 	memmove(line + strlen(new_line), rest,
+ 		contents + st.st_size + 1 - rest);
+ 	memcpy(line, new_line, strlen(new_line));
+-	if (lseek(fd, line - contents, SEEK_SET) == -1) {
++	if (lseek(e->new_fd, line - contents, SEEK_SET) == -1) {
+ 		lu_error_new(error, lu_error_write, NULL);
+ 		goto err_contents;
+ 	}
+ 	len = strlen(line);
+-	if ((size_t)write(fd, line, len) != len) {
++	if ((size_t)write(e->new_fd, line, len) != len) {
+ 		lu_error_new(error, lu_error_write, NULL);
+ 		goto err_contents;
+ 	}
+-	if (ftruncate(fd, (line - contents) + len) != 0) {
++	if (ftruncate(e->new_fd, (line - contents) + len) != 0) {
+ 		lu_error_new(error, lu_error_write, NULL);
+ 		goto err_contents;
+ 	}
+@@ -1063,16 +1248,11 @@ generic_mod(struct lu_module *module, co
+ 
+ err_contents:
+ 	g_free(contents);
+-err_lock:
+-	lu_util_lock_free(lock);
+-err_fd:
+-	close(fd);
+-err_fscreate:
+-	lu_util_fscreate_restore(fscreate);
++err_editing:
++	ret = editing_close(e, ret, ret, error); /* Commit/rollback happens here. */
+ err_new_line:
+ 	g_free(new_line);
+-err_filename:
+-	g_free(filename);
++err_current_name:
+ 	g_free(current_name);
+ 	return ret;
+ }
+@@ -1118,16 +1298,14 @@ static gboolean
+ generic_del(struct lu_module *module, const char *file_suffix,
+ 	    struct lu_ent *ent, struct lu_error **error)
+ {
+-	lu_security_context_t fscreate;
++	struct editing *e;
+ 	char *name;
+-	char *contents, *filename;
++	char *contents;
+ 	char *fragment2;
+ 	struct stat st;
+ 	size_t len;
+-	int fd;
+-        gboolean ret = FALSE;
++        gboolean commit = FALSE, ret = FALSE;
+ 	gboolean found;
+-	gpointer lock;
+ 
+ 	/* Get the entity's current name. */
+ 	if (ent->type == lu_user)
+@@ -1141,42 +1319,23 @@ generic_del(struct lu_module *module, co
+ 	g_assert(module != NULL);
+ 	g_assert(ent != NULL);
+ 
+-	filename = module_filename(module, file_suffix);
+-
+-	if (!lu_util_fscreate_save(&fscreate, error))
+-		goto err_filename;
+-	if (!lu_util_fscreate_from_file(filename, error))
+-		goto err_fscreate;
+-	/* Create a backup of that file. */
+-	if (lu_files_create_backup(filename, error) == FALSE)
+-		goto err_fscreate;
+-
+-	/* Open the file to be modified. */
+-	fd = open(filename, O_RDWR);
+-	if (fd == -1) {
+-		lu_error_new(error, lu_error_open,
+-			     _("couldn't open `%s': %s"), filename,
+-			     strerror(errno));
+-		goto err_fscreate;
+-	}
+-
+-	/* Lock the file. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL)
+-		goto err_fd;
++	e = editing_open(module, file_suffix, error);
++	if (e == NULL)
++		goto err_name;
+ 
+ 	/* Determine the file's size. */
+-	if (fstat(fd, &st) == -1) {
++	if (fstat(e->new_fd, &st) == -1) {
+ 		lu_error_new(error, lu_error_stat,
+-			     _("couldn't stat `%s': %s"), filename,
++			     _("couldn't stat `%s': %s"), e->new_filename,
+ 			     strerror(errno));
+-		goto err_lock;
++		goto err_editing;
+ 	}
+ 
+ 	/* Allocate space to hold the file and read it all in. */
+ 	contents = g_malloc(st.st_size + 1);
+-	if (read(fd, contents, st.st_size) != st.st_size) {
++	if (read(e->new_fd, contents, st.st_size) != st.st_size) {
+ 		lu_error_new(error, lu_error_read,
+-			     _("couldn't read from `%s': %s"), filename,
++			     _("couldn't read from `%s': %s"), e->new_filename,
+ 			     strerror(errno));
+ 		goto err_contents;
+ 	}
+@@ -1229,41 +1388,38 @@ generic_del(struct lu_module *module, co
+ 
+ 	/* Otherwise we need to write the new data to the file.  Jump back to
+ 	 * the beginning of the file. */
+-	if (lseek(fd, 0, SEEK_SET) == -1) {
++	if (lseek(e->new_fd, 0, SEEK_SET) == -1) {
+ 		lu_error_new(error, lu_error_write,
+-			     _("couldn't write to `%s': %s"), filename,
++			     _("couldn't write to `%s': %s"), e->new_filename,
+ 			     strerror(errno));
+ 		goto err_contents;
+ 	}
+ 
+ 	/* Write the new contents out. */
+-	if ((size_t)write(fd, contents, len) != len) {
++	if ((size_t)write(e->new_fd, contents, len) != len) {
+ 		lu_error_new(error, lu_error_write,
+-			     _("couldn't write to `%s': %s"), filename,
++			     _("couldn't write to `%s': %s"), e->new_filename,
+ 			     strerror(errno));
+ 		goto err_contents;
+ 	}
+ 
+ 	/* Truncate the file to the new (certainly shorter) length. */
+-	if (ftruncate(fd, len) == -1) {
++	if (ftruncate(e->new_fd, len) == -1) {
+ 		lu_error_new(error, lu_error_generic,
+-			     _("couldn't write to `%s': %s"), filename,
++			     _("couldn't write to `%s': %s"), e->new_filename,
+ 			     strerror(errno));
+ 		goto err_contents;
+ 	}
++	commit = TRUE;
+ 	ret = TRUE;
+ 	/* Fall through */
+ 
+  err_contents:
+ 	g_free(contents);
+- err_lock:
+-	lu_util_lock_free(lock);
+- err_fd:
+-	close(fd);
+-err_fscreate:
+-	lu_util_fscreate_restore(fscreate);
+- err_filename:
+-	g_free(filename);
++err_editing:
++	/* Commit/rollback happens here. */
++	ret = editing_close(e, commit, ret, error);
++err_name:
+ 	g_free(name);
+ 	return ret;
+ }
+@@ -1344,12 +1500,9 @@ static gboolean
+ generic_lock(struct lu_module *module, const char *file_suffix, int field,
+ 	     struct lu_ent *ent, enum lock_op op, struct lu_error **error)
+ {
+-	lu_security_context_t fscreate;
+-	char *filename;
++	struct editing *e;
+ 	char *value, *new_value, *name;
+-	int fd;
+-	gpointer lock;
+-	gboolean ret = FALSE;
++	gboolean commit = FALSE, ret = FALSE;
+ 
+ 	/* Get the name which keys the entries of interest in the file. */
+ 	g_assert((ent->type == lu_user) || (ent->type == lu_group));
+@@ -1362,33 +1515,14 @@ generic_lock(struct lu_module *module, c
+ 	g_assert(module != NULL);
+ 	g_assert(ent != NULL);
+ 
+-	filename = module_filename(module, file_suffix);
+-
+-	if (!lu_util_fscreate_save(&fscreate, error))
+-		goto err_filename;
+-	if (!lu_util_fscreate_from_file(filename, error))
+-		goto err_fscreate;
+-	/* Create a backup of the file. */
+-	if (lu_files_create_backup(filename, error) == FALSE)
+-		goto err_fscreate;
+-
+-	/* Open the file. */
+-	fd = open(filename, O_RDWR);
+-	if (fd == -1) {
+-		lu_error_new(error, lu_error_open,
+-			     _("couldn't open `%s': %s"), filename,
+-			     strerror(errno));
+-		goto err_fscreate;
+-	}
+-
+-	/* Lock the file. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL)
+-		goto err_fd;
++	e = editing_open(module, file_suffix, error);
++	if (e == NULL)
++		goto err_name;
+ 
+ 	/* Read the old value from the file. */
+-	value = lu_util_field_read(fd, name, field, error);
++	value = lu_util_field_read(e->new_fd, name, field, error);
+ 	if (value == NULL)
+-		goto err_lock;
++		goto err_editing;
+ 
+ 	/* Check that we actually care about this.  If there's a non-empty,
+ 	 * not locked string in there, but it's too short to be a hash, then
+@@ -1396,27 +1530,27 @@ generic_lock(struct lu_module *module, c
+ 	if (LU_CRYPT_INVALID(value)) {
+ 		g_free(value);
+ 		ret = TRUE;
+-		goto err_lock;
++		goto err_editing;
+ 	}
+ 
+ 	/* Generate a new value for the file. */
+ 	new_value = lock_process(value, op, ent, error);
+ 	g_free(value);
+ 	if (new_value == NULL)
+-		goto err_lock;
++		goto err_editing;
+ 
+ 	/* Make the change. */
+-	ret = lu_util_field_write(fd, name, field, new_value, error);
++	if (lu_util_field_write(e->new_fd, name, field, new_value, error)
++	    == FALSE)
++		goto err_editing;
++	commit = TRUE;
++	ret = TRUE;
+ 	/* Fall through */
+ 
+-err_lock:
+-	lu_util_lock_free(lock);
+- err_fd:
+-	close(fd);
+-err_fscreate:
+-	lu_util_fscreate_restore(fscreate);
+- err_filename:
+-	g_free(filename);
++err_editing:
++	/* Commit/rollback happens here. */
++	ret = editing_close(e, commit, ret, error);
++err_name:
+ 	g_free(name);
+ 	return ret;
+ }
+@@ -1429,7 +1563,6 @@ generic_is_locked(struct lu_module *modu
+ 	char *filename;
+ 	char *value, *name;
+ 	int fd;
+-	gpointer lock;
+ 	gboolean ret = FALSE;
+ 
+ 	/* Get the name of this account. */
+@@ -1454,22 +1587,16 @@ generic_is_locked(struct lu_module *modu
+ 		goto err_filename;
+ 	}
+ 
+-	/* Lock the file. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL)
+-		goto err_fd;
+-
+ 	/* Read the value. */
+ 	value = lu_util_field_read(fd, name, field, error);
+ 	if (value == NULL)
+-		goto err_lock;
++		goto err_fd;
+ 
+ 	/* It all comes down to this. */
+ 	ret = value[0] == '!';
+ 	g_free(value);
+ 	/* Fall through */
+ 
+-err_lock:
+-	lu_util_lock_free(lock);
+ err_fd:
+ 	close(fd);
+ err_filename:
+@@ -1624,10 +1751,8 @@ generic_setpass(struct lu_module *module
+ 		struct lu_ent *ent, const char *password, gboolean is_shadow,
+ 		struct lu_error **error)
+ {
+-	lu_security_context_t fscreate;
+-	char *filename, *value, *name;
+-	int fd;
+-	gpointer lock;
++	struct editing *e;
++	char *value, *name;
+ 	gboolean ret = FALSE;
+ 
+ 	/* Get the name of this account. */
+@@ -1641,34 +1766,14 @@ generic_setpass(struct lu_module *module
+ 	g_assert(module != NULL);
+ 	g_assert(ent != NULL);
+ 
+-	filename = module_filename(module, file_suffix);
+-
+-	if (!lu_util_fscreate_save(&fscreate, error))
+-		goto err_filename;
+-	if (!lu_util_fscreate_from_file(filename, error))
+-		goto err_fscreate;
+-
+-	/* Create a backup of the file. */
+-	if (lu_files_create_backup(filename, error) == FALSE)
+-		goto err_filename;
+-
+-	/* Open the file. */
+-	fd = open(filename, O_RDWR);
+-	if (fd == -1) {
+-		lu_error_new(error, lu_error_open,
+-			     _("couldn't open `%s': %s"), filename,
+-			     strerror(errno));
+-		goto err_fscreate;
+-	}
+-
+-	/* Lock the file. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL)
+-		goto err_fd;
++	e = editing_open(module, file_suffix, error);
++	if (e == NULL)
++		goto err_name;
+ 
+ 	/* Read the current contents of the field. */
+-	value = lu_util_field_read(fd, name, field, error);
++	value = lu_util_field_read(e->new_fd, name, field, error);
+ 	if (value == NULL)
+-		goto err_lock;
++		goto err_editing;
+ 
+ 	/* pam_unix uses shadow passwords only if pw_passwd is "x"
+ 	   (or ##${username}).  Make sure to preserve the shadow marker
+@@ -1693,9 +1798,9 @@ generic_setpass(struct lu_module *module
+ 	else if (g_ascii_strncasecmp(password, LU_CRYPTED, strlen(LU_CRYPTED))
+ 		 == 0) {
+ 		password = password + strlen(LU_CRYPTED);
+-		if (strchr(password, ':') != NULL) {
++		if (strpbrk(password, ":\n") != NULL) {
+ 			lu_error_new(error, lu_error_invalid_attribute_value,
+-				     _("`:' not allowed in encrypted "
++				     _("`:' and `\\n' not allowed in encrypted "
+ 				       "password"));
+ 			goto err_value;
+ 		}
+@@ -1713,19 +1818,14 @@ generic_setpass(struct lu_module *module
+ 	}
+ 
+ 	/* Now write our changes to the file. */
+-	ret = lu_util_field_write(fd, name, field, password, error);
++	ret = lu_util_field_write(e->new_fd, name, field, password, error);
+ 	/* Fall through */
+ 
+- err_value:
++err_value:
+ 	g_free(value);
+-err_lock:
+-	lu_util_lock_free(lock);
+- err_fd:
+-	close(fd);
+-err_fscreate:
+-	lu_util_fscreate_restore(fscreate);
+- err_filename:
+-	g_free(filename);
++err_editing:
++	ret = editing_close(e, ret, ret, error); /* Commit/rollback happens here. */
++err_name:
+ 	g_free(name);
+ 	return ret;
+ }
+@@ -1802,7 +1902,6 @@ lu_files_enumerate(struct lu_module *mod
+ 		   const char *pattern, struct lu_error **error)
+ {
+ 	int fd;
+-	gpointer lock;
+ 	GValueArray *ret;
+ 	GValue value;
+ 	char *buf;
+@@ -1824,20 +1923,12 @@ lu_files_enumerate(struct lu_module *mod
+ 		return NULL;
+ 	}
+ 
+-	/* Lock the file. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL) {
+-		close(fd);
+-		g_free(filename);
+-		return NULL;
+-	}
+-
+ 	/* Wrap the file for stdio operations. */
+ 	fp = fdopen(fd, "r");
+ 	if (fp == NULL) {
+ 		lu_error_new(error, lu_error_open,
+ 			     _("couldn't open `%s': %s"), filename,
+ 			     strerror(errno));
+-		lu_util_lock_free(lock);
+ 		close(fd);
+ 		g_free(filename);
+ 		return NULL;
+@@ -1873,7 +1964,6 @@ lu_files_enumerate(struct lu_module *mod
+ 
+ 	/* Clean up. */
+ 	g_value_unset(&value);
+-	lu_util_lock_free(lock);
+ 	fclose(fp);
+ 	g_free(filename);
+ 
+@@ -1902,7 +1992,6 @@ lu_files_users_enumerate_by_group(struct
+ 				  struct lu_error **error)
+ {
+ 	int fd;
+-	gpointer lock;
+ 	GValueArray *ret;
+ 	GValue value;
+ 	char *buf, grp[CHUNK_SIZE];
+@@ -1927,21 +2016,12 @@ lu_files_users_enumerate_by_group(struct
+ 		return NULL;
+ 	}
+ 
+-	/* Lock the passwd file. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL) {
+-		close(fd);
+-		g_free(pwdfilename);
+-		g_free(grpfilename);
+-		return NULL;
+-	}
+-
+ 	/* Wrap the descriptor in a stdio FILE. */
+ 	fp = fdopen(fd, "r");
+ 	if (fp == NULL) {
+ 		lu_error_new(error, lu_error_open,
+ 			     _("couldn't open `%s': %s"), pwdfilename,
+ 			     strerror(errno));
+-		lu_util_lock_free(lock);
+ 		close(fd);
+ 		g_free(pwdfilename);
+ 		g_free(grpfilename);
+@@ -2000,7 +2080,6 @@ lu_files_users_enumerate_by_group(struct
+ 	}
+ 	/* Close the file. */
+ 	g_value_unset(&value);
+-	lu_util_lock_free(lock);
+ 	fclose(fp);
+ 
+ 	/* Open the group file. */
+@@ -2015,22 +2094,12 @@ lu_files_users_enumerate_by_group(struct
+ 		return NULL;
+ 	}
+ 
+-	/* Lock the group file. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL) {
+-		close(fd);
+-		g_free(pwdfilename);
+-		g_free(grpfilename);
+-		g_value_array_free(ret);
+-		return NULL;
+-	}
+-
+ 	/* Wrap the group file in an stdio file. */
+ 	fp = fdopen(fd, "r");
+ 	if (fp == NULL) {
+ 		lu_error_new(error, lu_error_open,
+ 			     _("couldn't open `%s': %s"), grpfilename,
+ 			     strerror(errno));
+-		lu_util_lock_free(lock);
+ 		close(fd);
+ 		g_free(pwdfilename);
+ 		g_free(grpfilename);
+@@ -2085,7 +2154,6 @@ lu_files_users_enumerate_by_group(struct
+ 	}
+ 
+ 	/* Clean up. */
+-	lu_util_lock_free(lock);
+ 	fclose(fp);
+ 
+ 	g_free(pwdfilename);
+@@ -2102,7 +2170,6 @@ lu_files_groups_enumerate_by_user(struct
+ 				  struct lu_error **error)
+ {
+ 	int fd;
+-	gpointer lock;
+ 	GValueArray *ret;
+ 	GValue value;
+ 	char *buf;
+@@ -2126,19 +2193,12 @@ lu_files_groups_enumerate_by_user(struct
+ 		goto err_pwdfilename;
+ 	}
+ 
+-	/* Lock it. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL) {
+-		close(fd);
+-		goto err_pwdfilename;
+-	}
+-
+ 	/* Open it so that we can use stdio. */
+ 	fp = fdopen(fd, "r");
+ 	if (fp == NULL) {
+ 		lu_error_new(error, lu_error_open,
+ 			     _("couldn't open `%s': %s"), pwdfilename,
+ 			     strerror(errno));
+-		lu_util_lock_free(lock);
+ 		close(fd);
+ 		goto err_pwdfilename;
+ 	}
+@@ -2186,7 +2246,6 @@ lu_files_groups_enumerate_by_user(struct
+ 		}
+ 		g_free(buf);
+ 	}
+-	lu_util_lock_free(lock);
+ 	fclose(fp);
+ 
+ 	/* Open the groups file. */
+@@ -2198,19 +2257,12 @@ lu_files_groups_enumerate_by_user(struct
+ 		goto err_key;
+ 	}
+ 
+-	/* Lock it. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL) {
+-		close(fd);
+-		goto err_key;
+-	}
+-
+ 	/* Open it so that we can use stdio. */
+ 	fp = fdopen(fd, "r");
+ 	if (fp == NULL) {
+ 		lu_error_new(error, lu_error_open,
+ 			     _("couldn't open `%s': %s"), grpfilename,
+ 			     strerror(errno));
+-		lu_util_lock_free(lock);
+ 		close(fd);
+ 		goto err_key;
+ 	}
+@@ -2267,7 +2319,6 @@ lu_files_groups_enumerate_by_user(struct
+ 	g_free(key);
+ 	g_value_unset(&value);
+ 
+-	lu_util_lock_free(lock);
+ 	fclose(fp);
+ 	g_free(pwdfilename);
+ 	g_free(grpfilename);
+@@ -2291,7 +2342,6 @@ lu_files_enumerate_full(struct lu_module
+ 			struct lu_error **error)
+ {
+ 	int fd;
+-	gpointer lock;
+ 	GPtrArray *ret = NULL;
+ 	char *buf;
+ 	char *key, *filename;
+@@ -2311,19 +2361,12 @@ lu_files_enumerate_full(struct lu_module
+ 		goto err_filename;
+ 	}
+ 
+-	/* Lock the file. */
+-	if ((lock = lu_util_lock_obtain(fd, error)) == NULL) {
+-		close(fd);
+-		goto err_filename;
+-	}
+-
+ 	/* Wrap the file up in stdio. */
+ 	fp = fdopen(fd, "r");
+ 	if (fp == NULL) {
+ 		lu_error_new(error, lu_error_open,
+ 			     _("couldn't open `%s': %s"), filename,
+ 			     strerror(errno));
+-		lu_util_lock_free(lock);
+ 		close(fd);
+ 		goto err_filename;
+ 	}
+@@ -2358,7 +2401,6 @@ lu_files_enumerate_full(struct lu_module
+ 		g_free(key);
+ 	}
+ 
+-	lu_util_lock_free(lock);
+ 	fclose(fp);
+ 
+  err_filename:
+diff -up libuser-0.60/tests/files_test.py.CVE-2015-3246 libuser-0.60/tests/files_test.py
+--- libuser-0.60/tests/files_test.py.CVE-2015-3246	2013-10-12 23:56:08.000000000 +0200
++++ libuser-0.60/tests/files_test.py	2015-07-08 15:15:14.061544074 +0200
+@@ -262,6 +262,21 @@ class Tests(unittest.TestCase):
+         e = self.a.initUser('user6_8')
+         self.assertRaises(RuntimeError, self.a.addUser, e, False, False)
+ 
++    def testUserAdd9(self):
++        # '\n' in field values
++        # libuser.USERPASSWORD not tested because lu_shadow_user_add_prep()
++        # always replaces it by 'x'.  libuser.UIDNUMBER not tested because
++        # ent_has_name_and_id() interprets the value as a number.
++        for field in (libuser.USERNAME, libuser.GIDNUMBER, libuser.GECOS,
++                      libuser.HOMEDIRECTORY, libuser.LOGINSHELL,
++                      libuser.SHADOWPASSWORD, libuser.SHADOWLASTCHANGE, 
++                      libuser.SHADOWMIN, libuser.SHADOWMAX, 
++                      libuser.SHADOWWARNING, libuser.SHADOWINACTIVE, 
++                      libuser.SHADOWEXPIRE, libuser.SHADOWFLAG):
++            e = self.a.initUser('user_6_9' + field)
++            e[field] = str(e[field][0]) + '\nx'
++            self.assertRaises(RuntimeError, self.a.addUser, e, False, False)
++
+     def testUserMod1(self):
+         # A minimal case
+         e = self.a.initUser('user7_1')
+@@ -421,6 +436,26 @@ class Tests(unittest.TestCase):
+         e[libuser.USERNAME] = 'user7_7'
+         self.assertRaises(RuntimeError, self.a.modifyUser, e, False)
+ 
++    def testUserMod8(self):
++        # '\n' in field values
++        # libuser.USERPASSWORD not tested because lu_shadow_user_add_prep()
++        # always replaces it by 'x'.  libuser.UIDNUMBER not tested because
++        # ent_has_name_and_id() interprets the value as a number.
++        for field in (libuser.USERNAME, libuser.USERPASSWORD, libuser.GIDNUMBER,
++                      libuser.GECOS, libuser.HOMEDIRECTORY, libuser.LOGINSHELL,
++                      libuser.SHADOWPASSWORD, libuser.SHADOWLASTCHANGE,
++                      libuser.SHADOWMIN, libuser.SHADOWMAX,
++                      libuser.SHADOWWARNING, libuser.SHADOWINACTIVE,
++                      libuser.SHADOWEXPIRE, libuser.SHADOWFLAG):
++            e = self.a.initUser('user7_9' + field)
++            self.a.addUser(e, False, False)
++            del e
++            e = self.a.lookupUserByName('user7_9' + field)
++            self.assertIsNotNone(e)
++            self.assertNotIn('\n', str(e[field][0]))
++            e[field] = str(e[field][0]) + '\nx'
++            self.assertRaises(RuntimeError, self.a.modifyUser, e, False)
++
+     def testUserDel(self):
+         e = self.a.initUser('user8_1')
+         self.a.addUser(e, False, False)
+@@ -619,6 +654,22 @@ class Tests(unittest.TestCase):
+         crypted = crypt.crypt('a:b', e[libuser.SHADOWPASSWORD][0])
+         self.assertEqual(e[libuser.SHADOWPASSWORD], [crypted])
+ 
++    def testUserSetpass5(self):
++        # '\n' in field value
++        e = self.a.initUser('user12_5')
++        self.a.addUser(e, False, False)
++        del e
++        e = self.a.lookupUserByName('user12_5')
++        self.assertNotIn('\n', e[libuser.SHADOWPASSWORD][0])
++        self.assertRaises(SystemError, self.a.setpassUser, e, 'a\nb', True)
++        self.a.setpassUser(e, 'a\nb', False)
++        del e
++        e = self.a.lookupUserByName('user12_5')
++        self.assertEqual(e[libuser.SHADOWPASSWORD][0][:3], '$1$')
++        self.assertNotIn('\n', e[libuser.SHADOWPASSWORD][0])
++        crypted = crypt.crypt('a\nb', e[libuser.SHADOWPASSWORD][0])
++        self.assertEqual(e[libuser.SHADOWPASSWORD], [crypted])
++
+     def testUserRemovepass(self):
+         e = self.a.initUser('user13_1')
+         e[libuser.SHADOWPASSWORD] = '03dgZm5nZvqOc'
+@@ -884,6 +935,20 @@ class Tests(unittest.TestCase):
+         e = self.a.initGroup('group21_5')
+         self.assertRaises(RuntimeError, self.a.addGroup, e)
+ 
++    def testGroupAdd6(self):
++        # '\n' in field values
++        # libuser.GROUPPASSWORD not tested because lu_shadow_group_add_prep()
++        # always replaces it by 'x'.  libuser.GIDNUMBER not tested because
++        # ent_has_name_and_id() interprets the value as a number.
++        for field in (libuser.GROUPNAME, libuser.SHADOWPASSWORD,
++                      libuser.MEMBERNAME, libuser.ADMINISTRATORNAME):
++            e = self.a.initGroup('group_21_6' + field)
++            if e.has_key(field):
++                e[field] = str(e[field][0]) + '\nx'
++            else:
++                e[field] = field + '\nx'
++            self.assertRaises(RuntimeError, self.a.addGroup, e)
++
+     def testGroupMod1(self):
+         # A minimal case
+         e = self.a.initGroup('group22_1')
+@@ -997,6 +1062,25 @@ class Tests(unittest.TestCase):
+         e[libuser.GROUPNAME] = 'group22_6'
+         self.assertRaises(RuntimeError, self.a.modifyGroup, e)
+ 
++    def testGroupMod7(self):
++        # '\n' in field values
++        # libuser.GIDNUMBER not tested because ent_has_name_and_id() interprets
++        # the value as a number.
++        for field in (libuser.GROUPNAME, libuser.GROUPPASSWORD,
++                      libuser.SHADOWPASSWORD, libuser.MEMBERNAME,
++                      libuser.ADMINISTRATORNAME):
++            e = self.a.initGroup('group22_8' + field)
++            self.a.addGroup(e)
++            del e
++            e = self.a.lookupGroupByName('group22_8' + field)
++            self.assertIsNotNone(e)
++            if e.has_key(field):
++                self.assertNotIn('\n', str(e[field][0]))
++                e[field] = str(e[field][0]) + '\nx'
++            else:
++                e[field] = field + '\nx'
++            self.assertRaises(RuntimeError, self.a.modifyGroup, e)
++
+     def testGroupDel(self):
+         e = self.a.initGroup('group23_1')
+         self.a.addGroup(e)
+@@ -1190,6 +1274,22 @@ class Tests(unittest.TestCase):
+         crypted = crypt.crypt('a:b', e[libuser.SHADOWPASSWORD][0])
+         self.assertEqual(e[libuser.SHADOWPASSWORD], [crypted])
+ 
++    def testGroupSetpass4(self):
++        # '\n' in field value
++        e = self.a.initGroup('group27_5')
++        self.a.addGroup(e)
++        del e
++        e = self.a.lookupGroupByName('group27_5')
++        self.assertNotIn('\n', e[libuser.SHADOWPASSWORD][0])
++        self.assertRaises(SystemError, self.a.setpassGroup, e, 'a\nb', True)
++        self.a.setpassGroup(e, 'a\nb', False)
++        del e
++        e = self.a.lookupGroupByName('group27_5')
++        self.assertEqual(e[libuser.SHADOWPASSWORD][0][:3], '$1$')
++        self.assertNotIn('\n', e[libuser.SHADOWPASSWORD][0])
++        crypted = crypt.crypt('a\nb', e[libuser.SHADOWPASSWORD][0])
++        self.assertEqual(e[libuser.SHADOWPASSWORD], [crypted])
++
+     def testGroupRemovepass(self):
+         e = self.a.initGroup('group28_1')
+         e[libuser.SHADOWPASSWORD] = '07Js7N.eEhbgs'
diff --git a/SPECS/libuser.spec b/SPECS/libuser.spec
new file mode 100644
index 0000000..6d514a4
--- /dev/null
+++ b/SPECS/libuser.spec
@@ -0,0 +1,927 @@
+%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
+
+Name: libuser
+Version: 0.60
+Release: 9%{?dist}
+Group: System Environment/Base
+License: LGPLv2+
+URL: https://fedorahosted.org/libuser/
+Source: https://fedorahosted.org/releases/l/i/libuser/libuser-%{version}.tar.xz
+# https://bugzilla.redhat.com/show_bug.cgi?id=1480537
+Source1: libuser-0.60-ja.po
+Patch0: libuser-CVE-2015-3246.patch
+BuildRequires: glib2-devel, linuxdoc-tools, pam-devel, popt-devel, python2-devel
+BuildRequires: cyrus-sasl-devel, libselinux-devel, openldap-devel
+# To make sure the configure script can find it
+BuildRequires: nscd
+# For %%check
+BuildRequires: openldap-clients, openldap-servers, openssl
+BuildRequires: gettext
+Summary: A user and group account administration library
+
+%description
+The libuser library implements a standardized interface for manipulating
+and administering user and group accounts.  The library uses pluggable
+back-ends to interface to its data sources.
+
+Sample applications modeled after those included with the shadow password
+suite are included.
+
+%package devel
+Group: Development/Libraries
+Summary: Files needed for developing applications which use libuser
+Requires: %{name}%{?_isa} = %{version}-%{release}
+Requires: glib2-devel%{?_isa}
+
+%description devel
+The libuser-devel package contains header files, static libraries, and other
+files useful for developing applications with libuser.
+
+%package python
+Summary: Python bindings for the libuser library
+Group: Development/Libraries
+Requires: libuser%{?_isa} = %{version}-%{release}
+
+%description python
+The libuser-python package contains the Python bindings for
+the libuser library, which provides a Python API for manipulating and
+administering user and group accounts.
+
+%prep
+%setup -q
+
+%patch0 -p1 -b .CVE-2015-3246
+cp %{SOURCE1} po/ja.po
+
+%build
+%configure --with-selinux --with-ldap --with-html-dir=%{_datadir}/gtk-doc/html
+make
+make -C po ja.gmo # (make all) only rebuilds .gmo files if the .pot file is updated, regardless of po/ja.po changes
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT INSTALL='install -p'
+
+%find_lang %{name}
+
+%check
+
+make check || { cat test-suite.log; false; }
+
+# Verify that all python modules load, just in case.
+LD_LIBRARY_PATH=$RPM_BUILD_ROOT/%{_libdir}:${LD_LIBRARY_PATH}
+export LD_LIBRARY_PATH
+cd $RPM_BUILD_ROOT/%{python_sitearch}
+python -c "import libuser"
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files -f %{name}.lang
+%doc AUTHORS COPYING NEWS README TODO docs/*.txt
+%config(noreplace) %{_sysconfdir}/libuser.conf
+
+%attr(0755,root,root) %{_bindir}/*
+%{_libdir}/*.so.*
+%dir %{_libdir}/%{name}
+%{_libdir}/%{name}/*.so
+%attr(0755,root,root) %{_sbindir}/*
+%{_mandir}/man1/*
+%{_mandir}/man5/*
+
+%exclude %{_libdir}/*.la
+%exclude %{_libdir}/%{name}/*.la
+
+%files python
+%doc python/modules.txt
+%{python_sitearch}/*.so
+%exclude %{python_sitearch}/*.la
+
+%files devel
+%{_includedir}/libuser
+%{_libdir}/*.so
+%{_libdir}/pkgconfig/*
+%{_datadir}/gtk-doc/html/*
+
+%changelog
+* Mon Jan 15 2018 Miloslav Trmač <mitr@redhat.com> - 0.60-9
+- Update Japanese translation
+  Resolves: #1480537
+
+* Tue Dec  5 2017 Miloslav Trmač <mitr@redhat.com> - 0.60-8
+- Update Japanese translation
+  Resolves: #1480537
+
+* Wed Jul  8 2015 Miloslav Trmač <mitr@redhat.com> - 0.60-7
+- Update CVE-2015-3246 patch based on review comments
+  Resolves: #1235520
+
+* Fri Jun 26 2015 Miloslav Trmač <mitr@redhat.com> - 0.60-6
+- Fix CVE-2015-3246
+  Resolves: #1235520
+
+* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 0.60-5
+- Mass rebuild 2014-01-24
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 0.60-4
+- Mass rebuild 2013-12-27
+
+* Tue Oct 15 2013 Miloslav Trmač <mitr@redhat.com> - 0.60-3
+- Fix the -2 change, %%check should fail on test suite failure
+- Drop an upstreamed patch
+
+* Mon Oct 14 2013 Miloslav Trmač <mitr@redhat.com> - 0.60-2
+- Include test suite output in build log on failure
+
+* Mon Oct 14 2013 Miloslav Trmač <mitr@redhat.com> - 0.60-1
+- Update to libuser-0.60
+  Resolves: #1008933
+
+* Thu Jun 27 2013 Miloslav Trmač <mitr@redhat.com> - 0.59-2
+- Drop BuildRequires: fakeroot and skip the test that needs it
+  Resolves: #975888
+
+* Thu Mar 28 2013 Miloslav Trmač <mitr@redhat.com> - 0.59-1
+- Update to libuser-0.59 (CVE-2012-5630, CVE-2012-5644)
+  Resolves: #928846
+
+* Mon Feb  4 2013 Miloslav Trmač <mitr@redhat.com> - 0.58-2
+- Always use secure_getenv() or __secure_getenv(), fail build if neither is
+  available.  Patch by Viktor Hercinger <vhercing@redhat.com>.
+
+* Thu Nov  8 2012 Miloslav Trmač <mitr@redhat.com> - 0.58-1
+- Update to libuser-0.58
+  Resolves: #844140, #854236
+
+* Mon Sep 24 2012 Miloslav Trmač <mitr@redhat.com> - 0.57.7-1
+- Update to libuser-0.57.7
+
+* Tue Aug 21 2012 Miloslav Trmač <mitr@redhat.com> - 0.57.6-3
+- Drop no longer necessary %%clean and %%defattr commands.
+
+* Thu Jul 19 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.57.6-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Thu Mar 22 2012 Miloslav Trmač <mitr@redhat.com> - 0.57.6-1
+- Update to libuser-0.57.6
+  Resolves: #803840
+
+* Sat Mar  3 2012 Miloslav Trmač <mitr@redhat.com> - 0.57.5-1
+- Update to libuser-0.57.5
+- BuildRequires: openssl, the testsuite needs /usr/bin/openssl
+
+* Fri Feb 10 2012 Miloslav Trmač <mitr@redhat.com> - 0.57.4-1
+- Update to libuser-0.57.4
+  Resolves: #788521
+
+* Fri Jan 13 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.57.3-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
+
+* Tue Oct  4 2011 Miloslav Trmač <mitr@redhat.com> - 0.57.3-2
+- Wait up to 30 seconds for slapd to start in the test suite
+
+* Tue Oct  4 2011 Miloslav Trmač <mitr@redhat.com> - 0.57.3-1
+- Update to libuser-0.57.3
+  Resolves: #717116, #724986
+
+* Thu Mar 31 2011 Miloslav Trmač <mitr@redhat.com> - 0.57.2-1
+- Update to libuser-0.57.2
+  Resolves: #671494
+- Reenable (make check)
+
+* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.57.1-5
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Fri Feb  4 2011 Miloslav Trmač <mitr@redhat.com> - 0.57.1-4
+- Use %%{?_isa} in Requires:
+
+* Fri Jan 21 2011 Miloslav Trmač <mitr@redhat.com> - 0.57.1-3
+- Disable (make check) to allow parallel 32-bit and 64-bit builds
+
+* Thu Jan 20 2011 Miloslav Trmač <mitr@redhat.com> - 0.57.1-2
+- Don't default commonName to gecos if it is empty
+  Resolves: #670151
+
+* Fri Jan 14 2011 Miloslav Trmač <mitr@redhat.com> - 0.57.1-1
+- Update to libuser-0.57.1
+  Resolves: #668855
+
+* Mon Jan 10 2011 Miloslav Trmač <mitr@redhat.com> - 0.57-1
+- Update to libuser-0.57
+  Resolves: #497333 #610172
+
+* Wed Sep 29 2010 Miloslav Trmač <mitr@redhat.com> - 0.56.18-2
+- Handle matchpathcon() failing with ENOENT
+  Resolves: #631717
+
+* Tue Sep 14 2010 Miloslav Trmač <mitr@redhat.com> - 0.56.18-1
+- Update to libuser-0.56.18
+
+* Wed Sep  1 2010 Miloslav Trmač <mitr@redhat.com> - 0.56.17-2
+- Change default crypt_style to sha512
+  Resolves: #629001
+
+* Thu Aug 26 2010 Miloslav Trmač <mitr@redhat.com> - 0.56.17-1
+- Update to libuser-0.56.17
+
+* Wed Jul 21 2010 David Malcolm <dmalcolm@redhat.com> - 0.56.16-3
+- Rebuilt for https://fedoraproject.org/wiki/Features/Python_2.7/MassRebuild
+
+* Fri Jul  2 2010 Miloslav Trmač <mitr@redhat.com> - 0.56.16-2
+- Provide LU_VALUE_INVALID_ID and id_t validation in the Python module
+  Resolves: #610838
+
+* Thu Mar 25 2010 Miloslav Trmač <mitr@redhat.com> - 0.56.16-1
+- Update to libuser-0.56.16.
+
+* Thu Mar  4 2010 Miloslav Trmač <mitr@redhat.com> - 0.56.15-1
+- Update to libuser-0.56.15.
+- Drop no longer necessary references to BuildRequires
+
+* Mon Feb  8 2010 Miloslav Trmač <mitr@redhat.com> - 0.56.14-1
+- Update to libuser-0.56.14.
+
+* Tue Jan  5 2010 Miloslav Trmač <mitr@redhat.com> - 0.56.13-2
+- s/%%define/%%global/
+
+* Fri Dec 11 2009 Miloslav Trmač <mitr@redhat.com> - 0.56.13-1
+- Update to libuser-0.56.13.
+  Resolves: #251951
+  Resolves: #454079
+  Resolves: #456373
+  Resolves: #456382
+  Resolves: #530513
+
+* Fri Oct  2 2009 Miloslav Trmač <mitr@redhat.com> - 0.56.12-1
+- Update to libuser-0.56.12.
+
+* Mon Sep 14 2009 Miloslav Trmač <mitr@redhat.com> - 0.56.11-1
+- Update to libuser-0.56.11.
+  Resolves: #454091
+  Resolves: #456267
+  Resolves: #456270
+  Resolves: #487129
+
+* Thu Jul 30 2009 Miloslav Trmač <mitr@redhat.com> - 0.56.10-3
+- Fix nscd cache invalidation
+  Resolves: #506628
+- Preserve timestamps during (make install)
+
+* Sat Jul 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.56.10-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
+
+* Wed Apr 15 2009 Miloslav Trmač <mitr@redhat.com> - 0.56.10-1
+- Update to libuser-0.56.10.
+
+* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.56.9-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Sat Nov 29 2008 Ignacio Vazquez-Abrams <ivazqueznet+rpm@gmail.com> - 0.56.9-2
+- Rebuild for Python 2.6
+
+* Wed Apr  9 2008 Miloslav Trmač <mitr@redhat.com> - 0.56.9-1
+- Update to libuser-0.56.9.
+
+* Sat Feb 23 2008 Miloslav Trmač <mitr@redhat.com> - 0.56.8-1
+- New home page at https://fedorahosted.org/libuser/ .
+
+* Tue Feb 19 2008 Fedora Release Engineering <rel-eng@fedoraproject.org> - 0.56.7-2
+- Autorebuild for GCC 4.3
+
+* Wed Jan  9 2008 Miloslav Trmač <mitr@redhat.com> - 0.56.7-1
+- Add support for SHA256 and SHA512 in password hashes
+  Related: #173583
+- Fix file locking on some architectures
+- Rename sr@Latn.po to sr@latin.po
+  Resolves: #426584
+- Address issues from a review by Jason Tibbitts:
+  - Remove default.-c, moving the provided functions to libuser proper
+  - Remove the WITH_SELINUX build option
+  - Move Python library test to %%check
+  Resolves: #226054
+
+* Mon Jan 07 2008 Jason L Tibbitts III <tibbs@math.uh.edu> - 0.56.6-4
+- Add the usual "there is no upstream" notice.
+
+* Tue Dec 04 2007 Release Engineering <rel-eng at fedoraproject dot org> - 0.56.6-4
+ - Rebuild for openldap bump
+
+* Tue Dec  4 2007 Miloslav Trmač <mitr@redhat.com> - 0.56.6-3
+- Rebuild with openldap-2.4.
+
+* Wed Oct 31 2007 Miloslav Trmač <mitr@redhat.com> - 0.56.6-2
+- Fix uninitialized memory usage when SELinux is disabled
+
+* Thu Oct 25 2007 Miloslav Trmač <mitr@redhat.com> - 0.56.6-1
+- Set SELinux file contexts when creating home directories, preserve them when
+  moving home directories
+  Resolves: #351201
+
+* Thu Oct 11 2007 Miloslav Trmač <mitr@redhat.com> - 0.56.5-1
+- Work around spurious error messages when run against the Fedora Directory
+  server
+- Fix error reporting when creating home directories and creating/removing mail
+  spool files
+  Resolves: #318121
+
+* Wed Sep  5 2007 Miloslav Trmač <mitr@redhat.com> - 0.56.4-3
+- s/popt/popt-devel/ in BuildRequires
+  Resolves: #277541
+
+* Wed Aug  8 2007 Miloslav Trmač <mitr@redhat.com> - 0.56.4-2
+- Split the Python module to a separate subpackage (original patch by Yanko
+  Kaneti)
+- Update the License: tag
+
+* Fri Jun 15 2007 Miloslav Trmač <mitr@redhat.com> - 0.56.4-1
+- Update the last password change date field when changing passwords
+  Resolves: #243854
+
+* Sat Jun  9 2007 Miloslav Trmač <mitr@redhat.com> - 0.56.3-1
+- Allow specifying a SASL mechanism (original patch by Simo Sorce)
+  Resolves: #240904
+
+* Thu Apr 19 2007 Miloslav Trmac <mitr@redhat.com> - 0.56.2-1
+- New release with updated translations
+
+* Fri Feb 23 2007 Miloslav Trmac <mitr@redhat.com> - 0.56.1-1
+- When changing passwords, only silently ignore know shadow markers, not all
+  invalid hashes
+  Resolves: #225495
+
+* Sat Feb 17 2007 Miloslav Trmac <mitr@redhat.com> - 0.56-1
+- Tighten the API and implementation to avoid corrupting number-like strings;
+  the module interface ABI has changed
+  Resolves: #226976
+
+* Sat Jan  6 2007 Jeremy Katz <katzj@redhat.com> - 0.55-2
+- Fix inconsistent PyObject/PyMem usage (#220679)
+
+* Sun Dec 10 2006 Miloslav Trmac <mitr@redhat.com> - 0.55-1
+- Update to support the 64-bit API of Python 2.5
+- Drop the quota library and Python module
+
+* Thu Dec  7 2006 Jeremy Katz <katzj@redhat.com> - 0.54.8-2
+- rebuild against python2.5
+- follow python packaging guidelines
+
+* Thu Nov  2 2006 Miloslav Trmac <mitr@redhat.com> - 0.54.8-1
+- Add importing of HOME from default/useradd
+  Related: #204707
+
+* Sun Oct 01 2006 Jesse Keating <jkeating@redhat.com> - 0.54.7-2
+- rebuilt for unwind info generation, broken in gcc-4.1.1-21
+
+* Mon Sep 25 2006 Miloslav Trmac <mitr@redhat.com> - 0.54.7-1
+- New release with updated translations
+
+* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 0.54.6-2.1
+- rebuild
+
+* Wed Jun  7 2006 Miloslav Trmac <mitr@redhat.com> - 0.54.6-2
+- Configure without --enable-gtk-doc to fix multilib conflict (#192715)
+
+* Mon May  1 2006 Miloslav Trmac <mitr@redhat.com> - 0.54.6-1
+- Fix bugs in handling of invalid lines in the files and shadow modules
+- Fix pattern matching in lu_*_enumerate_full in the files and shadow modules
+- Add more error reporting, return non-zero exit status on error from utils
+- Use the skeleton directory specified in libuser.conf by Python
+  admin.createHome and admin.addUser, add parameter skeleton= to admin.addUser
+  (#189984)
+
+* Tue Feb 21 2006 Miloslav Trmac <mitr@redhat.com> - 0.54.5-1
+- Fix multilib conflict on libuser.conf.5
+
+* Mon Feb 13 2006 Miloslav Trmac <mitr@redhat.com> - 0.54.4-1
+- New release with updated translations
+
+* Fri Feb 10 2006 Jesse Keating <jkeating@redhat.com> - 0.54.3-1.2.1
+- bump again for double-long bug on ppc(64)
+
+* Tue Feb 07 2006 Jesse Keating <jkeating@redhat.com> - 0.54.3-1.2
+- rebuilt for new gcc4.1 snapshot and glibc changes
+
+* Fri Dec 09 2005 Jesse Keating <jkeating@redhat.com>
+- rebuilt
+
+* Fri Dec  2 2005 Miloslav Trmac <mitr@redhat.com> - 0.54.3-1
+- Fix crash in lpasswd when user is not specified (#174801)
+
+* Fri Nov 11 2005 Miloslav Trmac <mitr@redhat.com> - 0.54.2-1
+- Avoid using deprecated openldap functions
+
+* Fri Nov 11 2005 Miloslav Trmac <mitr@redhat.com> - 0.54.1-2
+- Rebuild with newer openldap
+
+* Tue Oct 11 2005 Miloslav Trmac <mitr@redhat.com> - 0.54.1-1
+- Support importing of configuration from shadow-utils (/etc/login.defs and
+  /etc/default/useradd)
+- Add libuser.conf(5) man page
+
+* Wed Oct  5 2005 Matthias Clasen <mclasen@redhat.com> - 0.54-2
+- Use gmodule-no-export in the .pc file
+
+* Tue Sep 13 2005 Miloslav Trmac <mitr@redhat.com> - 0.54-1
+- Make sure attributes with no values can never appear
+- Fix crash in the "files" module when an attribute is missing
+- Use hidden visibility for internal functions, remove them from
+  libuser/user_private.h; this changes module interface ABI
+
+* Wed Jun  8 2005 Miloslav Trmac <mitr@redhat.com> - 0.53.8-1
+- Permit "portable" user and group names as defined by SUSv3, plus trailing $
+  (#159452)
+- Don't build static libraries
+
+* Sat Apr 30 2005 Miloslav Trmac <mitr@redhat.com> - 0.53.7-1
+- Rebuild with updated translations, add missing translations.
+
+* Sun Apr 24 2005 Miloslav Trmac <mitr@redhat.com> - 0.53.6-1
+- Allow empty configuration values (#155402)
+
+* Fri Apr 15 2005 Miloslav Trmac <mitr@redhat.com> - 0.53.5-1
+- Ignore nss_compat lines in the "files" module (#154651)
+- Autodetect Python version (#154096)
+- Add BuildRequires: libselinux-devel, s/BuildPrereq/BuildRequires/
+
+* Wed Apr  6 2005 Miloslav Trmac <mitr@redhat.com> - 0.53.4-1
+- Fix adding objectclasses to existing LDAP entries (#152960)
+
+* Wed Mar 30 2005 Miloslav Trmac <mitr@redhat.com> - 0.53.3-2
+- Add Requires: glib2-devel to libuser-devel (#152501)
+- Run ldconfig using %%post{,un} -p to let RPM play tricks
+
+* Sat Mar  5 2005 Miloslav Trmac <mitr@redhat.com> - 0.53.3-1
+- Don't silently ignore some I/O errors
+- Don't include a Cyrus SASL v1 header file when libldap links to v2 (#150046)
+- Rebuild with gcc 4
+
+* Mon Jan 17 2005 Miloslav Trmac <mitr@redhat.com> - 0.53.2-1
+- Important bug fixes in lchage, lgroupmod, lnewusers and lusermod
+- Minor bug fixes in lpasswd and luseradd
+- Add man pages for the utilities (#61673)
+
+* Mon Dec 13 2004 Miloslav Trmac <mitr@redhat.com> - 0.53.1-1
+- Export UT_NAMESIZE from <utmp.h> to Python (#141273)
+
+* Sun Nov 14 2004 Miloslav Trmac <mitr@redhat.com> - 0.53-1
+- Support UID and GID values larger than LONG_MAX (#124967)
+- Fix updating of groups after user renaming in lusermod
+- Allow setting a shadow password even if the current shadow password is
+  invalid (#131180)
+- Add lu_{user,group}_unlock_nonempty (#86414); module interface ABI has 
+  changed
+- Miscellaneous bug and memory leak fixes
+
+* Mon Nov  8 2004 Jeremy Katz <katzj@redhat.com> - 0.52.6-2
+- rebuild against python 2.4
+
+* Tue Nov  2 2004 Miloslav Trmac <mitr@redhat.com> - 0.52.6-1
+- Make error reporting more consistent, more verbose and always on stderr
+  (partly #133861, original patch by Pawel Salek)
+- Mark strings previously blocked by string freeze for translation
+
+* Tue Oct 12 2004 Miloslav Trmac <mitr@redhat.com> - 0.52.5-1
+- Fix home directory renaming in ADMIN.modifyUser (#135280)
+- Further Python reference counting fixes
+
+* Sun Oct 10 2004 Miloslav Trmac <mitr@redhat.com> - 0.52.4-1
+- Fix memory leaks (#113730)
+- Build with updated translations
+
+* Wed Sep 29 2004 Miloslav Trmac <mitr@redhat.com> - 0.52.3-1
+- Fix compilation without libuser headers already installed (#134085)
+
+* Tue Sep 28 2004 Miloslav Trmac <mitr@redhat.com> - 0.52.2-1
+- Allow LDAP connection using ldaps, custom ports or without TLS (original
+  patch from Pawel Salek).
+
+* Mon Sep 27 2004 Miloslav Trmac <mitr@redhat.com> - 0.52.1-1
+- Fix freecon() of uninitialized value in files/shadow module
+
+* Mon Sep 27 2004 Miloslav Trmac <mitr@redhat.com> - 0.52-1
+- Usable LDAP backend (#68052, #99435, #130404)
+- Miscellaneous bug fixes
+
+* Fri Sep 24 2004 Miloslav Trmac <mitr@redhat.com> - 0.51.12-1
+- Don't claim success and exception at the same time (#133479)
+- LDAP fixes, second round
+- Various other bugfixes
+
+* Thu Sep 23 2004 Miloslav Trmac <mitr@redhat.com> - 0.51.11-1
+- Allow documented optional arguments in Python
+  ADMIN.{addUser,modifyUser,deleteUser} (#119812)
+- Add man pages for lchfn and lchsh
+- LDAP fixes, first round
+- Avoid file conflict on multilib systems
+- Call ldconfig correctly
+
+* Fri Sep  3 2004 Miloslav Trmac <mitr@redhat.com> - 0.51.10-1
+- Don't attempt to lookup using original entity name after entity
+  modification (rename in particular) (#78376, #121252)
+- Fix copying of symlinks from /etc/skel (#87572, original patch from gLaNDix)
+- Make --enable-quota work, and fix the quota code to at least compile (#89114)
+- Fix several bugs (#120168, original patch from Steve Grubb)
+- Don't hardcode python version in spec file (#130952, from Robert Scheck)
+- Properly integrate the SELinux patch, it should actually be used now, even
+  though it was "enabled" since 0.51.7-6
+
+* Tue Aug 31 2004 Miloslav Trmac <mitr@redhat.com> - 0.51.9-1
+- Fix various typos
+- Document library interfaces
+- Build all shared libraries with -fPIC (#72536)
+
+* Wed Aug 25 2004 Miloslav Trmac <mitr@redhat.com> - 0.51.8-1
+- Update to build with latest autotools and gtk-doc
+- Update ALL_LINGUAS and POTFILES.in
+- Rebuild to depend on newer openldap
+
+* Mon Jan 26 2004 Dan Walsh <dwalsh@redhat.com> 0.51.7-7
+- fix is_selinux_enabled call
+
+* Sun Dec 14 2003 Jeremy Katz <katzj@redhat.com> 0.51.7-6
+- rebuild against python 2.3
+- enable SELinux
+
+* Mon Sep 08 2003 Dan Walsh <dwalsh@redhat.com> 0.51.7-5
+- Turn off SELinux 
+
+* Wed Aug 06 2003 Dan Walsh <dwalsh@redhat.com> 0.51.7-3
+- Add SELinux support
+
+* Wed Feb 19 2003 Nalin Dahyabhai <nalin@redhat.com> 0.51.7-1
+- ldap: set error codes correctly when we encounter failures initializing
+- don't double-close modules which fail initialization
+- ldap: don't set an error in cases where one is already set
+
+* Tue Feb 18 2003 Nalin Dahyabhai <nalin@redhat.com> 0.51.6-1
+- use a crypt salt consistent with the defaults/crypt_style setting when
+  setting new passwords (#79337)
+
+* Thu Feb  6 2003 Nalin Dahyabhai <nalin@redhat.com> 0.51.5-2
+- rebuild
+
+* Wed Feb  5 2003 Nalin Dahyabhai <nalin@redhat.com> 0.51.5-1
+- expose lu_get_first_unused_id() as a package-private function
+- provide libuser.ADMIN.getFirstUnusedUid and libuser.ADMIN.getFirstUnusedGid
+  in python
+
+* Thu Dec 19 2002 Nalin Dahyabhai <nalin@redhat.com> 0.51.4-1
+- fix not freeing resources properly in files.c(generic_is_locked), spotted by
+  Zou Pengcheng
+
+* Wed Dec 11 2002 Nalin Dahyabhai <nalin@redhat.com> 0.51.2-1
+- degrade gracefully
+- build with --with-pic and -fPIC
+- remove unpackaged man page
+
+* Tue Aug 27 2002 Nalin Dahyabhai <nalin@redhat.com> 0.51.1-2
+- translation updates
+
+* Wed Jul 24 2002 Nalin Dahyabhai <nalin@redhat.com> 0.51.1-1
+- doc updates -- cvs tree moved
+- language updates
+- disallow weird characters in account names
+
+* Sun May 26 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Mon May 20 2002 Nalin Dahyabhai <nalin@redhat.com> 0.51-1
+- files: ignore blank lines in files
+- libuser: disallow creation of accounts with names containing whitespace,
+  control characters, or non-ASCII characters
+
+* Tue Apr 16 2002 Nalin Dahyabhai <nalin@redhat.com> 0.50.2-1
+- refresh translations
+- fix a heap-corruption bug in the python bindings
+
+* Mon Apr 15 2002 Nalin Dahyabhai <nalin@redhat.com> 0.50-1
+- bump version
+- refresh translations
+
+* Thu Mar 14 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.102-1
+- ldap: cache an entity's dn in the entity structure to try to speed things up
+
+* Mon Mar 11 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.101-3
+- rebuild in new environment
+
+* Thu Mar  7 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.101-2
+- add missing buildreqs on cyrus-sasl-devel and openldap-devel (#59456)
+- translation refresh
+
+* Fri Mar  1 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.101-1
+- fix python bindings of enumerateFull functions
+- adjust prompter wrapping to not error out on successful returns
+
+* Thu Feb 28 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.100-1
+- be more careful about printing error messages
+- fix refreshing after adding of accounts
+- ldap: try to use a search to convert names to DNs, and only fall back to
+  guessing if it turns up nothing
+- files: fix an off-by-one in removal of entries
+
+* Mon Feb 25 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.99-1
+- refresh translations
+- fix admin() constructor comments in the python module
+
+* Thu Feb 21 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.98-1
+- automatically refresh entities after add, modify, setpass, removepass,
+  lock, and unlock operations
+- remove debug spewage when creating and removing mail spools
+- files: fix saving of multi-valued attributes
+- rename MEMBERUID attribute for groups to MEMBERNAME
+
+* Wed Feb 20 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.97-1
+- files: fix bug in removals
+- ldap: revert attempts at being smart at startup time, because it makes UIs
+  very messy (up the three whole dialogs just to start the ldap stuff!)
+
+* Sat Feb 16 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.96-1
+- fix thinko in dispatch routines
+
+* Wed Feb 13 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.95-1
+- lgroupmod: fix thinko
+
+* Thu Jan 31 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.94-2
+- rebuild in new environment
+
+* Tue Jan 29 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.93-1
+- move shadow initialization for groups to the proper callback
+- rework locking in the files module to not require that files be writable
+
+* Tue Jan 29 2002 Nalin Dahyabhai <nalin@redhat.com>
+- expose lu_strerror()
+- add various typedefs for types used by the library
+
+* Mon Jan 28 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.92-1
+- add removepass() functions
+
+* Thu Jan 24 2002 Nalin Dahyabhai <nalin@redhat.com>
+- lchfn,lchsh,lpasswd - reorder PAM authentication calls
+- include API docs in the package
+
+* Thu Jan 24 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.91-1
+- ldap: finish port to new API
+- sasl: finish port to new API (needs test)
+- libuser: don't commit object changes before passing data to service
+  functions which might need differing data sets to figure out what to
+  change (for example, ldap)
+
+* Thu Jan 17 2002 Nalin Dahyabhai <nalin@redhat.com> 0.49.90-1
+- bind the internal mail spool creation/removal functions for python
+
+* Wed Jan 16 2002 Nalin Dahyabhai <nalin@redhat.com>
+- renamed the python module
+- revamped internals to use gobject's gvalues and gvaluearrays instead of
+  glists of cached strings
+- add enumeration-with-data functions to the C library
+
+* Mon Jan 07 2002 Florian La Roche <Florian.LaRoche@redhat.de>
+- require linuxdoc-tools instead of sgml-tools for rawhide
+
+* Tue Nov 13 2001 Nalin Dahyabhai <nalin@redhat.com>
+- fixup build files to allow building for arbitrary versions of python
+
+* Wed Aug 29 2001 Nalin Dahyabhai <nalin@redhat.com> 0.32-1
+- link the python module against libpam
+- attempt to import the python modules at build-time to verify dependencies
+
+* Tue Aug 28 2001 Nalin Dahyabhai <nalin@redhat.com> 0.31-1
+- fix a file-parsing bug that popped up in 0.29's mmap modifications
+
+* Mon Aug 27 2001 Nalin Dahyabhai <nalin@redhat.com> 0.30-1
+- quotaq: fix argument order when reading quota information
+- user_quota: set quota grace periods correctly
+- luseradd: never create home directories for system accounts
+
+* Tue Aug 21 2001 Nalin Dahyabhai <nalin@redhat.com>
+- add da translation files
+- update translations
+
+* Tue Aug 21 2001 Nalin Dahyabhai <nalin@redhat.com> 0.29-1
+- add an explicit build dependency on jade (for the docs)
+
+* Mon Aug 20 2001 Nalin Dahyabhai <nalin@redhat.com>
+- HUP nscd on modifications
+- userutil.c: mmap files we're reading for probable speed gain
+- userutil.c: be conservative with the amount of random data we read
+- docs fixes
+
+* Wed Aug 15 2001 Nalin Dahyabhai <nalin@redhat.com> 0.28-1
+- apps: print usage on errors
+- lnewusers.c: initialize groups as groups, not users
+- lnewusers.c: set passwords for new accounts
+- luseradd.c: accept group names in addition to IDs for the -g flag
+- luseradd.c: allow the primary GID to be a preexisting group
+
+* Tue Aug 14 2001 Nalin Dahyabhai <nalin@redhat.com> 0.27-1
+- add ko translation files
+- files.c: fix a heap corruption bug in lock/unlock (#51750)
+- files.c: close a memory leak in reading of files
+
+* Mon Aug 13 2001 Nalin Dahyabhai <nalin@redhat.com>
+- files.c: remove implementation limits on lengths of lines
+
+* Thu Aug  9 2001 Nalin Dahyabhai <nalin@redhat.com> 0.26-1
+- lusermod: change user name in groups the user is a member of during renames
+- lgroupmod: change primary GID for users who are in the group during renumbers
+- ldap.c: handle new attributes more gracefully if possible
+- add ru translation files
+
+* Tue Aug  7 2001 Nalin Dahyabhai <nalin@redhat.com> 0.25.1-1
+- rename the quota source files to match the library, which clears up a
+  file conflict with older quota packages
+- add ja translation files
+
+* Thu Aug  2 2001 Nalin Dahyabhai <nalin@redhat.com>
+- add lu_ent_clear_all() function
+
+* Thu Aug  2 2001 Nalin Dahyabhai <nalin@redhat.com> 0.25-1
+- close up some memory leaks
+- add the ability to include resident versions of modules in the library
+
+* Wed Aug  1 2001 Nalin Dahyabhai <nalin@redhat.com> 0.24-4
+- fix incorrect Py_BuildValue invocation in python module
+
+* Tue Jul 31 2001 Nalin Dahyabhai <nalin@redhat.com> 0.24-3
+- stop leaking descriptors in the files module
+- speed up user creation by reordering some checks for IDs being in use
+- update the shadowLastChanged attribute when we set a password
+- adjust usage of getXXXXX_r where needed
+- fix assorted bugs in python binding which break prompting
+
+* Mon Jul 30 2001 Nalin Dahyabhai <nalin@redhat.com> 0.23-1
+- install sv translation
+- make lpasswd prompt for passwords when none are given on the command line
+- make sure all user-visible strings are marked for translation
+- clean up some user-visible strings
+- require PAM authentication in lchsh, lchfn, and lpasswd for non-networked modules
+
+* Fri Jul 27 2001 Nalin Dahyabhai <nalin@redhat.com>
+- print uids and gids of users and names in lid app
+- fix tree traversal in users_enumerate_by_group and groups_enumerate_by_users
+- implement enumerate_by_group and enumerate_by_user in ldap module
+- fix id-based lookups in the ldap module
+- implement islocked() method in ldap module
+- implement setpass() method in ldap module
+- add lchfn and lchsh apps
+- add %%d substitution to libuser.conf
+
+* Thu Jul 26 2001 Nalin Dahyabhai <nalin@redhat.com> 0.21-1
+- finish adding a sasldb module which manipulates a sasldb file
+- add users_enumerate_by_group and groups_enumerate_by_users
+
+* Wed Jul 25 2001 Nalin Dahyabhai <nalin@redhat.com> 
+- luserdel: remove the user's primary group if it has the same name as
+  the user and has no members configured (-G disables)
+- fixup some configure stuff to make libuser.conf get generated correctly
+  even when execprefix isn't specified
+
+* Tue Jul 24 2001 Nalin Dahyabhai <nalin@redhat.com> 0.20-1
+- only call the auth module when setting passwords (oops)
+- use GTrees instead of GHashTables for most internal tables
+- files: complain properly about unset attributes
+- files: group passwords are single-valued, not multiple-valued
+- add lpasswd app, make sure all apps start up popt with the right names
+
+* Mon Jul 23 2001 Nalin Dahyabhai <nalin@redhat.com> 0.18-1
+- actually make the new optional arguments optional
+- fix lu_error_new() to actually report errors right
+- fix part of the python bindings
+- include tools in the binary package again
+- fixup modules so that password-changing works right again
+- add a "key" field to prompt structures for use by apps which like to
+  cache these things
+- add an optional "mvhomedir" argument to userModify (python)
+
+* Fri Jul 20 2001 Nalin Dahyabhai <nalin@redhat.com> 0.16.1-1
+- finish home directory population
+- implement home directory moving
+- change entity get semantics in the python bindings to allow default values for .get()
+- add lu_ent_has(), and a python has_key() method to Entity types
+- don't include tools in the binary package
+- add translated strings
+
+* Thu Jul 19 2001 Nalin Dahyabhai <nalin@redhat.com>
+- lib/user.c: catch and ignore errors when running stacks
+- lusermod: fix slightly bogus help messages
+- luseradd: when adding a user and group, use the gid of the group
+  instead of the user's uid as the primary group
+- properly set the password field in user accounts created using
+  auth-only auth modules (shadow needs "x" instead of "!!")
+- implement home directory removal, start on population
+
+* Wed Jul 18 2001 Nalin Dahyabhai <nalin@redhat.com>
+- fix group password setting in the files module
+- setpass affects both auth and info, so run both stacks
+
+* Tue Jul 17 2001 Nalin Dahyabhai <nalin@redhat.com>
+- make the testbed apps noinst
+
+* Mon Jul 16 2001 Nalin Dahyabhai <nalin@redhat.com>
+- fix errors due to uninitialized fields in the python bindings
+- add kwargs support to all python wrappers
+- add a mechanism for passing arguments to python callbacks
+
+* Wed Jul 11 2001 Nalin Dahyabhai <nalin@redhat.com>
+- stub out the krb5 and ldap modules so that they'll at least compile again
+ 
+* Tue Jul 10 2001 Nalin Dahyabhai <nalin@redhat.com>
+- don't bail when writing empty fields to colon-delimited files
+- use permissions of the original file when making backup files instead of 0600
+
+* Fri Jul  6 2001 Nalin Dahyabhai <nalin@redhat.com>
+- finish implementing is_locked methods in files/shadow module
+- finish cleanup of the python bindings
+- allow conditional builds of modules so that we can build without
+  all of the prereqs for all of the modules
+
+* Thu Jun 21 2001 Nalin Dahyabhai <nalin@redhat.com>
+- add error reporting facilities
+- split public header into pieces by function
+- backend cleanups
+
+* Mon Jun 18 2001 Nalin Dahyabhai <nalin@redhat.com>
+- make %%{name}-devel require %%{name} and not %%{name}-devel
+
+* Fri Jun 15 2001 Nalin Dahyabhai <nalin@redhat.com>
+- clean up quota bindings some more
+- finish most of the ldap bindings
+- fix a subtle bug in the files module that would show up when renaming accounts
+- fix mapping methods for entity structures in python
+
+* Thu Jun 14 2001 Nalin Dahyabhai <nalin@redhat.com>
+- get bindings for prompts to work correctly
+- clean up some of the add/remove semantics (set source on add)
+- ldap: implement enumeration
+- samples/enum: fix the argument order
+
+* Wed Jun 13 2001 Nalin Dahyabhai <nalin@redhat.com>
+- clean up python bindings for quota
+
+* Tue Jun 12 2001 Nalin Dahyabhai <nalin@redhat.com> 0.11
+- finish up python bindings for quota support
+
+* Sun Jun 10 2001 Nalin Dahyabhai <nalin@redhat.com>
+- finish up quota support libs
+
+* Fri Jun  8 2001 Nalin Dahyabhai <nalin@redhat.com>
+- start quota support library to get some type safety
+
+* Thu Jun  7 2001 Nalin Dahyabhai <nalin@redhat.com>
+- start looking at quota manipulation
+
+* Wed Jun  6 2001 Nalin Dahyabhai <nalin@redhat.com>
+- add functions for enumerating users and groups, optionally per-module
+- lusermod.c: -s should specify the shell, not the home directory
+
+* Fri Jun  1 2001 Nalin Dahyabhai <nalin@redhat.com> 0.10
+- finish the python bindings and verify that the file backend works again
+
+* Wed May 30 2001 Nalin Dahyabhai <nalin@redhat.com>
+- remove a redundant check which was breaking modifications
+
+* Tue May 29 2001 Nalin Dahyabhai <nalin@redhat.com>
+- finish adding setpass methods
+
+* Wed May  2 2001 Nalin Dahyabhai <nalin@redhat.com> 0.9
+- get a start on some Python bindings
+
+* Tue May  1 2001 Nalin Dahyabhai <nalin@redhat.com> 0.8.2
+- make binary-incompatible change in headers
+
+* Mon Apr 30 2001 Nalin Dahyabhai <nalin@redhat.com> 0.8.1
+- add doxygen docs and a "doc" target for them
+
+* Sat Jan 20 2001 Nalin Dahyabhai <nalin@redhat.com> 0.8
+- add a "quiet" prompter
+- add --interactive flag to sample apps and default to using quiet prompter
+- ldap: attempt a "self" bind if other attempts fail
+- krb5: connect to the password-changing service if the user principal has
+  the NULL instance
+
+* Wed Jan 10 2001 Nalin Dahyabhai <nalin@redhat.com>
+- the great adding-of-the-copyright-statements
+- take more care when creating backup files in the files module
+
+* Wed Jan  3 2001 Nalin Dahyabhai <nalin@redhat.com> 0.7
+- add openldap-devel as a buildprereq
+- krb5: use a continuous connection
+- krb5: add "realm" config directive
+- ldap: use a continuous connection
+- ldap: add "server", "basedn", "binddn", "user", "authuser" config directives
+- ldap: actually finish the account deletion function
+- ldap: don't send cleartext passwords to the directory
+- fix naming attribute for users (should be uid, not gid)
+- refine the search-by-id,convert-to-name,search-by-name logic
+- fix handling of defaults when the config file is read in but contains no value
+- implement an LDAP information store
+- try to clean up module naming with libtool
+- luseradd: pass plaintext passwords along
+- luseradd: use symbolic attribute names instead of hard-coded
+- lusermod: pass plaintext passwords along
+- lgroupadd: pass plaintext passwords along
+- lgroupmod: pass plaintext passwords along
+- add libuser as a dependency of libuser-devel
+
+* Tue Jan  2 2001 Nalin Dahyabhai <nalin@redhat.com> 0.6
+- initial packaging