| 27 | static status_t |
| 28 | CopyData(BFile& srcFile, BFile& dstFile) |
| 29 | { |
| 30 | char buffer[4096]; |
| 31 | |
| 32 | while (true) { |
| 33 | ssize_t bytesRead = srcFile.Read(buffer, sizeof(buffer)); |
| 34 | if (bytesRead > 0) { |
| 35 | ssize_t bytesWritten = dstFile.Write(buffer, bytesRead); |
| 36 | if (bytesWritten < 0) |
| 37 | return bytesWritten; |
| 38 | } else if (bytesRead < 0) |
| 39 | return bytesRead; |
| 40 | else |
| 41 | break; |
| 42 | } |
| 43 | |
| 44 | return B_OK; |
| 45 | } |
| 46 | |
| 47 | |
| 48 | static status_t |
| 49 | CopyAttributes(BNode& srcNode, BNode& dstNode) |
| 50 | { |
| 51 | srcNode.RewindAttrs(); |
| 52 | char name[B_ATTR_NAME_LENGTH]; |
| 53 | while (srcNode.GetNextAttrName(name) == B_OK) { |
| 54 | attr_info info; |
| 55 | if (srcNode.GetAttrInfo(name, &info) == B_OK) { |
| 56 | char buffer[info.size]; |
| 57 | |
| 58 | ssize_t bytesRead = srcNode.ReadAttr(name, info.type, 0, buffer, info.size); |
| 59 | if (bytesRead > 0) { |
| 60 | ssize_t bytesWritten = dstNode.WriteAttr(name, info.type, 0, |
| 61 | buffer, info.size); |
| 62 | if (bytesWritten < 0) |
| 63 | return bytesWritten; |
| 64 | } else |
| 65 | return bytesRead; |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | return B_OK; |
| 70 | } |
| 71 | |
| 72 | |
| 73 | static status_t |
| 74 | CopyScreenSaver(BFile& srcFile, BFile& dstFile) |
| 75 | { |
| 76 | status_t status = CopyData(srcFile, dstFile); |
| 77 | if (status < B_OK) |
| 78 | return status; |
| 79 | |
| 80 | return CopyAttributes(srcFile, dstFile); |
| 81 | } |
| 82 | |
| 83 | |
61 | | // TODO: find_directory() anyone?? |
62 | | char temp[2*B_PATH_NAME_LENGTH]; |
63 | | sprintf(temp,"cp %s '/boot/home/config/add-ons/Screen Savers/'\n", path.Path()); |
64 | | system(temp); |
65 | | fScreenSaverWindow->PostMessage(kMsgUpdateList); |
| 117 | if (srcEntry.InitCheck() != B_OK) |
| 118 | return; |
| 119 | |
| 120 | BPath srcPath; |
| 121 | srcEntry.GetPath(&srcPath); |
| 122 | |
| 123 | if (srcEntry.IsDirectory()) { |
| 124 | BString errorMessage; |
| 125 | errorMessage << srcPath.Leaf() << " is a directory!\n"; |
| 126 | errorMessage << "You can not install a directory!"; |
| 127 | (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL, |
| 128 | B_WIDTH_AS_USUAL, B_INFO_ALERT))->Go(); |
| 129 | return; |
| 130 | } |
| 131 | |
| 132 | BFile srcFile(srcPath.Path(), O_RDONLY); |
| 133 | if (srcFile.InitCheck() != B_OK) |
| 134 | return; |
| 135 | |
| 136 | // Check if the file in question is really a screensaver |
| 137 | // (with some acrobatics!) |
| 138 | |
| 139 | // First check for black-listed files: |
| 140 | // binary files that contains the string 'StartSaver' |
| 141 | // libscreensaver.so, ScreenSaver, screen_blanker |
| 142 | // without being really screensavers, and the |
| 143 | // user may try to throw in the ScreenSaver pref. window |
| 144 | |
| 145 | BString blackListed1("libscreensaver.so"); |
| 146 | BString blackListed2("ScreenSaver"); |
| 147 | BString blackListed3("screen_blanker"); |
| 148 | |
| 149 | BString candidateScr(srcPath.Leaf()); |
| 150 | |
| 151 | if (candidateScr == blackListed1 |
| 152 | || candidateScr == blackListed2 |
| 153 | || candidateScr == blackListed3) { |
| 154 | BString errorMessage; |
| 155 | errorMessage << "File " << srcPath.Leaf() << "\n"; |
| 156 | errorMessage << "is not a screensaver file!"; |
| 157 | (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL, |
| 158 | B_WIDTH_AS_USUAL, B_INFO_ALERT))->Go(); |
| 159 | return; |
| 160 | } |
| 161 | |
| 162 | // Check all the other files |
| 163 | |
| 164 | off_t location = 0; |
| 165 | bool isFileScreenSaver = false; |
| 166 | uint32 kBytesToRead = 4096; |
| 167 | uint32 kNumOfTries = 20; |
| 168 | char buffer[kNumOfTries * kBytesToRead]; |
| 169 | ssize_t bytesRead; |
| 170 | |
| 171 | while (kNumOfTries) { |
| 172 | bytesRead = srcFile.ReadAt(location, buffer + location, kBytesToRead); |
| 173 | if (bytesRead < B_OK) { |
| 174 | BString errorMessage; |
| 175 | errorMessage << "At " << __PRETTY_FUNCTION__ << "\n"; |
| 176 | errorMessage << "failed to examine file " << srcPath.Leaf() << "\n"; |
| 177 | errorMessage << "Reason: " << strerror(bytesRead); |
| 178 | (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL, |
| 179 | B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go(); |
| 180 | return; |
| 181 | } |
| 182 | |
| 183 | for (uint32 index = 0; index < kBytesToRead; index++) { |
| 184 | if (buffer[location + index] == '\0') |
| 185 | buffer[location + index] = 'a'; |
| 186 | } |
| 187 | |
| 188 | const char stringToFind[] = "StartSaver"; |
| 189 | if (char* foundAddress = strstr(buffer, stringToFind)) { |
| 190 | isFileScreenSaver = true; |
| 191 | memset(foundAddress, 'a', strlen(stringToFind)); |
| 192 | break; |
| 193 | } |
| 194 | |
| 195 | location += kBytesToRead; |
| 196 | kNumOfTries--; |
| 197 | } |
| 198 | |
| 199 | if (!isFileScreenSaver) { |
| 200 | BString errorMessage; |
| 201 | errorMessage << "File " << srcPath.Leaf() << "\n"; |
| 202 | errorMessage << "is not a screensaver file!"; |
| 203 | (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL, |
| 204 | B_WIDTH_AS_USUAL, B_INFO_ALERT))->Go(); |
| 205 | return; |
| 206 | } |
| 207 | |
| 208 | BPath userNewScreenSaver; |
| 209 | status_t status = find_directory(B_USER_ADDONS_DIRECTORY, |
| 210 | &userNewScreenSaver); |
| 211 | if (status < B_OK) { |
| 212 | BString errorMessage; |
| 213 | errorMessage << "At " << __PRETTY_FUNCTION__ << "\n"; |
| 214 | errorMessage << "find_directory() failed. \nReason: "; |
| 215 | errorMessage << strerror(status); |
| 216 | (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL, |
| 217 | B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go(); |
| 218 | return; |
| 219 | } |
| 220 | |
| 221 | userNewScreenSaver.Append("Screen Savers"); |
| 222 | userNewScreenSaver.Append(srcPath.Leaf()); |
| 223 | |
| 224 | BFile destFile(userNewScreenSaver.Path(), O_RDWR | O_CREAT); |
| 225 | if (destFile.InitCheck() != B_OK) |
| 226 | return; |
| 227 | |
| 228 | status = CopyScreenSaver(srcFile, destFile); |
| 229 | if (status < B_OK) { |
| 230 | BString errorMessage; |
| 231 | errorMessage << "At " << __PRETTY_FUNCTION__ << "\n"; |
| 232 | errorMessage << "Copying the screensaver file failed. \nReason: "; |
| 233 | errorMessage << strerror(status); |
| 234 | (new BAlert("AlertError", errorMessage.String(), "OK", NULL, NULL, |
| 235 | B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go(); |
| 236 | return; |
| 237 | } |
| 238 | |
| 239 | fScreenSaverWindow->PostMessage(kMsgUpdateList); |
| 240 | } |