Always preserve GID and UID, always reconstruct field list.
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Sat, 19 Oct 2013 19:55:18 +0000 (21:55 +0200)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Sat, 19 Oct 2013 19:55:18 +0000 (21:55 +0200)
src/VfsAuthn.cpp
src/VfsAuthn.h

index 057bb61..33656fb 100644 (file)
@@ -222,7 +222,7 @@ void VfsAuthn::updateGroup(const GroupInfo& group) throw (DmException)
   // update local set of GIDs if needed
   gid = this->groups_[i].getUnsigned("gid");
   newGid = group.getUnsigned("gid");
-  if (gid != newGid) {
+  if (group.hasField("gid") && gid != newGid) {
     this->gids_.erase(gid);
     //not needed immediately: if (this->nextGid_ > gid) this->nextGid_ = gid;
   }
@@ -231,6 +231,8 @@ void VfsAuthn::updateGroup(const GroupInfo& group) throw (DmException)
   debug("update group '%s', gid %u", group.name.c_str(), gid);
   this->groups_[i].clear();
   this->groups_[i].copy(group);
+  if (!group.hasField("gid"))
+    this->groups_[i]["gid"] = gid;
   this->dirtyGroups_ = true;
 
   // save
@@ -348,7 +350,7 @@ void VfsAuthn::updateUser(const UserInfo& user) throw (DmException)
   // update local set of UIDs if needed
   uid = this->users_[i].getUnsigned("uid");
   newUid = user.getUnsigned("uid");
-  if (uid != newUid) {
+  if (user.hasField("uid") && uid != newUid) {
     this->uids_.erase(uid);
     //not needed immediately: if (this->nextUid_ > uid) this->nextUid_ = uid;
   }
@@ -357,6 +359,8 @@ void VfsAuthn::updateUser(const UserInfo& user) throw (DmException)
   debug("update user '%s', uid %u", user.name.c_str(), uid);
   this->users_[i].clear();
   this->users_[i].copy(user);
+  if (!user.hasField("uid"))
+    this->users_[i]["uid"] = uid;
   this->dirtyUsers_ = true;
 
   // save
@@ -412,11 +416,13 @@ static void csv_groups_load_entry(void *ctx, const Extensible& values) {
 
 
 void VfsAuthn::vfsLoad() throw (DmException) {
+  std::set<std::string> userFields, groupFields;
+
   // users
   this->users_.clear();
   this->uids_.clear();
   try {
-    csvLoad(VFS_USERS_FILE, (void *)&this->users_, this->userFields_, csv_users_load_entry);
+    csvLoad(VFS_USERS_FILE, (void *)&this->users_, userFields, csv_users_load_entry);
   } catch (DmException& e) {
     switch (e.code()) {
       case DMLITE_SYSERR(EIO):
@@ -433,7 +439,7 @@ void VfsAuthn::vfsLoad() throw (DmException) {
   this->groups_.clear();
   this->gids_.clear();
   try {
-    csvLoad(VFS_GROUPS_FILE, (void *)&this->groups_, this->groupFields_, csv_groups_load_entry);
+    csvLoad(VFS_GROUPS_FILE, (void *)&this->groups_, groupFields, csv_groups_load_entry);
   } catch (DmException& e) {
     switch (e.code()) {
       case DMLITE_SYSERR(EIO):
@@ -464,13 +470,19 @@ static bool csv_users_save_entry(void *ctx, size_t n, Extensible& values) {
 
 
 void VfsAuthn::vfsSaveUsers() throw (DmException) {
+  std::set<std::string> fields;
+
   if (this->noSync_) {
     this->dirtyUsers_ = true;
     return;
   }
 
+  // construct list of used fields
+  for (size_t i = 0; i < users_.size(); i++)
+    vfsRefreshFields(users_[i], fields);
+
   try {
-    csvSave(VFS_USERS_FILE, (void *)&this->users_, this->userFields_, csv_users_save_entry);
+    csvSave(VFS_USERS_FILE, (void *)&this->users_, fields, csv_users_save_entry);
   } catch (DmException& e) {
     log(LOG_NOTICE, "could not create new version of users file in '%s'", this->prefix_.c_str());
     this->dirtyUsers_ = true;
@@ -497,13 +509,19 @@ static bool csv_groups_save_entry(void *ctx, size_t n, Extensible& values) {
 
 
 void VfsAuthn::vfsSaveGroups() throw (DmException) {
+  std::set<std::string> fields;
+
   if (this->noSync_) {
     this->dirtyGroups_ = true;
     return;
   }
 
+  // construct list of used fields
+  for (size_t i = 0; i < groups_.size(); i++)
+    vfsRefreshFields(groups_[i], fields);
+
   try {
-    csvSave(VFS_GROUPS_FILE, (void *)&this->groups_, this->groupFields_, csv_groups_save_entry);
+    csvSave(VFS_GROUPS_FILE, (void *)&this->groups_, fields, csv_groups_save_entry);
   } catch (DmException& e) {
     log(LOG_NOTICE, "could not create new version of groups file in '%s'", this->prefix_.c_str());
     this->dirtyGroups_ = true;
@@ -617,10 +635,12 @@ void VfsAuthn::csvSave(std::string fileName, void *ctx, std::set<std::string>& k
 
 
 ///
-/// Helper function to check field names and contents in Extensible.
+/// Helper function to check field names and contents in Extensible. Also update the fields set.
+///
 /// @param entity Entity ("user", "group")
 /// @param name   User/group name
 /// @param data   Checked data
+/// @param fields Fields set to update
 //
 void VfsAuthn::vfsCheckInfo(const std::string& entity, const std::string& name, const Extensible data) throw (DmException) {
   std::vector<std::string> keys;
@@ -633,3 +653,14 @@ void VfsAuthn::vfsCheckInfo(const std::string& entity, const std::string& name,
       vfsThrow(DMLITE_SYSERR(EINVAL), "forbidden characters in %s data (user '%s', field '%s')", entity.c_str(), name.c_str(), keys[i].c_str());
   }
 }
+
+
+
+void VfsAuthn::vfsRefreshFields(const Extensible& data, std::set<std::string>& fields) {
+  std::vector<std::string> keys;
+
+  keys = data.getKeys();
+  for (size_t i = 0; i < keys.size(); i++) {
+    fields.insert(keys[i]);
+  }
+}
index 7b9ca6a..82dc7b7 100644 (file)
@@ -44,6 +44,7 @@ namespace dmlite {
       void vfsSaveGroups() throw (DmException);
       void vfsSaveUsers() throw (DmException);
       void vfsCheckInfo(const std::string& entity, const std::string& name, const Extensible data) throw (DmException);
+      void vfsRefreshFields(const Extensible& data, std::set<std::string>& fields);
       void csvLoad(std::string fileName, void *ctx, std::set<std::string>& keys, csv_load_entry_f *callback) throw (DmException);
       void csvSave(std::string fileName, void *ctx, std::set<std::string>& keys, csv_save_entry_f *callback) throw (DmException);
 
@@ -51,7 +52,6 @@ namespace dmlite {
       std::vector<UserInfo> users_;
       std::vector<GroupInfo> groups_;
       std::set<unsigned int> uids_, gids_;   /// helper sets with UID/GID
-      std::set<std::string> userFields_, groupFields_; /// all fields used in user/group info
       unsigned int nextUid_, nextGid_;       /// next UID/GID after the one last inserted
       bool noSync_;                          /// saving users/groups disabled
       bool dirtyUsers_, dirtyGroups_;        /// data needed to be saved