Как смонтировать каталог через afp с помощью mount(2)?

Я хочу смонтировать каталог, который находится на другом хосте в моей сети. До сих пор я успешно делал это через afp, используя mount(8) через системный вызов, например:

std::string syscmd = "mount -v -t afp -r \"afp://user:password@host/dir\" \"/tmp/foo/bar\"";
FILE *fd;
if(!(fd = popen(syscmd.c_str(), "r"))) {
    std::cout << "oops. popen() failed." << std::endl;
    exit(1);
}    

Но я хотел бы монтировать напрямую с помощью вызова функции, без дополнительных накладных расходов на вызов оболочки с помощью popen(). Я не могу понять, как это сделать с помощью mount(2), который имеет следующую подпись:

 int mount(const char *type, const char *dir, int flags, void *data);

Каким должно быть data? Страница руководства не объясняет это подробно. Например, он говорит:

Data — это указатель на структуру, содержащую аргументы конкретного типа для монтирования. Формат этих структур аргументов описан на странице руководства для каждой файловой системы.

Где эта страница руководства, на которую он ссылается? Есть ли какая-то другая документация, которую мне не хватает? Может ли кто-нибудь указать мне простой рабочий пример, иллюстрирующий использование mount(2) поверх afp? Есть лучший способ сделать это?


person jt bullitt    schedule 26.05.2017    source источник
comment
Я нигде не могу найти справочную страницу для него. Я предполагаю, что ему просто нужен указатель на URL.   -  person Barmar    schedule 26.05.2017
comment
Возможно, запустите mount_afp с включенной трассировкой системных вызовов, чтобы увидеть, как он вызывает mount().   -  person Barmar    schedule 26.05.2017
comment
@Barmar Я пробовал char data[]="afp://user:password@host/dir"; mount("hfs","/tmp/foo/",MNT_RDONLY,data);, но это дало ошибку 14 (неверный адрес). Я попытался запустить mount_afp с отслеживанием вызовов (dtruss), но не нашел ничего полезного в тысячах строк вывода.   -  person jt bullitt    schedule 27.05.2017


Ответы (1)


У вас есть причина требовать, чтобы это было сделано через mount(2)?

Apple предоставляет функцию NetFSMountURLSync() из среды NetFS для монтирования сетевых файловых систем. К сожалению, единственной документацией является заголовочный файл, поэтому я не могу дать на него ссылку, но вот соответствующее объявление:

/*
 * Given a URL that refers to a file server, connect to that server
 * and mount stuff.
 *
 * If the URL just specifies a server and you can't just mount the
 * "root directory" of the server, the user will be prompted with
 * a window to let them select one or more items to mount from that
 * server, otherwise whatever item the URL specifies to mount will
 * be mounted.
 *
 * If the mountpath is provided it will be used as the mount point.
 * If the mountpath is set to NULL, a default mount point will be used.
 *
 * If the user and passwd are set, they will override any user name
 * or password that may be set in the URL. These calls go through the NetAuth agent.
 * If the URL doesn't specify a password, and one is needed, the
 * user will be prompted with a window requesting password.
 *
 * Options can be provided for the session open and the mount itself.
 * If the mount is successful, the POSIX path to each mountpoint is
 * returned as a CFStringRef in mountpoints.
 *
 * If the return value is zero the mount has succeeded.
 *
 * A positive non-zero return value represents an errno value
 * (see /usr/include/sys/errno.h).  For instance, a missing mountpoint
 * error will be returned as ENOENT (2).
 *
 * A negative non-zero return value represents an OSStatus error.
 * For instance, error -128 is userCanceledErr, returned when a mount
 * operation is canceled by the user. These OSStatus errors are
 * extended to include:
 *
 *  from this header:
 *  ENETFSPWDNEEDSCHANGE        -5045
 *  ENETFSPWDPOLICY         -5046
 *  ENETFSACCOUNTRESTRICTED     -5999
 *  ENETFSNOSHARESAVAIL     -5998
 *  ENETFSNOAUTHMECHSUPP        -5997
 *  ENETFSNOPROTOVERSSUPP       -5996
 *
 *  from <NetAuth/NetAuthErrors.h>
 *  kNetAuthErrorInternal       -6600
 *  kNetAuthErrorMountFailed    -6602
 *  kNetAuthErrorNoSharesAvailable  -6003
 *  kNetAuthErrorGuestNotSupported  -6004
 *  kNetAuthErrorAlreadyClosed  -6005
 *
 */
int
NetFSMountURLSync(
    CFURLRef url,               // URL to mount, e.g. nfs://server/path
    CFURLRef mountpath,         // Path for the mountpoint
    CFStringRef user,           // Auth user name (overrides URL)
    CFStringRef passwd,             // Auth password (overrides URL)
    CFMutableDictionaryRef open_options,    // Options for session open (see below)
    CFMutableDictionaryRef mount_options,   // Options for mounting (see below)
    CFArrayRef *mountpoints)        // Array of mountpoints
    __OSX_AVAILABLE_STARTING(__MAC_10_8, __IPHONE_NA);

Существует также асинхронная версия, если она полезна для вашего варианта использования.

Как показано в этом ответе, вам нужно будет используйте параметр kNetFSMountAtMountDirKey, если вы хотите указать точку монтирования.

person Ken Thomases    schedule 26.05.2017
comment
Это интересная идея. Раньше я не использовал OS X Frameworks. В основном я привык к стандартной библиотеке C++ и различным библиотекам с открытым исходным кодом, полученным через MacPorts. Помимо привыкания к длинным CamelCaseVariableNames Apple, есть ли какие-то большие концептуальные проблемы при погружении в OS X Frameworks? Крутая кривая обучения? - person jt bullitt; 27.05.2017
comment
Ну, в macOS есть много разных фреймворков. Однако NetFS, похоже, действительно зависит только от Core Foundation. Не должно быть слишком плохо. Главное, что нужно изучить, — это правила управления памятью и соглашения об именах, на которых они основаны. См. это и это. - person Ken Thomases; 27.05.2017