Getresuid устарел в c99?

Я пытаюсь скомпилировать функцию, содержащую вызов getresuid. Однако он генерирует следующее предупреждение:

setuid.c:8:3: warning: implicit declaration of function 'getresuid' is invalid
in C99 [-Wimplicit-function-declaration]
getresuid(&ruid, &euid, &suid);
^

Undefined symbols for architecture x86_64:
"_getresuid", referenced from:
_main in setuid-ba46f8.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1

Почему возникает ошибка компоновщика, говорящая, что символ не найден для архитектуры x86_64? Как сделать так, чтобы ссылка была успешной?

Если это поможет, мой исходный код был:

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main() {
    uid_t euid, ruid, suid;
    getresuid(&ruid, &euid, &suid);
    printf("EUID: %d, RUID: %d, SUID: %d\n", euid, ruid, suid);
    return 0;
}

Я пытаюсь скомпилировать на Mac OS X 10.10.2 (Yosemite).


person lingz    schedule 27.04.2015    source источник
comment
Прямой ответ — нет; getresuid() просто не является частью C99 и POSIX 2008 (2013). Поэтому, чтобы использовать его, вы должны использовать расширение для конкретной платформы. Вам не нужно #include <sys/types.h> в вашем коде. Ваш код компилируется нормально для меня на Ubuntu 14.04. Какую версию Linux вы используете?   -  person Jonathan Leffler    schedule 27.04.2015
comment
Я думаю, что C99 запрещает неявные объявления, а не getresuid(), что и вызывает путаницу.   -  person myaut    schedule 27.04.2015
comment
@ Джонатан Леффлер: Mac OS 10.10.2? Извините, это может быть глупый вопрос, но какое расширение вам нужно (и где вы можете найти ссылки)?   -  person lingz    schedule 27.04.2015
comment
Mac OS X 10.10.2 не является вариантом Linux; это вариант BSD. Функция getresuid() просто недоступна на Mac — она не реализована. Вам нужно будет использовать getuid() и geteuid() для частей 'r' и 'e'; Я не уверен, что есть способ получить часть 's'. Обратите внимание, что точное указание платформы в вопросе помогло бы избежать различных тупиков.   -  person Jonathan Leffler    schedule 27.04.2015


Ответы (2)


Вам нужно определить перед всеми заголовками

#define _GNU_SOURCE

поскольку getresuid является функцией расширения GNU.

person Rahul Tripathi    schedule 27.04.2015
comment
Я сделал это в своем исходном коде. Это все еще дает ту же ошибку. - person lingz; 27.04.2015
comment
@cathy: - Вы пытались добавить -D_GNU_SOURCE в параметры GCC? Также убедитесь, что вы добавили #define _GNU_SOURCE перед всеми заголовками в вашем файле. - person Rahul Tripathi; 27.04.2015
comment
Ага. Я прочитал еще один пост SO, в котором предлагались все эти вещи. Я считаю, что основным отличием моей ошибки выше является ошибка компоновщика. Соответствующее сообщение SO: объявление функции getresuid и seteuid"> stackoverflow.com/questions/19721810/ - person lingz; 27.04.2015
comment
@cathy: Когда вы определили _GNU_SOURCE, вы получили предупреждение о компиляции или просто ошибку компоновщика? - person Jonathan Leffler; 27.04.2015
comment
Обе. gcc setuid.c дает следующее: - person lingz; 27.04.2015
comment
setuid.c:8:3: предупреждение: неявное объявление функции getresuid недопустимо в C99 [-Wimplicit-function-declaration] getresuid(&ruid, &euid, &suid); ^ Создано 1 предупреждение. Неопределенные символы для архитектуры x86_64: _getresuid, на которые ссылается: _main в setuid-d2be64.old: символы не найдены для архитектуры x86_64 clang: ошибка: команда компоновщика завершилась неудачно с кодом выхода 1 - person lingz; 27.04.2015
comment
@cathy: в идеале вы должны определить, какую версию Linux вы используете. Что вы получаете от grep -l -e getresuid -r /usr/include? Вы должны получить /usr/include/unistd.h и другие файлы в перечисленных подкаталогах. - person Jonathan Leffler; 27.04.2015

Прямой ответ: «Нет; getresuid() просто не является частью C99 и POSIX 2008 (2013)». Поэтому, чтобы использовать его, вы должны использовать расширение для конкретной платформы, и оно доступно не на всех платформах.

Кстати, вам не нужно #include <sys/types.h> в вашем коде.

Ваш код компилируется нормально для меня на Ubuntu 14.04. Однако он не компилируется в Mac OS X 10.10.3 (Yosemite), производной от BSD, а не от Linux. Функция getresuid() просто недоступна — не реализована — на платформе.

Вам нужно будет использовать getuid() и geteuid() для информации «r» (реальный UID) и «e» (действующий UID); Я не думаю, что есть разумный способ получить информацию «s» (сохраненный UID). В большинстве случаев три значения UID совпадают. Только программа, которая должна быть запущена с установленным битом setuid, должна беспокоиться об этом, и такие программы могут захотеть беспокоиться о сохраненном UID. Однако вы, вероятно, ограничены проверкой действующего UID при запуске программы; это сохраненный UID.

person Jonathan Leffler    schedule 27.04.2015