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 {
new() -> Self25 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
open_file(file_path: &str) -> File39 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`: 用户信息
execute(info: UAddInfo)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文件:添加用户信息
write_passwd_file(info: &UAddInfo)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文件:将用户添加到对应用户组中
write_group_file(info: &UAddInfo)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文件:添加用户口令相关信息
write_shadow_file(info: &UAddInfo)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文件:将用户添加到对应用户组中
write_gshadow_file(info: &UAddInfo)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`: 用户信息
execute(info: UDelInfo)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文件: 删除用户信息
update_passwd_file(info: &UDelInfo)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文件: 将用户从组中移除
update_group_file(info: &UDelInfo)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文件: 将用户信息删去
update_shadow_file(info: &UDelInfo)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文件: 将用户从组中移除
update_gshadow_file(info: &UDelInfo)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`: 用户信息
execute(mut info: UModInfo)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
update_passwd_file(info: &UModInfo)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文件中各用户组中的用户
update_group_file(info: &mut UModInfo)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
update_shadow_file(info: &UModInfo)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文件中各用户组中的用户
update_gshadow_file(info: &UModInfo)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`: 用户密码信息
execute(info: PasswdInfo)499 pub fn execute(info: PasswdInfo) {
500 Self::update_passwd_file(&info);
501 Self::update_shadow_file(&info);
502 }
503
504 /// 更新/etc/passwd文件: 修改用户密码
update_passwd_file(info: &PasswdInfo)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文件: 修改用户密码
update_shadow_file(info: &PasswdInfo)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`: 组信息
execute(info: GAddInfo)555 pub fn execute(info: GAddInfo) {
556 Self::write_group_file(&info);
557 Self::write_gshadow_file(&info);
558 }
559
560 /// 写入/etc/group文件: 添加用户组信息
write_group_file(info: &GAddInfo)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文件: 添加用户组密码信息
write_gshadow_file(info: &GAddInfo)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`: 组信息
execute(info: GDelInfo)589 pub fn execute(info: GDelInfo) {
590 Self::update_group_file(&info);
591 Self::update_gshadow_file(&info);
592 }
593
594 /// 更新/etc/group文件:删除用户组
update_group_file(info: &GDelInfo)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文件:移除用户组
update_gshadow_file(info: &GDelInfo)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`: 组信息
execute(info: GModInfo)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文件: 更新用户组信息
update_group_file(info: &GModInfo)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文件: 更新用户组密码信息
update_gshadow_file(info: &GModInfo)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可能会被修改
update_passwd_file(info: &GModInfo)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
read_to_string(mut file: &File) -> String724 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