1 /* 2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de> 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <dirent.h> 9 #include <errno.h> 10 #include <fcntl.h> 11 #include <getopt.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 17 #include <Entry.h> 18 19 #include <package/PackageInfo.h> 20 #include <package/hpkg/HPKGDefs.h> 21 #include <package/hpkg/PackageWriter.h> 22 23 #include "package.h" 24 #include "PackageWriterListener.h" 25 #include "StandardErrorOutput.h" 26 27 28 using BPackageKit::BHPKG::BPackageWriterListener; 29 using BPackageKit::BHPKG::BPackageWriter; 30 31 32 int 33 command_create(int argc, const char* const* argv) 34 { 35 const char* changeToDirectory = NULL; 36 const char* packageInfoFileName = NULL; 37 bool quiet = false; 38 bool verbose = false; 39 40 while (true) { 41 static struct option sLongOptions[] = { 42 { "help", no_argument, 0, 'h' }, 43 { "quiet", no_argument, 0, 'q' }, 44 { "verbose", no_argument, 0, 'v' }, 45 { 0, 0, 0, 0 } 46 }; 47 48 opterr = 0; // don't print errors 49 int c = getopt_long(argc, (char**)argv, "+C:hi:qv", sLongOptions, NULL); 50 if (c == -1) 51 break; 52 53 switch (c) { 54 case 'C': 55 changeToDirectory = optarg; 56 break; 57 58 case 'h': 59 print_usage_and_exit(false); 60 break; 61 62 case 'i': 63 packageInfoFileName = optarg; 64 break; 65 66 case 'q': 67 quiet = true; 68 break; 69 70 case 'v': 71 verbose = true; 72 break; 73 74 default: 75 print_usage_and_exit(true); 76 break; 77 } 78 } 79 80 // The remaining arguments is the package file, i.e. one more argument. 81 if (optind + 1 != argc) 82 print_usage_and_exit(true); 83 84 const char* packageFileName = argv[optind++]; 85 86 // create package 87 PackageWriterListener listener(verbose, quiet); 88 BPackageWriter packageWriter(&listener); 89 status_t result = packageWriter.Init(packageFileName); 90 if (result != B_OK) 91 return 1; 92 93 // If a package info file has been specified explicitly, open it. 94 int packageInfoFD = -1; 95 if (packageInfoFileName != NULL) { 96 packageInfoFD = open(packageInfoFileName, O_RDONLY); 97 if (packageInfoFD < 0) { 98 fprintf(stderr, "Error: Failed to open package info file \"%s\": " 99 "%s\n", packageInfoFileName, strerror(errno)); 100 } 101 } 102 103 // change directory, if requested 104 if (changeToDirectory != NULL) { 105 if (chdir(changeToDirectory) != 0) { 106 listener.PrintError( 107 "Error: Failed to change the current working directory to " 108 "\"%s\": %s\n", changeToDirectory, strerror(errno)); 109 } 110 } 111 112 // add all files of current directory 113 DIR* dir = opendir("."); 114 if (dir == NULL) { 115 listener.PrintError("Error: Failed to opendir '.': %s\n", 116 strerror(errno)); 117 return 1; 118 } 119 120 while (dirent* entry = readdir(dir)) { 121 // skip "." and ".." 122 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) 123 continue; 124 125 // also skip the .PackageInfo -- we'll add it later 126 if (strcmp(entry->d_name, B_HPKG_PACKAGE_INFO_FILE_NAME) == 0) 127 continue; 128 129 result = packageWriter.AddEntry(entry->d_name); 130 if (result != B_OK) 131 return 1; 132 } 133 134 closedir(dir); 135 136 // add the .PackageInfo 137 result = packageWriter.AddEntry(B_HPKG_PACKAGE_INFO_FILE_NAME, 138 packageInfoFD); 139 if (result != B_OK) 140 return 1; 141 142 // write the package 143 result = packageWriter.Finish(); 144 if (result != B_OK) 145 return 1; 146 147 if (verbose) 148 printf("\nsuccessfully created package '%s'\n", packageFileName); 149 150 return 0; 151 } 152