1 | /*␊ |
2 | * shell_process.cpp␊ |
3 | *␊ |
4 | * Created by Rekursor on 1/17/2010.␊ |
5 | *␊ |
6 | */␊ |
7 | ␊ |
8 | #include "ShellProcess.h"␊ |
9 | #include <string.h>␊ |
10 | #include <sys/stat.h>␊ |
11 | #include <string_util.h>␊ |
12 | ␊ |
13 | PartitionExtractor* PartitionExtractor::_instance = NULL;␊ |
14 | ␊ |
15 | //----------------------------------------------------------------␊ |
16 | // portable open process:␊ |
17 | FILE * ShellProcess::open(const char *cmd, const char *mode) {␊ |
18 | ␉_fpt=::popen(cmd,mode);␊ |
19 | ␉return _fpt;␊ |
20 | }␊ |
21 | ␊ |
22 | //----------------------------------------------------------------␊ |
23 | int ShellProcess::close() {␊ |
24 | ␉int ret = ::pclose(_fpt);␊ |
25 | ␉_fpt=NULL;␊ |
26 | ␉return ret;␊ |
27 | }␊ |
28 | ␊ |
29 | //----------------------------------------------------------------␊ |
30 | void PartitionInfo::removeSpaces(std::string &str)␊ |
31 | {␊ |
32 | ␉if (!str.size()) return;␊ |
33 | ␉int posl=0,posr=0;␊ |
34 | ␉for (posl=0; posl<str.size()-1 && str[posl]==' '; posl++);␊ |
35 | ␉for (posr=str.size()-1; posr>0 && str[posr]==' '; posr--);␊ |
36 | ␉str = (posl>posr) ? "" : str.substr(posl, posr-posl+1);␊ |
37 | }␊ |
38 | //----------------------------------------------------------------␊ |
39 | /**␊ |
40 | * ␉return the image index corresponding to a fs:␊ |
41 | */␊ |
42 | int PartitionInfo::imageIndexFromFs() const␊ |
43 | {␊ |
44 | ␉if (_fsType.find("Apple")!=std::string::npos ||␊ |
45 | ␉␉_fsType.find("HFS")!=std::string::npos)␊ |
46 | ␉␉return 0; // Windows␊ |
47 | ␉else if (_fsType.find("Windows")!=std::string::npos ||␊ |
48 | ␉␉␉ _fsType.find("Microsoft")!=std::string::npos ||␊ |
49 | ␉␉␉ _fsType.find("NTFS")!=std::string::npos ||␊ |
50 | ␉␉␉ _fsType.find("FAT")!=std::string::npos)␊ |
51 | ␉␉return 1; // Windows␊ |
52 | ␉else if (_fsType.find("Linux")!=std::string::npos)␊ |
53 | ␉␉return 2; // Unknown␊ |
54 | ␉return 10; //Unknown␊ |
55 | ␉␊ |
56 | }␊ |
57 | //----------------------------------------------------------------␊ |
58 | bool PartitionInfo::fromPartitionHdString(const char * inHdStr)␊ |
59 | {␊ |
60 | ␉if (!inHdStr || !(*inHdStr) || ␊ |
61 | ␉␉strlen(inHdStr)<7 || !strstr(inHdStr,"hd(")) return false;␊ |
62 | ␉␊ |
63 | ␉// enhance me here: should not assume that we have less than 10 partitions per disk/ disks␊ |
64 | ␉_disk = inHdStr[3]-'0'; ␊ |
65 | ␉_part = inHdStr[5]-'0';␊ |
66 | ␉return true;␊ |
67 | }␊ |
68 | //----------------------------------------------------------------␊ |
69 | const char * PartitionExtractor::checkForRename(const char * label, const char *szHd)␊ |
70 | {␊ |
71 | ␉const int MAX_ALIAS_SIZE=31;␊ |
72 | ␉static char szAlias[MAX_ALIAS_SIZE+1];␊ |
73 | ␉char *q=szAlias;␊ |
74 | ␉const char* szAliases = _renamedParts.c_str();␊ |
75 | ␉␊ |
76 | ␉if (!szHd || !*szHd || !szAliases || !*szAliases) return label; // no renaming wanted␊ |
77 | ␉␊ |
78 | ␉const char * p = strstr(szAliases, szHd);␊ |
79 | ␉if(!p || !(*p)) return label; // this volume must not be renamed, or option is malformed␊ |
80 | ␉␊ |
81 | ␉p+= strlen(szHd); // skip the "hd(n,m) " field␊ |
82 | ␉// multiple aliases can be found separated by a semi-column␊ |
83 | ␉while(*p && *p != ';' && q<(szAlias+MAX_ALIAS_SIZE)) *q++=*p++;␊ |
84 | ␉*q='\0';␊ |
85 | ␉␊ |
86 | ␉return szAlias;␊ |
87 | ␉␊ |
88 | }␊ |
89 | ␊ |
90 | // set to 1 the following line for debugging with a fake diskutil file named /diskutil.txt␊ |
91 | // for the debug to be accurate you need to alias (ln -s ...) the user to debug with your real disks␊ |
92 | #define DEBUG_DISKUTIL 0␊ |
93 | ␊ |
94 | //----------------------------------------------------------------␊ |
95 | const std::vector<PartitionInfo>& ␊ |
96 | PartitionExtractor::extractPartitions(const char* szHide, const char* szRenamed)␊ |
97 | {␊ |
98 | ␉const char * const diskTag = "/dev/disk";␊ |
99 | ␉const char * const nameTag = "NAME";␊ |
100 | ␉const char * const sizeTag = "SIZE";␊ |
101 | ␊ |
102 | ␉PartitionInfo partInfo;␊ |
103 | ␊ |
104 | ␉char line[1024]="";␊ |
105 | ␉char label[32]="", fsType[32]="" ;␊ |
106 | ␉size_t len=0;␊ |
107 | ␉int disk =0, part=0;␊ |
108 | ␉int label_pos=0, size_pos=0;␊ |
109 | ␉char * p=0,*q=0;␊ |
110 | ␉int skipwhite=0;␊ |
111 | ␉␊ |
112 | ␉_partList.clear();␊ |
113 | ␉if (szHide) hidePartitions(szHide);␊ |
114 | ␉if (szRenamed) renamedPartitions(szRenamed);␊ |
115 | ␊ |
116 | #if DEBUG_DISKUTIL␊ |
117 | ␉this->open("cat /diskutil.txt");␊ |
118 | #else␊ |
119 | ␉this->open("diskutil list");␊ |
120 | #endif␊ |
121 | ␉␊ |
122 | ␉while(get_line(line, sizeof(line)-1))␊ |
123 | ␉{␊ |
124 | ␉␉// printf("%s\n",line);␊ |
125 | ␉␉len = strlen(line);␊ |
126 | ␉␉for(skipwhite=0; line[skipwhite]==' ';skipwhite++);␊ |
127 | ␉␉␊ |
128 | ␉␉const char * sdisk = strstr(line, diskTag);␊ |
129 | ␉␉const char * sName = strstr(line, nameTag);␊ |
130 | ␉␉const char * sSize = strstr(line, sizeTag);␊ |
131 | ␉␉␊ |
132 | ␉␉if (sdisk)␊ |
133 | ␉␉{␊ |
134 | ␉␉␉// extract disk number␊ |
135 | ␉␉␉sscanf(&sdisk[strlen(diskTag)],"%d", &disk);␊ |
136 | ␉␉␉if (disk>=0 && disk <MAX_HD)␊ |
137 | ␉␉␉␉disk = _hdRedirTable[disk];␊ |
138 | ␉␉}␊ |
139 | ␉␉else if (len && line[skipwhite]=='#' && line[skipwhite+1]==':')␊ |
140 | ␉␉{␊ |
141 | ␉␉␉label_pos = sName ? (sName - line) : 0;␊ |
142 | ␉␉␉size_pos = sSize ? (sSize - line) : 0;␊ |
143 | ␉␉}␊ |
144 | ␉␉else if (len && line[skipwhite+1]==':' && isdigit(line[skipwhite]))␊ |
145 | ␉␉{␊ |
146 | ␉␉␉for (p=&line[skipwhite+2], q=fsType; *p && p < &line[label_pos-1]; p++,q++) *q=*p;␊ |
147 | ␉␉␉for (p=&line[label_pos], q=label; *p && p < &line[size_pos]; p++,q++) *q=*p;␊ |
148 | ␉␉␉␊ |
149 | ␉␉␉*q='\0';␊ |
150 | ␉␉␉part = line[skipwhite]-'0';␊ |
151 | ␉␉␉partInfo.fsType(fsType);␊ |
152 | ␉␉␉partInfo.disk(disk);␊ |
153 | ␉␉␉partInfo.partition(part);␊ |
154 | ␉␉␉partInfo.label(checkForRename(label, partInfo.toHdStr().c_str()));␊ |
155 | ␉␉␉size_t len = partInfo.label().length();␊ |
156 | ␉␉␉if(len==0){␊ |
157 | ␉␉␉␉strncpy(label, "Untitled", sizeof(label));␊ |
158 | ␉␉␉␉partInfo.label(label);␊ |
159 | ␉␉␉}␊ |
160 | ␉␉␉␉␊ |
161 | ␉␉␉// filter useless partitions:␊ |
162 | ␉␉␉if (partInfo.clabel()[len-1] !='*' && ␊ |
163 | ␉␉␉␉partInfo.clabel()!="EFI" && ␊ |
164 | ␉␉␉␉partInfo.fsType()!="EFI" &&␊ |
165 | ␉␉␉␉partInfo.fsType()!="Apple_partition_scheme" &&␊ |
166 | ␉␉␉␉partInfo.fsType()!="Apple_partition_map" &&␊ |
167 | ␉␉␉␉partInfo.fsType()!="Apple_Free" ␊ |
168 | ␉␉␉␉)␊ |
169 | ␉␉␉{␊ |
170 | ␉␉␉␉if (partInfo.fsType()=="Apple_HFS") partInfo.fsType("Apple HFS");␊ |
171 | ␉␉␉␉std::string diskLabel(trim(label)); ␊ |
172 | ␉␉␉␉bool found=false;␊ |
173 | ␉␉␉␉// early bail out if we found what we need: DON't make any assumption ␊ |
174 | ␉␉␉␉// that Windows is the name of WIN32 bootable disk dir ...␊ |
175 | ␉␉␉␉if (␊ |
176 | ␉␉␉␉␉fileExists("/Volumes/" + diskLabel + "/boot") || ␊ |
177 | ␉␉␉␉␉fileExists("/Volumes/" + diskLabel + "/System/Library/Extensions") ||␊ |
178 | ␉␉␉␉␉fileExists("/Volumes/" + diskLabel + "/ntldr") ||␊ |
179 | ␉␉␉␉␉fileExists("/Volumes/" + diskLabel + "/bootmgr") ||␊ |
180 | ␉␉␉␉␉fileExists("/Volumes/" + diskLabel + "/Boot") ||␊ |
181 | ␉␉␉␉␉fileExists("/Volumes/" + diskLabel + "/pagefile.sys") ||␊ |
182 | ␉␉␉␉␉fileExists("/Volumes/" + diskLabel + "/hiberfil.sys")␊ |
183 | ␉␉␉␉␉)␊ |
184 | ␉␉␉␉␉found=true;␊ |
185 | ␉␉␉␉else if ((strstr(fsType,"Linux") ) && !strstr(fsType, "Linux_Swap"))␊ |
186 | ␉␉␉␉␉found=true; // Added Linux case␊ |
187 | ␉␉␉␉if (found)␊ |
188 | ␉␉␉␉{ //check if one of them exists␊ |
189 | ␉␉␉␉␉if (partInfo.label().size()==0) partInfo.label("Untitled");␊ |
190 | ␉␉␉␉␉if(_hiddenParts.length()==0 || ␊ |
191 | ␉␉␉␉␉ _hiddenParts.find(partInfo.toHdStr()) == std::string::npos)␊ |
192 | ␉␉␉␉␉␉_partList.push_back(partInfo);␊ |
193 | ␉␉␉␉}␊ |
194 | ␉␉␉}␊ |
195 | ␉␉}␊ |
196 | ␉}␊ |
197 | ␉close();␊ |
198 | ␉␊ |
199 | ␉sort(_partList.begin(), _partList.end(), isDiskIndexInf);␊ |
200 | ␉return _partList;␊ |
201 | }␊ |
202 | ␊ |
203 | /** ␊ |
204 | * Get the index in the internal partlist of the hd(n,m) partition specified by the input string␊ |
205 | * return -1 if no match, >=0 if a match happens␊ |
206 | */␊ |
207 | int PartitionExtractor::getIndexFromHdStringSpec(const char* inHDStr)␊ |
208 | {␉␊ |
209 | ␉PartitionInfo info;␊ |
210 | ␉␊ |
211 | ␉if (info.fromPartitionHdString(inHDStr)) // try decode the partition disk and part infos␊ |
212 | ␉{␊ |
213 | ␉␉for (int i=0; i<_partList.size(); i++)␊ |
214 | ␉␉{␊ |
215 | ␉␉␉if (_partList[i].disk() == info.disk() && _partList[i].partition() == info.partition())␊ |
216 | ␉␉␉␉return i;␊ |
217 | ␉␉}␊ |
218 | ␉}␊ |
219 | ␉␊ |
220 | ␉return -1;␊ |
221 | }␊ |
222 | |