Я хотел бы написать функцию, которая генерирует gz файл. Функция будет работать только в Linux
поэтому я хотел бы использовать команду gzip
(просто выполнить внешнюю команду).
Пока у меня это:
bool generate_gz( const String& path )
{
bool res = false;
// LINUX
#ifndef __WXMSW__
if( !gzip_command_exists())
cout << "cannot compress file. 'gzip' command is not available.\n";
else
res = (0 == execute_command(String::Format("gzip %s", path.c_str())));
// WINDOWS
#else
// do nothing - result will be false
#endif
return res;
}
bool gzip_command_exists()
{
// TBD
}
Вопрос
Есть ли способ реализовать gzip_command_exists()
? Если это так, нужно ли включать запуск (или попытку запуска) команды gzip
?
Самое простое - выполнить через system()
: "which gzip"
и посмотреть код выхода системного вызова:
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ Возвращаемое значение -1 при ошибке (например, fork (2) не удалось) и статус возврата команды в противном случае. Этот последний статус возврата находится в формате, указанном в ожидании (2). Таким образом, код выхода команды будет WEXITSTATUS (статус). В случае, если /bin/sh не может быть выполнен, статус выхода будет таковым из команды, которая выполняет выход (127).
Что искать:
:~$ which gzip
/bin/gzip
:~$ echo $?
0
:~$ which gzip11
:~$ echo $?
1
Если вы не хотите создавать внешнюю команду, вы можете использовать функцию stat, чтобы проверить, существует ли файл и если он выполняется в системе POSIX.
Это вы не хотите жестко кодировать путь к gzip, это немного сложнее. Вам нужно будет получить переменную среды PATH, разделить ее на двоеточие, а затем проверить каждый путь для gzip. Опять же, имя и формат переменных пути являются специфичными для POSIX. Проверьте функцию getenv, чтобы прочитать путь, и вы можете использовать strtok для его разделения.
Это сомнительно, если стоит проверить, хотя, наоборот, просто пытается запустить его и обработать любые ошибки.
Вы можете использовать popen (3) для чтения вывода /usr/bin/which gzip
(и вы также можете использовать его для сжатия на лету write- popen
-ing gzip > file.gz
command). вы также можете: FILE* pgzipv = popen("gzip --version", "r");
и fgets
первая строка затем pclose
....
Вы могли бы рассмотреть возможность использования getenv("PATH")
то делает петлю на него с access
теста к каждому сконструированной путиполученного путем добавления /gzip
к каждому элементу в PATH
, и т.д... Вы можете также fork
затем execvp
с помощью gzip
--version
с stdout
и stderr
соответствующим образом перенаправлены и т.д.
Обратите внимание, что и popen (3), и система (3) не сработают, если вас попросят выполнить несинхронную (CN04) xisting-программу (так как оба fork (2) a /bin/sh shell с -c
). Таким образом, вам не нужно проверять наличие gzip
и вам всегда нужно проверять успех system
или popen
(что может быть неудачно по многим причинам, см. Ниже для отказа fork
и документации для других сбоев).
Чтобы быть придирчивым, проверка того, что gzip
существует, бесполезна: [файл /bin/gzip
] может (маловероятно) быть удален между вашей проверкой -e.g.с access
как показано ниже, или с именем popen
как above- и последующим вызовом system
или popen
;поэтому ваша первая проверка на gzip
ничего не принесет.
В большинстве Linux-систем gzip
обычно доступен в /bin/gzip
(и на практике gzip
всегда устанавливается); это требуется стандартом иерархии файловой системы (в котором говорится, что если gzip
установлен, он должен находиться на этом пути к файлу). Тогда вы можете просто использовать доступ (2), например, с кодом, например
#define GZIP_PATH "/bin/gzip" /* per FSH, see www.pathname.com/fhs */
if (access(GZIP_PATH, X_OK)) { perror(GZIP_PATH); exit(EXIT_FAILURE); };
В конце концов, вам не нужно вообще, чтобы раскошелиться на gzip
процесс GZIP -c ompress файл. Вы могли (и должны) просто использовать библиотеку, такую как zlib (которая требуется в соответствии с базой Linux Standard как libz.so.1
); вам нужны его gzopen
, gzwrite
, gzprintf
, gzputs
, gzclose
т. д.... функции! Это было бы быстрее (нет необходимости в fork (2) любом внешнем процессе) и более надежной (без зависимости от какой-либо внешней программы, такой как gzip
; будет работать, даже если fork
невозможен, поскольку пределы достигнуты - см. Setrlimit (2) с RLIMIT_NPROC
и ulimit
встроенный bash (1))
См. Также Расширенное программирование на Linux
zlib
. Я хотел бы понять, что я получу, используя zlib
вместо активации внешней команды, которая будет доступна в 99% случаев?