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