xref: /DragonOS/user/apps/user-manage/src/executor/executor.rs (revision 59a6bcf6aee15a11a16431bdf875905c5ecf9157)
1 use crate::{
2     check::info::{GAddInfo, GDelInfo, GModInfo, PasswdInfo, UAddInfo, UDelInfo, UModInfo},
3     error::error::{ErrorHandler, ExitStatus},
4 };
5 use lazy_static::lazy_static;
6 use std::{
7     fs::{self, File, OpenOptions},
8     io::{Read, Seek, Write},
9     sync::Mutex,
10 };
11 
12 lazy_static! {
13     static ref GLOBAL_FILE: Mutex<GlobalFile> = Mutex::new(GlobalFile::new());
14 }
15 
16 #[derive(Debug)]
17 pub struct GlobalFile {
18     passwd_file: File,
19     shadow_file: File,
20     group_file: File,
21     gshadow_file: File,
22 }
23 
24 impl GlobalFile {
25     pub fn new() -> Self {
26         let passwd = open_file("/etc/passwd");
27         let shadow = open_file("/etc/shadow");
28         let group = open_file("/etc/group");
29         let gshadow = open_file("/etc/gshadow");
30         Self {
31             passwd_file: passwd,
32             shadow_file: shadow,
33             group_file: group,
34             gshadow_file: gshadow,
35         }
36     }
37 }
38 
39 fn open_file(file_path: &str) -> File {
40     let r = OpenOptions::new()
41         .read(true)
42         .write(true)
43         .append(true)
44         .open(file_path);
45 
46     let exit_status = match file_path {
47         "/etc/group" => ExitStatus::GroupFile,
48         "/etc/gshadow" => ExitStatus::GshadowFile,
49         "/etc/passwd" => ExitStatus::PasswdFile,
50         "/etc/shadow" => ExitStatus::ShadowFile,
51         _ => ExitStatus::InvalidArg,
52     };
53 
54     if r.is_err() {
55         ErrorHandler::error_handle(format!("Can't open file: {}", file_path), exit_status);
56     }
57 
58     r.unwrap()
59 }
60 
61 /// useradd执行器
62 pub struct UAddExecutor;
63 
64 impl UAddExecutor {
65     /// **执行useradd**
66     ///
67     /// ## 参数
68     /// - `info`: 用户信息
69     pub fn execute(info: UAddInfo) {
70         // 创建用户home目录
71         let home = info.home_dir.clone();
72         let dir_builder = fs::DirBuilder::new();
73         if dir_builder.create(home.clone()).is_err() {
74             ErrorHandler::error_handle(
75                 format!("unable to create {}", home),
76                 ExitStatus::CreateHomeFail,
77             );
78         }
79 
80         Self::write_passwd_file(&info);
81         Self::write_shadow_file(&info);
82         Self::write_group_file(&info);
83         Self::write_gshadow_file(&info);
84     }
85 
86     /// 写入/etc/passwd文件:添加用户信息
87     fn write_passwd_file(info: &UAddInfo) {
88         let userinfo: String = info.clone().into();
89         GLOBAL_FILE
90             .lock()
91             .unwrap()
92             .passwd_file
93             .write_all(userinfo.as_bytes())
94             .unwrap();
95     }
96 
97     /// 写入/etc/group文件:将用户添加到对应用户组中
98     fn write_group_file(info: &UAddInfo) {
99         if info.group == info.username {
100             return;
101         }
102 
103         let mut guard = GLOBAL_FILE.lock().unwrap();
104         let content = read_to_string(&guard.group_file);
105         let mut new_content = String::new();
106         for line in content.lines() {
107             let mut field = line.split(":").collect::<Vec<&str>>();
108             let mut users = field.last().unwrap().split(",").collect::<Vec<&str>>();
109             users = users
110                 .into_iter()
111                 .filter(|username| !username.is_empty())
112                 .collect::<Vec<&str>>();
113             if field[0].eq(info.group.as_str()) && !users.contains(&info.username.as_str()) {
114                 users.push(info.username.as_str());
115             }
116 
117             let new_users = users.join(",");
118             field[3] = new_users.as_str();
119             new_content.push_str(format!("{}\n", field.join(":")).as_str());
120         }
121 
122         guard.group_file.set_len(0).unwrap();
123         guard.group_file.seek(std::io::SeekFrom::Start(0)).unwrap();
124         guard.group_file.write_all(new_content.as_bytes()).unwrap();
125         guard.group_file.flush().unwrap();
126     }
127 
128     /// 写入/etc/shadow文件:添加用户口令相关信息
129     fn write_shadow_file(info: &UAddInfo) {
130         let data = format!("{}::::::::\n", info.username,);
131         GLOBAL_FILE
132             .lock()
133             .unwrap()
134             .shadow_file
135             .write_all(data.as_bytes())
136             .unwrap();
137     }
138 
139     /// 写入/etc/gshadow文件:将用户添加到对应用户组中
140     fn write_gshadow_file(info: &UAddInfo) {
141         if info.group == info.username {
142             return;
143         }
144 
145         let mut guard = GLOBAL_FILE.lock().unwrap();
146         let content = read_to_string(&guard.gshadow_file);
147         let mut new_content = String::new();
148         for line in content.lines() {
149             let mut field = line.split(":").collect::<Vec<&str>>();
150             let mut users = field.last().unwrap().split(",").collect::<Vec<&str>>();
151             users = users
152                 .into_iter()
153                 .filter(|username| !username.is_empty())
154                 .collect::<Vec<&str>>();
155             if field[0].eq(info.group.as_str()) && !users.contains(&info.username.as_str()) {
156                 users.push(info.username.as_str());
157             }
158 
159             let new_users = users.join(",");
160             field[3] = new_users.as_str();
161             new_content.push_str(format!("{}\n", field.join(":")).as_str());
162         }
163         guard.gshadow_file.set_len(0).unwrap();
164         guard
165             .gshadow_file
166             .seek(std::io::SeekFrom::Start(0))
167             .unwrap();
168         guard
169             .gshadow_file
170             .write_all(new_content.as_bytes())
171             .unwrap();
172         guard.gshadow_file.flush().unwrap();
173     }
174 }
175 
176 /// userdel执行器
177 pub struct UDelExecutor;
178 
179 impl UDelExecutor {
180     /// **执行userdel**
181     ///
182     /// ## 参数
183     /// - `info`: 用户信息
184     pub fn execute(info: UDelInfo) {
185         // 移除home目录
186         if let Some(home) = info.home.clone() {
187             std::fs::remove_dir_all(home).unwrap();
188         }
189 
190         Self::update_passwd_file(&info);
191         Self::update_shadow_file(&info);
192         Self::update_group_file(&info);
193         Self::update_gshadow_file(&info);
194     }
195 
196     /// 更新/etc/passwd文件: 删除用户信息
197     fn update_passwd_file(info: &UDelInfo) {
198         let mut guard = GLOBAL_FILE.lock().unwrap();
199         let content = read_to_string(&guard.passwd_file);
200         let lines: Vec<&str> = content.lines().collect();
201         let new_content = lines
202             .into_iter()
203             .filter(|&line| {
204                 let field = line.split(':').collect::<Vec<&str>>();
205                 field[0] != info.username.as_str()
206             })
207             .collect::<Vec<&str>>()
208             .join("\n");
209 
210         guard.passwd_file.set_len(0).unwrap();
211         guard.passwd_file.seek(std::io::SeekFrom::Start(0)).unwrap();
212         guard.passwd_file.write_all(new_content.as_bytes()).unwrap();
213         guard.passwd_file.flush().unwrap();
214     }
215 
216     /// 更新/etc/group文件: 将用户从组中移除
217     fn update_group_file(info: &UDelInfo) {
218         let mut guard = GLOBAL_FILE.lock().unwrap();
219         let content = read_to_string(&guard.group_file);
220         let mut new_content = String::new();
221         for line in content.lines() {
222             let mut field = line.split(':').collect::<Vec<&str>>();
223             let mut users = field.last().unwrap().split(",").collect::<Vec<&str>>();
224             if users.contains(&info.username.as_str()) {
225                 field.remove(field.len() - 1);
226                 users.remove(
227                     users
228                         .iter()
229                         .position(|&x| x == info.username.as_str())
230                         .unwrap(),
231                 );
232                 let users = users.join(",");
233                 field.push(&users.as_str());
234                 new_content.push_str(format!("{}\n", field.join(":").as_str()).as_str());
235             } else {
236                 new_content.push_str(format!("{}\n", field.join(":").as_str()).as_str());
237             }
238 
239             guard.group_file.set_len(0).unwrap();
240             guard.group_file.seek(std::io::SeekFrom::Start(0)).unwrap();
241             guard.group_file.write_all(new_content.as_bytes()).unwrap();
242             guard.group_file.flush().unwrap();
243         }
244     }
245 
246     /// 更新/etc/shadow文件: 将用户信息删去
247     fn update_shadow_file(info: &UDelInfo) {
248         let mut guard = GLOBAL_FILE.lock().unwrap();
249         let content = read_to_string(&guard.shadow_file);
250         let lines: Vec<&str> = content.lines().collect();
251         let new_content = lines
252             .into_iter()
253             .filter(|&line| !line.contains(&info.username))
254             .collect::<Vec<&str>>()
255             .join("\n");
256 
257         guard.shadow_file.set_len(0).unwrap();
258         guard.shadow_file.seek(std::io::SeekFrom::Start(0)).unwrap();
259         guard.shadow_file.write_all(new_content.as_bytes()).unwrap();
260         guard.shadow_file.flush().unwrap();
261     }
262 
263     /// 更新/etc/gshadow文件: 将用户从组中移除
264     fn update_gshadow_file(info: &UDelInfo) {
265         let mut guard = GLOBAL_FILE.lock().unwrap();
266         let content = read_to_string(&guard.gshadow_file);
267         let mut new_content = String::new();
268         for line in content.lines() {
269             let mut field = line.split(':').collect::<Vec<&str>>();
270             let mut users = field.last().unwrap().split(",").collect::<Vec<&str>>();
271             if users.contains(&info.username.as_str()) {
272                 field.remove(field.len() - 1);
273                 users.remove(
274                     users
275                         .iter()
276                         .position(|&x| x == info.username.as_str())
277                         .unwrap(),
278                 );
279                 let users = users.join(",");
280                 field.push(&users.as_str());
281                 new_content.push_str(format!("{}\n", field.join(":").as_str()).as_str());
282             } else {
283                 new_content.push_str(format!("{}\n", field.join(":").as_str()).as_str());
284             }
285 
286             guard.gshadow_file.set_len(0).unwrap();
287             guard
288                 .gshadow_file
289                 .seek(std::io::SeekFrom::Start(0))
290                 .unwrap();
291             guard
292                 .gshadow_file
293                 .write_all(new_content.as_bytes())
294                 .unwrap();
295             guard.gshadow_file.flush().unwrap();
296         }
297     }
298 }
299 
300 /// usermod执行器
301 pub struct UModExecutor;
302 
303 impl UModExecutor {
304     /// **执行usermod**
305     ///
306     /// ## 参数
307     /// - `info`: 用户信息
308     pub fn execute(mut info: UModInfo) {
309         // 创建new_home
310         if let Some(new_home) = &info.new_home {
311             let dir_builder = fs::DirBuilder::new();
312             if dir_builder.create(new_home.clone()).is_err() {
313                 ErrorHandler::error_handle(
314                     format!("unable to create {}", new_home),
315                     ExitStatus::CreateHomeFail,
316                 );
317             }
318         }
319 
320         Self::update_passwd_file(&info);
321         Self::update_shadow_file(&info);
322         Self::update_group_file(&mut info);
323         Self::update_gshadow_file(&info);
324     }
325 
326     /// 更新/etc/passwd文件的username、uid、comment、home、shell
327     fn update_passwd_file(info: &UModInfo) {
328         let mut new_content = String::new();
329         let mut guard = GLOBAL_FILE.lock().unwrap();
330         let content = read_to_string(&guard.passwd_file);
331         for line in content.lines() {
332             let mut fields = line.split(':').collect::<Vec<&str>>();
333             if fields[0] == info.username {
334                 if let Some(new_username) = &info.new_name {
335                     fields[0] = new_username;
336                 }
337                 if let Some(new_uid) = &info.new_uid {
338                     fields[2] = new_uid;
339                 }
340                 if let Some(new_gid) = &info.new_gid {
341                     fields[3] = new_gid;
342                 }
343                 if let Some(new_comment) = &info.new_comment {
344                     fields[4] = new_comment;
345                 }
346                 if let Some(new_home) = &info.new_home {
347                     fields[5] = new_home;
348                 }
349                 if let Some(new_shell) = &info.new_shell {
350                     fields[6] = new_shell;
351                 }
352                 new_content.push_str(format!("{}\n", fields.join(":")).as_str());
353             } else {
354                 new_content.push_str(format!("{}\n", line).as_str());
355             }
356 
357             guard.passwd_file.set_len(0).unwrap();
358             guard.passwd_file.seek(std::io::SeekFrom::Start(0)).unwrap();
359             guard.passwd_file.write_all(new_content.as_bytes()).unwrap();
360             guard.passwd_file.flush().unwrap();
361         }
362     }
363 
364     /// 更新/etc/group文件中各用户组中的用户
365     fn update_group_file(info: &mut UModInfo) {
366         let mut name = info.username.clone();
367         if let Some(new_name) = &info.new_name {
368             name = new_name.clone();
369         }
370         let mut new_content = String::new();
371         let mut guard = GLOBAL_FILE.lock().unwrap();
372         let content = read_to_string(&guard.group_file);
373         for line in content.lines() {
374             let mut fields = line.split(':').collect::<Vec<&str>>();
375             let mut users = fields[3].split(",").collect::<Vec<&str>>();
376             users = users
377                 .into_iter()
378                 .filter(|username| !username.is_empty())
379                 .collect::<Vec<&str>>();
380             if let Some(idx) = users.iter().position(|&r| r == info.username) {
381                 if let Some(gid) = &info.new_gid {
382                     // 换组,将用户从当前组删去
383                     if gid != fields[2] {
384                         users.remove(idx);
385                     } else {
386                         info.new_group = Some(fields[0].to_string())
387                     }
388                 } else {
389                     // 不换组但是要更新名字
390                     users[idx] = &name;
391                 }
392             }
393 
394             if let Some(groups) = &info.groups {
395                 if groups.contains(&fields[0].to_string()) && !users.contains(&name.as_str()) {
396                     users.push(&name);
397                 }
398             }
399 
400             let new_users = users.join(",");
401             fields[3] = new_users.as_str();
402             new_content.push_str(format!("{}\n", fields.join(":")).as_str());
403         }
404 
405         guard.group_file.set_len(0).unwrap();
406         guard.group_file.seek(std::io::SeekFrom::Start(0)).unwrap();
407         guard.group_file.write_all(new_content.as_bytes()).unwrap();
408         guard.group_file.flush().unwrap();
409     }
410 
411     /// 更新/etc/shadow文件的username
412     fn update_shadow_file(info: &UModInfo) {
413         if let Some(new_name) = &info.new_name {
414             let mut new_content = String::new();
415             let mut guard = GLOBAL_FILE.lock().unwrap();
416             let content = read_to_string(&guard.shadow_file);
417             for line in content.lines() {
418                 let mut fields = line.split(':').collect::<Vec<&str>>();
419                 if fields[0] == info.username {
420                     fields[0] = new_name;
421                     new_content.push_str(format!("{}\n", fields.join(":")).as_str());
422                 } else {
423                     new_content.push_str(format!("{}\n", line).as_str());
424                 }
425             }
426 
427             guard.shadow_file.set_len(0).unwrap();
428             guard.shadow_file.seek(std::io::SeekFrom::Start(0)).unwrap();
429             guard.shadow_file.write_all(new_content.as_bytes()).unwrap();
430             guard.shadow_file.flush().unwrap();
431         }
432     }
433 
434     /// 更新/etc/gshadow文件中各用户组中的用户
435     fn update_gshadow_file(info: &UModInfo) {
436         let mut name = info.username.clone();
437         if let Some(new_name) = &info.new_name {
438             name = new_name.clone();
439         }
440         let mut new_content = String::new();
441         let mut guard = GLOBAL_FILE.lock().unwrap();
442         let content = read_to_string(&guard.gshadow_file);
443         for line in content.lines() {
444             let mut fields = line.split(':').collect::<Vec<&str>>();
445             let mut users = fields[3].split(",").collect::<Vec<&str>>();
446             users = users
447                 .into_iter()
448                 .filter(|username| !username.is_empty())
449                 .collect::<Vec<&str>>();
450             if let Some(idx) = users.iter().position(|&r| r == info.username) {
451                 if let Some(group) = &info.new_group {
452                     // 换组,将用户从当前组删去
453                     if group != fields[0] {
454                         users.remove(idx);
455                     }
456                 } else {
457                     // 不换组但是要更新名字
458                     users[idx] = &name;
459                 }
460             }
461 
462             let tmp = format!(",{}", name);
463             if let Some(groups) = &info.groups {
464                 if groups.contains(&fields[0].to_string()) && !users.contains(&name.as_str()) {
465                     if users.is_empty() {
466                         users.push(&name);
467                     } else {
468                         users.push(tmp.as_str());
469                     }
470                 }
471             }
472 
473             let new_users = users.join(",");
474             fields[3] = new_users.as_str();
475             new_content.push_str(format!("{}\n", fields.join(":")).as_str());
476         }
477 
478         guard.gshadow_file.set_len(0).unwrap();
479         guard
480             .gshadow_file
481             .seek(std::io::SeekFrom::Start(0))
482             .unwrap();
483         guard
484             .gshadow_file
485             .write_all(new_content.as_bytes())
486             .unwrap();
487         guard.gshadow_file.flush().unwrap();
488     }
489 }
490 
491 /// passwd执行器
492 pub struct PasswdExecutor;
493 
494 impl PasswdExecutor {
495     /// **执行passwd**
496     ///
497     /// ## 参数
498     /// - `info`: 用户密码信息
499     pub fn execute(info: PasswdInfo) {
500         Self::update_passwd_file(&info);
501         Self::update_shadow_file(&info);
502     }
503 
504     /// 更新/etc/passwd文件: 修改用户密码
505     fn update_passwd_file(info: &PasswdInfo) {
506         let mut new_content = String::new();
507         let mut guard = GLOBAL_FILE.lock().unwrap();
508         let content = read_to_string(&guard.passwd_file);
509         for line in content.lines() {
510             let mut field = line.split(':').collect::<Vec<_>>();
511             if field[0] == info.username {
512                 if info.new_password.is_empty() {
513                     field[1] = "";
514                 } else {
515                     field[1] = "x";
516                 }
517             }
518             new_content.push_str(format!("{}\n", field.join(":")).as_str());
519         }
520 
521         guard.passwd_file.set_len(0).unwrap();
522         guard.passwd_file.seek(std::io::SeekFrom::Start(0)).unwrap();
523         guard.passwd_file.write_all(new_content.as_bytes()).unwrap();
524         guard.passwd_file.flush().unwrap();
525     }
526 
527     /// 更新/etc/shadow文件: 修改用户密码
528     fn update_shadow_file(info: &PasswdInfo) {
529         let mut new_content = String::new();
530         let mut guard = GLOBAL_FILE.lock().unwrap();
531         let content = read_to_string(&guard.shadow_file);
532         for line in content.lines() {
533             let mut field = line.split(':').collect::<Vec<_>>();
534             if field[0] == info.username {
535                 field[1] = info.new_password.as_str();
536             }
537             new_content.push_str(format!("{}\n", field.join(":")).as_str());
538         }
539 
540         guard.shadow_file.set_len(0).unwrap();
541         guard.shadow_file.seek(std::io::SeekFrom::Start(0)).unwrap();
542         guard.shadow_file.write_all(new_content.as_bytes()).unwrap();
543         guard.shadow_file.flush().unwrap();
544     }
545 }
546 
547 /// groupadd执行器
548 pub struct GAddExecutor;
549 
550 impl GAddExecutor {
551     /// **执行groupadd**
552     ///
553     /// ## 参数
554     /// - `info`: 组信息
555     pub fn execute(info: GAddInfo) {
556         Self::write_group_file(&info);
557         Self::write_gshadow_file(&info);
558     }
559 
560     /// 写入/etc/group文件: 添加用户组信息
561     fn write_group_file(info: &GAddInfo) {
562         GLOBAL_FILE
563             .lock()
564             .unwrap()
565             .group_file
566             .write_all(info.to_string_group().as_bytes())
567             .unwrap()
568     }
569 
570     /// 写入/etc/gshadow文件: 添加用户组密码信息
571     fn write_gshadow_file(info: &GAddInfo) {
572         GLOBAL_FILE
573             .lock()
574             .unwrap()
575             .gshadow_file
576             .write_all(info.to_string_gshadow().as_bytes())
577             .unwrap();
578     }
579 }
580 
581 /// groupdel执行器
582 pub struct GDelExecutor;
583 
584 impl GDelExecutor {
585     /// **执行groupdel**
586     ///
587     /// ## 参数
588     /// - `info`: 组信息
589     pub fn execute(info: GDelInfo) {
590         Self::update_group_file(&info);
591         Self::update_gshadow_file(&info);
592     }
593 
594     /// 更新/etc/group文件:删除用户组
595     pub fn update_group_file(info: &GDelInfo) {
596         let mut new_content = String::new();
597         let mut guard = GLOBAL_FILE.lock().unwrap();
598         let content = read_to_string(&guard.group_file);
599         for line in content.lines() {
600             let field = line.split(':').collect::<Vec<&str>>();
601             if field[0] != info.groupname {
602                 new_content.push_str(format!("{}\n", line).as_str());
603             }
604         }
605 
606         guard.group_file.set_len(0).unwrap();
607         guard.group_file.seek(std::io::SeekFrom::Start(0)).unwrap();
608         guard.group_file.write_all(new_content.as_bytes()).unwrap();
609         guard.group_file.flush().unwrap();
610     }
611 
612     /// 更新/etc/gshadow文件:移除用户组
613     pub fn update_gshadow_file(info: &GDelInfo) {
614         let mut new_content = String::new();
615         let mut guard = GLOBAL_FILE.lock().unwrap();
616         let content = read_to_string(&guard.gshadow_file);
617         for line in content.lines() {
618             let field = line.split(':').collect::<Vec<&str>>();
619             if field[0] != info.groupname {
620                 new_content.push_str(format!("{}\n", line).as_str());
621             }
622         }
623 
624         guard.gshadow_file.set_len(0).unwrap();
625         guard
626             .gshadow_file
627             .seek(std::io::SeekFrom::Start(0))
628             .unwrap();
629         guard
630             .gshadow_file
631             .write_all(new_content.as_bytes())
632             .unwrap();
633         guard.gshadow_file.flush().unwrap();
634     }
635 }
636 
637 /// groupmod执行器
638 pub struct GModExecutor;
639 
640 impl GModExecutor {
641     /// **执行groupmod**
642     ///
643     /// ## 参数
644     /// - `info`: 组信息
645     pub fn execute(info: GModInfo) {
646         Self::update_passwd_file(&info);
647         Self::update_group_file(&info);
648         Self::update_gshadow_file(&info);
649     }
650 
651     /// 更新/etc/group文件: 更新用户组信息
652     fn update_group_file(info: &GModInfo) {
653         let mut new_content = String::new();
654         let mut guard = GLOBAL_FILE.lock().unwrap();
655         let content = read_to_string(&guard.group_file);
656         for line in content.lines() {
657             let mut field = line.split(':').collect::<Vec<&str>>();
658             if field[0] == info.groupname {
659                 if let Some(new_groupname) = &info.new_groupname {
660                     field[0] = new_groupname;
661                 }
662                 if let Some(new_gid) = &info.new_gid {
663                     field[2] = new_gid;
664                 }
665             }
666             new_content.push_str(format!("{}\n", field.join(":")).as_str());
667         }
668 
669         guard.group_file.set_len(0).unwrap();
670         guard.group_file.seek(std::io::SeekFrom::Start(0)).unwrap();
671         guard.group_file.write_all(new_content.as_bytes()).unwrap();
672         guard.group_file.flush().unwrap();
673     }
674 
675     /// 更新/etc/gshadow文件: 更新用户组密码信息
676     fn update_gshadow_file(info: &GModInfo) {
677         let mut new_content = String::new();
678         let mut guard = GLOBAL_FILE.lock().unwrap();
679         let content = read_to_string(&guard.gshadow_file);
680         for line in content.lines() {
681             let mut field = line.split(':').collect::<Vec<&str>>();
682             if field[0] == info.groupname {
683                 if let Some(new_groupname) = &info.new_groupname {
684                     field[0] = new_groupname;
685                 }
686             }
687             new_content.push_str(format!("{}\n", field.join(":")).as_str());
688         }
689 
690         guard.gshadow_file.set_len(0).unwrap();
691         guard
692             .gshadow_file
693             .seek(std::io::SeekFrom::Start(0))
694             .unwrap();
695         guard
696             .gshadow_file
697             .write_all(new_content.as_bytes())
698             .unwrap();
699         guard.gshadow_file.flush().unwrap();
700     }
701 
702     /// 更新/etc/passwd文件: 更新用户组ID信息,因为用户组ID可能会被修改
703     fn update_passwd_file(info: &GModInfo) {
704         let mut new_content = String::new();
705         let mut guard = GLOBAL_FILE.lock().unwrap();
706         let content = read_to_string(&guard.passwd_file);
707         for line in content.lines() {
708             let mut field = line.split(':').collect::<Vec<&str>>();
709             if field[3] == info.gid {
710                 if let Some(new_gid) = &info.new_gid {
711                     field[3] = new_gid;
712                 }
713             }
714             new_content.push_str(format!("{}\n", field.join(":")).as_str());
715         }
716 
717         guard.passwd_file.set_len(0).unwrap();
718         guard.passwd_file.seek(std::io::SeekFrom::Start(0)).unwrap();
719         guard.passwd_file.write_all(new_content.as_bytes()).unwrap();
720         guard.passwd_file.flush().unwrap();
721     }
722 }
723 
724 fn read_to_string(mut file: &File) -> String {
725     file.seek(std::io::SeekFrom::Start(0)).unwrap();
726     let mut content = String::new();
727     file.read_to_string(&mut content).unwrap();
728     content
729 }
730