2010-05-26 12 views
42

Necesito una forma de obtener el directorio de inicio del usuario en el programa C++ que se ejecuta en Linux. Si el mismo código funciona en Unix, sería bueno. No quiero usar el valor de entorno HOME.Obtener directorio de inicio en Linux, C++

AFAIK, el directorio raíz de inicio es/root. ¿Está bien crear algunos archivos/carpetas en este directorio, en el caso de que mi programa esté ejecutándose por usuario raíz?

+2

directorio principal actual del usuario (no nombre) es '~' es lo ¿no? Como en 'cd ~', 'mv some_file ~/some_file' etc. –

+14

@NickBedford -' ~ 'es implementado por el shell, no el kernel o libc. Cuando programe en C++, debe implementarlo usted mismo. –

+1

@Samuel gracias por la aclaración. –

Respuesta

72

Es necesario getuid para obtener el ID de usuario del usuario actual y luego getpwuid para obtener la introducción de la contraseña (que incluye el directorio de inicio) de ese usuario:

#include <unistd.h> 
#include <sys/types.h> 
#include <pwd.h> 

struct passwd *pw = getpwuid(getuid()); 

const char *homedir = pw->pw_dir; 

Nota: si usted necesita esto de una aplicación enhebrada, querrá usar getpwuid_r en su lugar.

+38

Tenga en cuenta que la página man 'getpwuid()' tiene esta advertencia: * Una aplicación que desea determinar el directorio de inicio de su usuario debe inspeccionar el valor de 'HOME' (en lugar del valor' getpwuid (getuid()) -> pw_dir ') ya que esto permite al usuario modificar su noción de" directorio personal "durante una sesión de inicio de sesión. * – caf

+16

Primero compruebo getenv (" HOME ") y luego getpwuid() –

+0

Esta no es una buena respuesta a la pregunta original . Este es el directorio de inicio del shell configurado en '/ etc/passwd', que puede ser o no el directorio de inicio del usuario (activo). Esta es información útil, pero 'getenv' es la respuesta correcta. –

1

Si está ejecutando el programa como usuario root, tendrá acceso rwx a este directorio. Crear cosas dentro de él está bien, supongo.

+1

No hay garantía de que/root sea el directorio de inicio para root en un sistema en particular.En general, es una idea bastante mala codificar las rutas en una aplicación, ya que hace que el software sea mucho menos portátil. Usar/root como predeterminado (cuando HOMEDIR no puede determinarse de otro modo) parece razonable siempre que haya una manera de anularlo a través de la configuración. –

+0

@Hypher Todo es cierto, aunque la respuesta a la pregunta "¿Está bien crear algunos archivos/carpetas en este directorio [/ root], en el caso de que mi programa esté ejecutándose por usuario raíz?" Es sí". – Anthony

44

Primero debe verificar la variable de entorno $HOME, y si eso no existe, use getpwuid.

#include <unistd.h> 
#include <sys/types.h> 
#include <pwd.h> 

const char *homedir; 

if ((homedir = getenv("HOME")) == NULL) { 
    homedir = getpwuid(getuid())->pw_dir; 
} 

También tenga en cuenta, que si se desea que el directorio principal para almacenar datos de configuración de caché o como parte de un programa que escribe y quiere distribuir a los usuarios, se debe considerar la siguiente XDG Base Directory Specification. Por ejemplo, si desea crear un directorio de configuración para su aplicación, primero debe marcar $XDG_CONFIG_HOME usando getenv como se muestra arriba y solo recurrir al código anterior si la variable no está configurada.

Si requiere de seguridad multi-hilo, se debe utilizar getpwuid_r en lugar de getpwuid como esto (desde la página getpwnam(3) hombre):

struct passwd pwd; 
struct passwd *result; 
char *buf; 
size_t bufsize; 
int s; 
bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); 
if (bufsize == -1) 
    bufsize = 16384; 
buf = malloc(bufsize); 
if (buf == NULL) { 
    perror("malloc"); 
    exit(EXIT_FAILURE); 
} 
s = getpwuid_r(getuid(), &pwd, buf, bufsize, &result); 
if (result == NULL) { 
    if (s == 0) 
     printf("Not found\n"); 
    else { 
     errno = s; 
     perror("getpwnam_r"); 
    } 
    exit(EXIT_FAILURE); 
} 
char *homedir = result.pw_dir; 
+0

Es posible que necesite un mutex allí. De lo contrario, la única forma es 'getpwuid_r'. Por qué esa función juega con la configuración regional, no lo sé. – user877329

+0

Parece que falta un libre de buf. –

+1

@ChrisSherlock Me temo que si 'free (buf)' en mi respuesta, entonces eso podría ser engañoso y provocar problemas de 'free()' demasiado temprano porque de acuerdo con la página man de 'getpwuid_r':" campos de cadena apuntado por los miembros de la estructura passwd se almacenan en el buffer buf de tamaño buflen ". Así que 'buf' sigue siendo útil mientras' pwd' sea útil. – josch

Cuestiones relacionadas