// -*- mode: cpp; mode: fold -*- // Description /*{{{*/ // $Id: cdromutl.cc,v 1.1 1998/11/29 01:19:27 jgg Exp $ /* ###################################################################### CDROM Utilities - Some functions to manipulate CDROM mounts. These are here for the cdrom method and apt-cdrom. ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ #ifdef __GNUG__ #pragma implementation "apt-pkg/cdromutl.h" #endif #include <apt-pkg/cdromutl.h> #include <apt-pkg/error.h> #include <apt-pkg/md5.h> #include <apt-pkg/fileutl.h> #include <sys/wait.h> #include <sys/errno.h> #include <sys/vfs.h> #include <dirent.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> /*}}}*/ // UnmountCdrom - Unmount a cdrom /*{{{*/ // --------------------------------------------------------------------- /* Forking umount works much better than the umount syscall which can leave /etc/mtab inconsitant. We drop all messages this produces. */ bool UnmountCdrom(string Path) { int Child = fork(); if (Child < -1) return _error->Errno("fork","Failed to fork"); // The child if (Child == 0) { // Make all the fds /dev/null for (int I = 0; I != 10; I++) close(I); for (int I = 0; I != 3; I++) dup2(open("/dev/null",O_RDWR),I); const char *Args[10]; Args[0] = "umount"; Args[1] = Path.c_str(); Args[2] = 0; execvp(Args[0],(char **)Args); exit(100); } // Wait for mount int Status = 0; while (waitpid(Child,&Status,0) != Child) { if (errno == EINTR) continue; return _error->Errno("waitpid","Couldn't wait for subprocess"); } // Check for an error code. if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) return false; return true; } /*}}}*/ // MountCdrom - Mount a cdrom /*{{{*/ // --------------------------------------------------------------------- /* We fork mount and drop all messages */ bool MountCdrom(string Path) { int Child = fork(); if (Child < -1) return _error->Errno("fork","Failed to fork"); // The child if (Child == 0) { // Make all the fds /dev/null for (int I = 0; I != 10; I++) close(I); for (int I = 0; I != 3; I++) dup2(open("/dev/null",O_RDWR),I); const char *Args[10]; Args[0] = "mount"; Args[1] = Path.c_str(); Args[2] = 0; execvp(Args[0],(char **)Args); exit(100); } // Wait for mount int Status = 0; while (waitpid(Child,&Status,0) != Child) { if (errno == EINTR) continue; return _error->Errno("waitpid","Couldn't wait for subprocess"); } // Check for an error code. if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) return false; return true; } /*}}}*/ // IdentCdrom - Generate a unique string for this CD /*{{{*/ // --------------------------------------------------------------------- /* We convert everything we hash into a string, this prevents byte size/order from effecting the outcome. */ bool IdentCdrom(string CD,string &Res) { MD5Summation Hash; string StartDir = SafeGetCWD(); if (chdir(CD.c_str()) != 0) return _error->Errno("chdir","Unable to change to %s",CD.c_str()); DIR *D = opendir("."); if (D == 0) return _error->Errno("opendir","Unable to read %s",CD.c_str()); // Run over the directory char S[300]; for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D)) { // Skip some files.. if (strcmp(Dir->d_name,".") == 0 || strcmp(Dir->d_name,"..") == 0) continue; sprintf(S,"%lu",Dir->d_ino); Hash.Add(S); Hash.Add(Dir->d_name); }; chdir(StartDir.c_str()); closedir(D); // Some stats from the fsys struct statfs Buf; if (statfs(CD.c_str(),&Buf) != 0) return _error->Errno("statfs","Failed to stat the cdrom"); sprintf(S,"%u %u",Buf.f_blocks,Buf.f_bfree); Hash.Add(S); Res = Hash.Result().Value(); return true; } /*}}}*/