ENUNCIADO
Como primera práctica (que no hay que entregar), hay que realizar
un programa que admita el nombre de un fichero como argumento.
El programa debe cambiar el grupo al que pertenece el fichero
al grupo cuyo identificador de grupo es el 666. El programa
debe detectar e imprimir las codiciones de error y devolver
0 al sistema operativo si no se produjeron errores y 1 en caso
contrario. Notas: en caso de que el fichero sea un enlace
simbólico, debe cambiar el grupo del propio enlace, no de
aquello a lo que apunta. El propietario del fichero debe
permanecer inalterado.
COMENTARIOS
La práctica con 0.25 es la de Goku y Son Gohan:
#define _HPUX_SOURCE
#include <stdio.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
/* Es normal verificar que los argumentos pasados son correctos */
if (argc != 2)
{ /* Los errores, por el canal de errores. */
fprintf(stderr,"\n\nUso: %s <fichero>\n\n",argv[0]);
return 1; /* Al incluir argv[0], si cambio el nombre del programa, el mensaje sigue siendo válido. */
}
if (lchown(argv[1],UID_NO_CHANGE,666)==-1)
{ /* Bastaría con el perror, pero así se sabe qué fichero falla. */
fprintf(stderr,"\nNo se ha podido cambiar el grupo del ");
fprintf(stderr,"grupo del fichero: %s\n\n",argv[1]);
perror("lchown");
return 2;
}
return 0; /* No olvidar el código de retorno de éxito. */
}
Fijaros en el estilo de la práctica para las próximas que
hagáis o tengáis que entregar.
Nada de comentarios ni código innecesario. Los comentarios en rojo
son del profesor.
MENCIONES ESPECIALES
- Inauguramos la sección de cosas que hay que evitar no con
un error, sino con un estilo de programación que se debe evitar:
if(argc != 2)
{
printf("\nSintaxis: cam_grp [fichero].\n");
return 1;
}
else
{
if(lchown(argv[1], getuid(), 666) == -1)
{
sprintf(etiqueta, "%s: chown: %s", argv[0], argv[1]);
perror(etiqueta);
return 1;
}
else return 0;
}
Consiste en un anidamiento innecesario de bloques
if-else. No aporta nada al código y hace que el
programa se desplace innecesariamente a la derecha. El mismo
código se puede escribir más claramente haciendo
exactamente lo mismo así:
if(argc != 2)
{
printf("\nSintaxis: cam_grp [fichero].\n");
return 1;
}
if(lchown(argv[1], getuid(), 666) == -1)
{
sprintf(etiqueta, "%s: chown: %s", argv[0], argv[1]);
perror(etiqueta);
return 1;
}
return 0;
Dicho de otro modo, si de dentro del bloque primero del if
nunca se sale, el bloque else es innecesario. Hay personas
que, incluso, de un modo proactivo, programan para que las condiciones
de salida aparezcan en sucesivos ifs donde son eliminadas,
quedando la
línea principal para la ejecución normal o satisfactoria.
- Observad esta línea:
res=lchown(argv[1],UID_NO_CHANGE,0666);
Ese inocente cero (0) que aparece delante del 666 hace que la
práctica no se comporte como se desea. ¿Es que hay diferencia
entre 666 y 0666? Pues en C, sí. Cuando se antepone un cero
a un número en C significa
que dicho número está escrito en
base 8. Así que 0666 equivale a 6+8*6+8*8*6=438. Lo que ocurre
es que cuando se manejan permisos de fichero es más cómodo
trabajar en octal pues cada dígito corresponde con un tipo de
permiso (propietario, grupo o todos los demás, respectivamente).
© 2011 Guillermo González Talaván.