Documentación

Tutoriales. Explican en profundidad un área de conocimiento.
Reportajes. Informan al lector sobre una tecnología.
Trucos. Describen alguna pequeña funcionalidad o consejo.
Videocursos. Vídeos sobre programación Mac/iOS
Bibliografía. Las fuentes de información que utilizamos.

Tutoriales

Animamos a otros sitios web a poner enlaces a nuestros tutoriales, pero por favor no hagan copias de ellos en otros servidores, ya que si actualizamos los tutoriales seguirá habiendo copias antiguas en circulación durante mucho tiempo. Esto va en perjuicio de los lectores que cojan la copia antigua. Lo que sí recomendamos es poner enlaces directos los permalink de esta página.

Programación con bloques

Mac OS X 10.6 y iOS 4 han introducido en el lenguaje los bloques (blocks), una construcción sintáctica que simplifica la programación de tareas. Su implementación es de código abierto, forma parte de GCC y Apple la ha enviado al comité de estandarización de ISO. Actualmente el compilador de GCC de Apple permite utilizar bloques tanto en lenguaje C como en el lenguaje C++ y Objective-C. En este tutorial se explica qué son los bloques, qué ventajas ofrecen y cómo se programan.

Este tutorial asume que el lector conoce el lenguaje C, y los conceptos de lenguaje y de programación que se explican en el tutorial Compilar y depurar aplicaciones con las herramientas de programación de GNU.

Download [enlace alternativo] [permalink]

Compilar y depurar aplicaciones con las herramientas de programación de GNU

En este tutorial pretendemos mostrar el manejo de las herramientas de programación que GNU ha puesto a disposición de los usuarios en multitud de sistemas, y que Apple ha elegido como base para sus herramientas de programación. Estas herramientas incluyen los conocidos comandos gcc y gdb. Sin embargo, las herramientas de programación de GNU son mucho más completas, e incluyen multitud de comandos que vamos a ir comentando a lo largo de este tutorial.

Al acabar este tutorial el lector debería de haber aprendido a compilar y depurar sus aplicaciones, crear librerías, medir el rendimiento, e incluso a combinar aplicaciones escritas en distintos lenguajes.

Download [enlace alternativo] [permalink]

Construcción de programas con make

Este tutorial pretende recoger toda la información necesaria para poder escribir ficheros Makefile usados para controlar la construcción de un programa con el comando make.

El documento empieza explicando las opciones más básicas para ir profundizando en ellas poco a poco. En los apartados 6 y 7 se acaban dando una serie de reglas prácticas que simplifican mucho el desarrollo de estos ficheros, con lo que aunque el lector no desee leer todo el documento le recomendamos que por lo sí que consulte estos apartados.

Download [enlace alternativo] [permalink]

Gestión de versiones con CVS y Subversion

El uso de un gestor de versiones se vuelve imprescindible para evitar la tediosa tarea de intercambiar entre los programadores los ficheros de código fuente que componen un proyecto según estos ficheros se van actualizando. Este documento intenta recopilar los conocimientos necesarios para usar y administrar los gestores de versiones CVS y Subversion.

La primera parte de este documento recopila los elementos generales que incorporan los gestores de versiones. La segunda y tercera parte del documento se centra en estudiar CVS y Subversion, respectivamente.

Download [enlace alternativo] [permalink]

El shell Bash

En este tutorial pretendemos enseñar el manejo de Bash, el Bourne Again Shell de GNU. Este shell es el que proporcionan por defecto muchos sistemas UNIX entre ellos Mac OS X o Linux.

Los ejemplos se explicarán sobre Mac OS X, pero debido a la interoperatividad que caracteriza a Bash, estos ejemplos deberían ser exactamente igual de útiles en otros sistemas UNIX. Cuando existan diferencias las indicaremos para que usuarios de otros sistemas puedan seguir correctamente este documento.

Al acabar este tutorial el lector debería de haber aprendido a usar las principales teclas rápidas, personalizar mucho más su terminal para hacerlo más manejable, y modificar o crear los scripts que configuran su sistema.

Download [enlace alternativo] [permalink]

Construcción de paquetes GNU

GNU ha definido un mecanismo estándar para construir paquetes software que puedan compilar en distintas plataformas. Una vez construido el paquete de acuerdo a las reglas que vamos a ver, podemos usar los conocidos comandos configure y make para compilar e instalar el software. Este documento pretende definir cuáles son estas recomendaciones.

Aunque los ejemplos se realizan sobre Mac OS X, la interoperatividad de este mecanismo de empaquetamiento debería permitir aplicar estas mismas reglas en otros sistemas con facilidad.

Al acabar este documento el lector deberá ser capaz de crear sus propios paquetes GNU de forma que se configuren, compilen, e instalen correctamente en distintas plataformas.

Download [enlace alternativo] [permalink]

Ensamblador del PowerPC con Mac OS X

Este tutorial nos enseña a programar en ensamblador del PowerPC de Mac OS X.

El tutorial empieza enseñando a manejar la herramienta de compilación que se distribuye con las herramientas de programación de Mac OS X y rápidamente se mete a estudiar la sistaxis del lenguaje con ejemplo aclaratorios.

Download [enlace alternativo] [permalink]

Seguridad, criptografía y comercio electrónico con Java

Este tutorial pretende recopilar los conceptos y tecnologías que se usan para conseguir crear sistemas informáticos seguros.

Muchos tutoriales de seguridad se centran en el uso de las herramientas administrativas. En este tutorial, aunque se evalúan bastantes herramientas desde el punto de vista administrativo, pretendemos llevar este estudio hasta el punto de vista del programador de estas herramientas. Con este fin hemos elegido las librerías criptográficas de Java, ya que creemos que son unas librerías completas, homogéneas, y que abarcan todos los aspectos de la criptografía moderna. Aunque el estudio se hace sobre Mac OS X, la interoperatividad del lenguaje Java permite llevar estos conceptos a otros sistemas operativos sin problemas.

Download [enlace alternativo] [permalink]

JNI (Java Native Interface)

Este documento es un tutorial de JNI (Java Native Interface), el mecanismo que permite ejecutar funciones C y C++ desde Java.

El tutorial supone que el lector conoce tanto los lenguajes Java como C, no es necesario saber C++, aunque el saber siempre ayuda. También supone que el lector esta familiarizado con el uso de herramientas de programación como gcc, java o javac

El tutorial trata cómo realizar estas operaciones en varios sistemas operativos aunque se centra sobre todo en dos: Mac OS X y Win32.

Download [enlace alternativo] [permalink]

Reportajes

Animamos a otros sitios web a poner enlaces a nuestros tutoriales, pero por favor no hagan copias de ellos en otros servidores, ya que si actualizamos los tutoriales seguirá habiendo copias antiguas en circulación durante mucho tiempo. Esto va en perjuicio de los lectores que cojan la copia antigua. Lo que sí recomendamos es poner enlaces directos los permalink de esta página.

Introducción al Entorno de Programación de Mac OS X

En este reportaje tenemos un resumen claro y rápido sobre las principales características, lenguajes y herramientas que existen para programar en Mac OS X.

El documento está claramente dirigido a programadores de otros entornos que quieran conocer cómo se programa en OS X.

Download [enlace alternativo] [permalink]

Control de corrupción y pérdida de memoria

Muchas aplicaciones fallan de forma impredecible debido a que se corrompe la memoria, o simplemente acaban agotando toda la memoria del sistema tras un periodo prolongado de uso debido a pérdidas de memoria. Este reportaje explica cómo podemos detectar los problemas de corrupción y pérdida de memoria en nuestras aplicaciones usando una serie de herramientas que existen en Mac OS X para tal fin.

Download [enlace alternativo] [permalink]

Programación de eventos del sistema de ficheros

En muchas ocasiones es útil para una aplicación saber cuándo otra aplicación modifica algún fichero del sistema de ficheros. Ejemplo de aplicaciones que pueden necesitar esta información serian un antivirus o una aplicación que necesita conocer cuándo han sido modificado externamente alguno de los múltiples ficheros que componen un proyecto. Este reportaje explica las APIs que proporciona Mac OS X para detectar estos eventos y actuar el consecuencia.

Download [enlace alternativo] [permalink]

Programación de rootkits en Mac OS X

Las aplicaciones ejecutan en el espacio de usuario ateniéndose a una serie de restricciones impuestas por el kernel. Sin embargo, el código que ejecuta en el kernel no tiene restricciones y puede cambiar cualquier aspecto del funcionamiento del sistema operativo. Un rootkit es un programa que se instala en el kernel del sistema operativo. Los rootkits son frecuentemente usados como malware ya que permite al atacante ocultar ficheros, procesos y conexiones de red, para ser transparente a las herramientas de administración. Esto hace que los rootkits sean extremadamente difíciles de detectar y de eliminar. Los rootkits también suelen habilitar un mecanismo de acceso (backdoor) así como sniffers de teclado y ratón. Este documento explica cómo se crea un rootkit.

Download [enlace alternativo] [permalink]

Ingeniería inversa en Mac OS X

La ingeniería inversa (reversing) son un conjunto de técnicas que nos permiten descubrir cómo funcionan las aplicaciones cuando no disponemos de su código fuente. Estas técnicas se utilizan frecuentemente para modificar el comportamiento de programas que incluyen funcionalidades no deseadas. Este reportaje describe estas técnicas en el entorno de Mac OS X.

Download [enlace alternativo] [permalink]

Configuración del sistema de arranque de Mac OS X

En este reportaje se estudia el proceso de arranque que sigue Mac OS X, y cómo podemos configurar servicios de Mac OS X para que se ejecutan automáticamente al arrancar la máquina.

Este documento está escrito para Mac OS X 10.4 o posteriores. Si quiere configurar una versión anterior debe consultar este otro reportaje.

Download [enlace alternativo] [permalink]

SystemStarter

En este reportaje se estudia cómo podemos configurar servicios de Mac OS X para que se ejecutan automáticamente al arrancar la máquina.

Este documento está escrito para Mac OS X 10.3 o anteriores. Debido a los cambios introducidos por Apple en el proceso de arranque de Mac OS X 10.4, si lo que quiere es configurar Mac OS X 10.4 o posterior debe consultar el reportaje Configuración del sistema de arranque de Mac OS X.

Download [enlace alternativo] [permalink]

ColorSync

En este reportaje se explica que es y cómo funciona ColorSync, el sistema de corrección de color de Mac OS X.

Este sistema de corrección de color permite obtener representaciones más precisas del color de las imágenes con las que estamos trabajando de forma transparente para el usuario. Antes de esto se describe detalladamente qué es la luz y el color, y cómo percibimos las personas los colores, así como técnicas de representación y corrección del color, como por ejemplo el soft-proofing.

Download [enlace alternativo] [permalink]

Quartz Extreme

En este reportaje se explica que es Quartz Extreme y que ventajas aporta.

Quartz Extreme no es más que el nombre que Apple da a su nuevo gestor de ventanas acelerado por hardware que incorpora desde Mac OS X 10.2.

Download [enlace alternativo] [permalink]

Trucos

Configurar locale en el terminal

Introducción

La librería gettext permite traducir un programa a muchas configuraciones del usuario: lenguajes, países y juegos de caracteres. Este truco revisa cómo configurar nuestro Mac usando la herramienta locale.

Un poco de programación

La librería gettext permite internacionalizar el código fuente de nuestros programas. Para ello, sentencias como esta:

printf("Hello %s.\n", name);

Deben de indicar el texto a internacionalizar usando el macro _():

printf(_("Hello %s.\n"), name);

El comando xgettext permite extraer estas cadenas en fichero .pot. el traductor traduce las cadenas del fichero .pot a distintos idiomas, y nos entrega el fichero renombrado a la extensión .po

El programador usar msgfmt para compilar el fichero .po para generar un fichero .mo. el fichero .mo se distribuye junto con el programa, y es la forma de que el programa pueda mostrar mensajes en el la configuración del usuario.

Nombres locale

La librería gettext la usan la mayoría de las aplicaciones GNU, y especialmente las de terminal. Para que un programa de terminal muestre mensajes adaptados a la configuración de usuario, es necesario que este configure locale. A Continuación vamos a ver cómo se haría.

Para empezar podemos consultar nuestra configuración actual:

$ locale
LANG=
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=

El valor "C" en las variables de configuración de locale indica que se use el valor hardcoded (por defecto) con el que se compiló el programa. Se llama "C" porque la mayoría de los programas están escritos en lenguaje C.

Además del valor "C", las variables de configuración de locale pueden tomar valores de la forma "en_US" donde las 2 primeras letras indican el idioma y las 2 segundas el país. Por ejemplo, para español de España se usaría "es_ES".

El valor de las variables de configuración también pueden incluir opcionalmente el juego de caracteres a usar. Por ejemplo, "es_ES.UTF-8" indica que queremos usar el juego de caracteres UTF-8.

Podemos obtener un listado de todos los posibles valores locale con el comando:

$ locale -a

Variables de entorno locale

La librería gettext consulta las variables de configuración en este orden:

  1. LANG
  2. LC_xxx, (LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES, ...)
  3. LC_ALL
  4. LANGUAGE

Por ejemplo, si LANG tiene un valor asignado, ya no consulta las demás. Sino consulta LC_xxx, etc.

El usuario sólo debería de configurar en su script de arranque (p.e. .profile) las variables de tipo LC_xxx. LC_ALL se reserva para scripts como configure o autoconf con el fin de sobrescribir la configuración del usuario.

LC_MESSAGES indica el lenguaje para los mensajes. Por ejemplo:

$ LC_MESSAGES="en_US" bison
bison: missing operand after `bison'
Try `bison --help' for more information.

$ LC_MESSAGES="es_ES" bison
bison: falta un operando después de `bison'
Pruebe `bison --help' para más información.

LC_CTYPE indica la configuraciones para funciones C como tolower(), toupper() and isalpha(), etc. LC_COLLATE se usa para indicar la configuración para ordenar caracteres. Por ejemplo, el siguiente comando muestra el path de los ficheros usando LC_CTYPE=C:

$ svn status
? content/files/Parc_Gu?\204?\136ell.jpg

Vemos que el nombre del fichero no representa bien símbolos UTF-8. Para resolverlo podemos hacer:

$ export LC_CTYPE=UTF-8
$ svn status
? content/files/Parc_Güell.jpg

El propósito de otras variables como LC_NUMERIC, LC_TIME, LC_MONETARY es más evidente.

Bibliografía

GNU gettext
Wikipedia gettext

Los paquetes de Mac OS X

Introducción

Los paquetes Mac OS X son ficheros con la extensión .pkg que básicamente contienen ficheros a instalar junto con una descripción de la ruta de los ficheros a instalar y sus permisos. Mac OS X utiliza los paquetes Mac OS X para instalar aplicaciones. Este truco clarifica cómo son y cómo usar estos paquetes.

Instalar y desinstalar paquetes

Para instalar un paquete basta con hacer doble click sobre él, pero también podemos usar el comando installer para instalarlo. Por ejemplo el siguiente comando instalaría el paquete iTunes.pkg en la raíz de nuestro sistema de ficheros:

$ installer -pkg iTunes.pkg -target /

Una ventaja de los paquetes es que Mac OS X lleva la cuenta de los paquetes instalados. Podemos consultar los paquetes instalados con el comando:

$ pkgutil --packages
apache.tomcat.6.0.26
com.adobe.pkg.FlashPlayer
com.apple.darwinstreamingserver
com.apple.MacOSX.lang.es
com.apple.pkg.AdditionalEssentials
com.apple.pkg.AdditionalFonts
com.apple.pkg.iTunesX
················

El comando devuelve el ID de cada paquete instalado. A partir de este ID podemos saber los ficheros que componen el paquete con el comando. Por ejemplo:

$ pkgutil --files org.virtualbox.pkg.vboxstartupitems
Library
Library/StartupItems
Library/StartupItems/VirtualBox
Library/StartupItems/VirtualBox/Resources
Library/StartupItems/VirtualBox/Resources/English.lproj
Library/StartupItems/VirtualBox/Resources/English.lproj/Localizable.strings
Library/StartupItems/VirtualBox/StartupParameters.plist
Library/StartupItems/VirtualBox/VirtualBox

Y también podemos desinstalar el paquete con el comando:

$ pkgutil --unlink org.virtualbox.pkg.vboxstartupitems

Formato de los paquetes

Hasta Mac OS X 10.4 los paquetes eran bundles estándar de Mac OS X, que son directorios especiales con los ficheros del paquete. La Figura 1 muestra el contenido de un paquete antiguo.

paquetes1.png
Figura 1: Paquete antiguo de Mac OS X

A partir de Mac OS X 10.5 su formato cambio a formato nuevo plano que es un formato de fichero comprimido con el comando xar. Podemos usar el comando xar para ver o extraer el contenido del paquete. Por ejemplo, para ver el contenido de un paquete nuevo hacemos:

$ xar -t -f iTunes.pkg

También tenemos la herramienta gráfica SuspiciousPackage para poder inspeccionar el contenido de un paquete (antiguo o nuevo) desde Finder. La Figura 2 muestra el contenido de un fichero de paquete plano.

paquetes2.png
Figura 2: Paquete nuevo de Mac OS X

El bill of materials

Mac OS X utiliza el término bill of materials (bom) para determinar los ficheros de paquete a instalar, actualizar o eliminar. Básicamente se trata de un log de ficheros instalados que después permite a Mac OS X desinstalarlos.

En el formato de paquetes antiguos este log se almacenaba en el directorio /Library/Receipts/boms. Con el formato de paquetes nuevos este log se ha pasado a almacenar en el directorio /var/db/receipts. Podemos usar el comando lsbom para ver el contenido de uno de estos ficheros.

$ lsbom /var/db/receipts/com.apple.pkg.CoreFP.bom
. 41775 0/80
./System 40755 0/0
./System/Library 40755 0/0
./System/Library/PrivateFrameworks 40755 0/0
./System/Library/PrivateFrameworks/CoreFP.framework 40755 0/0
./System/Library/PrivateFrameworks/CoreFP.framework/CodeResources

Tenga en cuenta que los paquetes (tanto en formato antiguo como nuevo) también contienen un fichero .bom, porque está es la forma de almacenar información sobre los permisos de los ficheros a instalar. Si por alguna razón se modifican los permisos de los ficheros del paquete podemos restaurarlos con el comando:

$ /usr/libexec/repair_packages --pkg com.birdstep.ZTEDataCardDriver --repair

Una vez que el paquete se instala, el fichero .bom se copia a Mac OS X para llevar un registro de los ficheros instalados y poder así desinstalarlos. Antes vimos que podemos desinstalar un paquete proporcionando su ID. Por ejemplo:

$ pkgutil --unlink com.birdstep.ZTEDataCardDriver

Este comando borra los ficheros pero no elimina el registro en el fichero bom. Podemos eliminar su registro en el fichero bom de Mac OS X usando el comando:

$ pkgutil --forget com.birdstep.ZTEDataCardDriver

Software Update

Software Update se basa en los ficheros bom y en los paquetes Mac OS X para llevar la cuenta del software que tenemos instalado. Este software compara los ficheros bom de nuestra máquina con los ficheros bom de un servidor de Apple para determinar si tiene que instalar nuevos paquetes en nuestro sistema.

Para determinar si hay actualizaciones disponibles podemos usar el comando:

$ softwareupdate -l

El comando softwareupdate también permite instalar un paquete con la opción -i, o bajarlo pero no instalarlo con la opción -d.

Añadir un usuario a un grupo

Mac OS X 10.6 no tiene en cuenta clásico fichero /etc/group para determinar los usuarios de un grupo. Este fichero sólo se tiene en cuenta cuando se arranca en modo monousuario. Este truco explica cómo configurar los grupos a los que pertenecen los usuarios.

Desde la línea de comandos

Podemos obtener los usuarios del sistema (y su uid) asociado con el comando:

$ dscl . list /Users uid

Podemos obtener los grupos del sistema (y su gid asociado) con el comando:

$ sudo dscl . list groups gid

Podemos conocer los grupos a los que nuestro usuario está asignado con el comando groups:

$ groups
staff com.apple.access_screensharing _developer _lpoperator _lpadmin _appserveradm admin _appserverusr localaccounts everyone

Para añadir o eliminar usuarios a grupos Mac OS X proporciona el comando dseditgroup. Este comando maneja los Directory Services y tiene la opción -o (operation) para indicar qué operación ejecutar (read, create, delete, edit, checkmember).

Para consultar los usuarios de un grupo tenemos la operacion read:

$ dseditgroup -o read admin
dsAttrTypeStandard:GroupMembers -
FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000
140D1472-7F93-472D-B221-D65A427F6FAA
561812D4-6182-46BC-A8CE-931BD77D5C0A
dsAttrTypeStandard:GroupMembership -
root
flh
fernando

Esta operación nos dice que hay tres usuarios en el grupo admin y nos da tanto su nombre como sus UUID.

Si queremos añadir un usuario a un grupo debemos usar la operación edit junto con la opción -a para indicar el registro que queremos añadir y -t para indicar que este registro es de tipo usuario. Por ejemplo, para añadir el usuario fernando al grupo wheel haríamos:

$ sudo dseditgroup -o edit -a fernando -t user wheel

Y para quitarlo del grupo:

$ sudo dseditgroup -o edit -d fernando -t user wheel

Herramientas gráficas

Apple proporciona gratuitamente las Server Admin Tools. Dentro de estas herramientas encontramos Workgroup Manager. Para administrar usuario y grupos visualmente debemos:

  1. Instalar Server Admin Tools
  2. Ejecutar /Applications/Server/Workgroup Manager
  3. Cuando se nos permite por el servidor a administrar indicamos localhost.
  4. Para ver todos los usuarios y grupos es muy recomendable seleccionar la opción de menú View | Show System Users and Groups.

Los servicios del menú de sistema Mac OS X

Este truco explica qué son y cómo se usan los servicios que aparecen en el menú de sistema de las aplicaciones Mac OS X.

Qué son los servicios Mac OS X

Los servicios del menú de sistema de las aplicaciones permiten a los usuarios acceder a la funcionalidad de una aplicación desde otra aplicación cliente. Las aplicaciones anuncian los servicios que proporcionan sobre uno o más tipos de datos. Las aplicaciones cliente (las que usan los servicios) no necesitan conocer por adelantado qué servicios existen en el sistema. La aplicación cliente simplemente necesita indicar los tipos de datos que usa. El menú de servicios se encarga de indicar qué servicios se pueden realizar sobre el tipo de dato que se está usando.

Ejemplos de servicios serían la encriptación de un texto, el reconocimiento de caracteres en un bitmap, o generar un mensaje del día. Cuando el usuario está manipulando un tipo de dato (p.e., escribiendo en una caja de texto), el usuario puede ejecutar los servicios que manipulan ese tipo de dato.

Ejemplo de servicios

Existen dos tipos de servicios: procesadores y proveedores.

Procesadores. Este tipo de servicios reciben datos y realizan una operación sobre ellos. Por ejemplo, si en una aplicación cliente seleccionamos un texto podemos enviárselo a alguien usando Mail como procesador. Si en la aplicación cliente seleccionamos una palabra podemos usar Dictionary para buscar la palabra, tal como muestra la siguiente figura:

processor-service1.png

Tras ejecutarse el servicio obtenemos la palabra resuelta en el procesaror (Dictionary):

processor-service2.png

Proveedores. Estos servicios devuelven datos a la aplicación cliente que les llama. Por ejemplo, podemos ejecutar desde TextEdit el servicio que captura parte de la pantalla:

provider-service1.png

Al terminar de ejecutarse el servicio obtenemos la captura de pantalla incrustada en la posición del cursor en TextEdit:

provider-service2.png

Cómo funcionan los servicios

La aplicación cliente y el servicio se ejecutan en procesos independientes. La forma de compartir datos es que las aplicaciones transportan datos a los servicios a través de un portapapeles privado. En caso de tratarse de un servicio proveedor, éste devuelve los datos usando el mismo portapapeles.

En concreto el proceso es el siguiente:

  1. Al seleccionar el menú del servicio en la aplicación cliente, ésta copia el texto o imagen seleccionado al portapapeles privado y se ejecuta la aplicación que proporciona e servicio (si ésta ya no está ejecutando).
  2. La aplicación que presta el servicio lee los datos del portapapeles privado y procesa los datos recibido.

Si el servicio es un proveedor:

  1. El servicio vuelve a copiar los datos procesados al portapapeles privado
  2. La aplicación cliente recoge los datos del portapapeles

Servicios standalone

Un servicio se puede ofrecer de dos formas:

  • Como parte de una aplicación (p.e., Mail). En este caso la aplicación suele tener la extensión .app y se suele guardar en la carpeta /Applications.
  • Como un servicio standalone. En este caso la aplicación no tiene interfaz de usuario y se limita a proporcionar el servicio. Las aplicaciones standalone suelen tener la extensión .service y se guardan en la carpeta /Library/Services (puede ser que tengamos que crear esta carpeta).

Un ejemplo de servicio standalone es SymbolycLinker, una aplicación que extiende Finder para crear enlaces simbólicos blandos UNIX.

Habilitar/deshabilitar servicios

No todos los servicios existentes están habilitados. Algunos se habilitan por defecto y otros tenemos que habilitarlos en System Preferences | Keyboard Shortcuts | Services. Como muestra la siguiente figura, estos servicios se agrupan por tipo.

habilitar-servicios.png

Cómo se declara un servicio

Las aplicaciones que proporcionan un servicio pueden estar instaladas en cualquier lugar del disco duro. Launch Services se encarga de identificar que una aplicación proporciona servicios consultando su fichero Info.plist. En base a esta información Mac OS X rellena el menú de servicios de las aplicaciones clientes. La siguiente figura muestra la entrada NSServices de la aplicación Dictionary. Esta es la entrada que usan las aplicaciones para indicar los servicios que prestan a otras aplicaciones clientes. Básicamente la entrada NSServices es un array de objetos NSDictionary. Cada servicio se describe en un objeto NSDictionary mediante una serie de claves y valores.

dictionary.png

X11 forwarding en Mac OS X

Este truco explica cómo utilizar SSH para hacer X11 forwarding. X11 forwarding permite ejecutar aplicaciones X11 situadas en un servidor remoto. Aunque el truco se centra en Mac OS X, los principios son los mismos en otros sistemas UNIX.

Cliente X y servidor X

Se llama servidor X al gestor de ventanas X11. Se llama cliente X a una aplicación gráfica X11 (p.e. xclock). Tenga cuidado, es muy frecuente liarse al interpretar estos términos al revés. Recuerde que el servidor X siempre se ejecuta en su máquina local y necesita de un teclado y una pantalla. Por su parte el cliente X es una aplicación que se puede estar ejecutando en su máquina local o en remoto. En Mac OS X el servidor X es la aplicación X11.app situada en la carpeta Utilities.

Las aplicaciones necesitan saber dónde está el servidor X, para ello usan la variable de entorno DISPLAY. Tres valores similares, pero no equivalentes, de esta variable son:

  • localhost:0 -> Conectar al puerto 6000 de localhost
  • :0 -> Connectar al socket de dominio UNIX /tmp/.X11-unix/:0
  • /tmp/launchd-xxxxxx/:0 -> Conectar al socket de dominio UNIX /tmp/launchd-xxxxxx/:0

La última opción es la que utiliza por defecto Mac OS X 10.5 y permite que no haga falta ejecutar X11.app. Cuando launchd detecta una conexión a este socket, lanza X11. Por ejemplo, en mi máquina obtengo el valor:

$ echo $DISPLAY
/tmp/launch-v6IuEo/:0

Una vez entendidos los principios básicos, vamos a ver cómo se configura el cliente X y el servidor X.

Configuración de la máquina remota

En la máquina remota podemos ejecutar fácilmente aplicaciones de consola a través de SSH. En este apartado vamos a explicar cómo configurar la máquina remota para poder ejecutar aplicaciones X11 (clientes X) cuyas ventanas se muestren en la máquina local (servidor X). Para ello tenemos habilitar X11 forwarding editando el fichero /etc/ssh/sshd_config, y reemplazando la entrada:

#X11Forwarding no

Por la entrada:

X11Forwarding yes

La otra cosa que tenemos que hacer es reiniciar el acceso remoto (sshd). Para ello podemos usar la opción Enable Remote Login del panel Sharing de System Preferences. Alternativamente podemos ejecutar el comando:

$ kill -HUP `cat /var/run/sshd.pid`

Configuración de la máquina local

En la máquina local primero conviene comprobar que podamos conectarnos a la máquina remota:

$ ssh flh@dymas.ii.uam.es

En este caso, para hacer X11 forwarding basta con añadir la opción -X (en mayúsculas, ya que -x en minúsculas deshabilita el X11 forwarding):

$ ssh -X flh@dymas.ii.uam.es

Ahora podemos ejecutar un cliente X en la máquina remota y ver si SSH hace X11 forwarding correctamente, nuestro servidor X (X11.app) deverá mostrar la ventana del cliente X remoto:

$ xclock

Observe que en la sesión SSH en la máquina remota la variable DISPLAY vale algo así como:

$ echo $DISPLAY
localhost:10.0

Esto significa que el servidor X está en el screen 10 del servidor de ventanas 0 de la máquina remota (localhost). El servidor SSH (sshd) se encargará de hacer forwarding al servidor X de nuestra máquina local.

Variables de entorno desde Finder

Cuando lanzamos una aplicación desde el terminal, resulta fácil fijar sus variables de entorno. Sin embargo, esta operación se puede complicar cuando es Finder quien debe fijar las variables de entorno. En este truco explicamos cómo fijar variables de entorno en las aplicaciones que ejecuta Finder.

Algunas aplicaciones requieren variables de entorno para funcionar correctamente. En este truco usaremos como ejemplo a NetBeans, y supondremos que queremos de pasarle valores en las variables de entorno PATH y CLASSPATH.

Una primera opción es fijar las variables de entorno en el terminal y ejecutar la aplicación desde el terminal:

$ export CLASSPATH=$CLASSPATH:.:/Library/Java/Home/lib/xjparse-1.0.jar
$ export PATH=$PATH:/usr/local/sw/bin
$ open /Applications/Development/NetBeans.app

Sin embargo, en ocasiones preferimos poder ejecutar la aplicación haciendo doble click en su icono con Finder. En este caso tenemos tres alternativas:

  1. Fijar variables de entorno para todos los procesos del sistema.
  2. Fijar variables de entorno para todas las aplicaciones que ejecute Finder.
  3. Fijar variables de entorno para una determinada aplicación que ejecute Finder.

En el primer caso podemos añadir la una línea como la siguiente al fichero /etc/launchd.conf o /etc/launchd-user.conf.

setenv VBOX_USER_HOME /Volumes/autor/storage/VirtualBox

Si añadimos la línea a /etc/launchd.conf la variable de entorno será recibida por todos los procesos del sistema mientras que si la añadimos a /etc/launchd-user.conf la variable de entorno sólo será recibida por los procesos de usuario.

En el segundo caso podemos crear un fichero de propiedades en la ruta $HOME/.MacOSX/environment.plist. Para crearlo podemos usar la herramienta Property List Editor tal como muestra la Figura 1. Podemos usar la utilidad RDEnvironment para configurar estas variables gráficamente.

figura1.png

Figura 1: Property List Editor con el fichero environment.plist

La tercera opción es fijar esas variables para una única aplicación. En este caso, usando la opción Show Package Contents podemos editar el fichero Info.plist de la aplicación en cuestión (p.e. NetBeans) y añadir la propiedad LSEnvironment, la cual es un diccionario donde cada entrada representa una variable de entorno. La Figura 2 muestra el resultado de esta edición.

figura2.png

Figura 2: Property List Editor con el fichero Info.plist de NetBeans

Para que Finder vuelva a releer el bundle de la aplicación NetBeans debemos de actualizar su fecha, por ejemplo ejecutando el comando touch sobre la aplicación de la forma:

$ touch /Applications/Development/NetBeans.app

Xcode con Organizer

Xcode 3.0 ha introducido un gestor de proyectos alternativo llamado Organizer. Este truco explica cómo usar Organizer para compilar y ejecutar proyectos desde Xcode.

Introducción

Los proyectos que genera Xcode son proyectos con una estructura cerrada, y en consecuencia no reutilizable desde otras herramientas de programación. Muchos programadores se sienten más cómodos usando ficheros de proyecto abiertos y clásicos como puedan ser make o ant. Además, a muchos programadores les gusta controlar los comandos de terminal que se están ejecutando cuando compilan o ejecutan sus programas. Xcode 3.0 introduce Organizer, una forma de trabajar con una gran variedad de lenguajes de programación como si estuviéramos trabajando en el terminal, pero con las ventajas que aporta el usar un entorno de desarrollo.

Cómo usar Organizer

Para abrir Organizer ejecute Xcode y, sin crear ningún proyecto, use la opción de menú Window|Organizer para obtener la ventana de la Figura 1 (a). Debajo de la ventana encontramos tres botones: El primero permite añadir ficheros y directorios a Organizer. El segundo permite añadir acciones. El tercero permite editar el fichero seleccionado en el proyecto.

organizer1a.png
(a)
(b)

Figura 1: Organizer todavía no hace referencia a ningún proyecto

Como ejemplo vamos a crear un directorio vacío llamado saludos y vamos a añadir este directorio al proyecto usando la opción Add Existing Folder de la Figura 1 (b), o bien arrastrando el fichero desde Finder a Organizer. Después podemos usar la opción New File de la Figura 1 (b) para crear un fichero vacío al que podemos llamar saluda.c. También podemos usar el tercer botón de la Figura 1 (b) para editar su contenido tal como muestra la Figura 2.

organizer2.png
Figura 2: Proyecto simple con Organizer

Compilar con Organizer

Lo siguiente que tenemos que hacer es compilar el fichero saluda.c. Para ello tenemos que crear una acción en el botón Build de la barra de herramientas. Pinchamos en el botón Build y obtenemos un diálogo como el de la Figura 3.

organizer3.png
Figura 3: Crear una acción

Abajo encontramos las opciones del menú:

  • New Shell Script, permite indicar uno o más comandos a ejecutar.
  • Add Script File, permite indicar un fichero de script a ejecutar.
  • Add Automator Workflow, permite indicar un Workflow de Automator a ejecutar.

Usando la opción New Shell Script podemos indicar que queremos ejecutar el siguiente comando de compilación:

gcc *.c -o saluda

En caso de que nuestro proyecto tenga subdirectorios, en Directory de la Figura 3 podemos indicar en qué directorio deberá ejecutarse la acción. En concreto se pueden usar uno de estos valores:

  • Selection, el directorio seleccionado en Organizer cuando ejecutamos la acción.
  • Top Level Organizer Item, el directorio raíz del proyecto.
  • Defining Organizer Item, el directorio seleccionado en Organizer cuando creamos la acción.
  • Home Directory, el directorio home.
  • File System Root, el directorio raíz (/) del sistema.

Observe que también podemos cambiar el nombre de la acción que hemos creado e indicar una shortkey para esta opción.

Análogamente al botón Clean le podemos asignar la siguiente acción que borra todos los ficheros generados durante la compilación:

rm -r build
rm saluda

Y al botón Run le podemos asociar la acción:

./saluda

La Figura 4 muestra cómo a las acciones de Run también las podemos asociar argumentos que se pasarán al comando a ejecutar. Por ejemplo, en la Figura 4 pasamos el argumento "Hola mundo". También podemos indicar si al ejecutar el comando lo queremos hacer con depuración.

organizer4.png
Figura 4: Crear una acción de ejecución

Por último, el botón Action permite crear acciones adicionales. Por ejemplo, podemos crear acciones para subir o bajar ficheros de un repositorio de código fuente.

Usar ficheros de proyecto comunes

Cuando añadimos a Organizer una carpeta que contiene un proyecto, Organizer crea automáticamente acciones para ese proyecto. Si no nos gustan esas acciones siempre podemos modificarlas o borrarlas.

Actualmente Organizer, al menos, reconoce tres tipos de proyectos:

  • Proyectos Xcode. Si añadimos a Organizer un directorio que contenga un proyecto creado con Xcode, se crearán automáticamente acciones para compilar, limpiar, ejecutar e instalar el proyecto. Estas acciones llaman al comando xcodebuild con los parámetros adecuados para cada acción.
  • Proyectos make. Si añadimos a Organizer un directorio que contenga un fichero Makefile, se creará en el botón Build una acción que ejecuta el comando make all, y en el botón Clean otra acción que ejecuta el comando make clean.
  • Proyectos ant. Si añadimos a Organizer un directorio que contenga un fichero build.xml, se creará en el botón Build una acción que ejecuta el comando ant.

Referencias

"Xcode 3.0 User Guide". Apple Inc.

Makefiles on Xcode

Preferencias de aplicación útiles en Mac OS X

El comando defaults permite modificar el comportamiento de gran cantidad de aplicaciones de Mac OS X, e incluso del propio sistema operativo. En este truco pretendemos recopilar las preferencias más útiles. Si alguien conoce más preferencias especialmente útiles que no aparezcan aquí, por favor póngase en contacto conmigo.

El comando defaults permite leer y escribir preferencias escritas en ficheros de preferencias de los directorios /Library/Preferences/ y ~/Library/Preferences/.

En la siguiente tabla se resumen las preferencias más útiles que hemos recopilado.

defaults write com.apple.appstore ShowDebugMenu -bool true
Añade un menú de depuración a Mac AppStore.
defaults write com.apple.Safari IncludeDebugMenu 1
Tras reiniciar Safari, habilita un menu que permite depurar páginas web, incluida la opción Inspect Element
defaults write com.apple.Safari WebKitDeveloperExtras -bool true
Habilita otro botón de depuración válido para todas las aplicaciones WebKit-based, no solo Safari. Por ejemplo, Google Chrome.
defaults write com.apple.Safari WebKitInitialTimedLayoutDelay -float 0.25
Reduce el tiempo que tarda Safari en empezar a renderizar una página de 1 seg a 0.25 seg.
defaults write com.apple.finder AppleShowAllFiles -bool true
Tras reiniciar Finder se empiezan a mostrar todos los ficheros del disco aunque tengan el atributo V o empiecen por punto (p.e. .profile). Encontrará una mejor descripción de esta preferencia en este otro truco.
defaults write com.apple.dock single-app -bool true
Tras reiniciar Finder pasa al modo single-app en el que sólo se ve la aplicación activa.
defaults write com.apple.LaunchServices LSQuarantine -bool NO
Deshabilita el que Finder emita un warning la primera vez que intentamos abrir un fichero bajado de Internet.
defaults write com.microsoft.word NSQuitAlwaysKeepsWindows -bool false
Evita que los ficheros abiertos al cerrar la sesión se vuelvan a abrir al volver a entrar en la sesión
defaults write com.apple.finder _FXShowPosixPathInTitle -bool YES
Tras reiniciar Finder, hace que Finder muestre en la barra de título no sólo el nombre de la carpeta donde estamos situados, sino su path.
defaults write com.apple.dashboard mcx-disabled -boolean YES
killall Dock
Deshabilita Dashboard.
defaults write -g NSNavPanelExpandedStateForSaveMode -bool true
Por defecto el cuadro de diálogo guardar como se muestra sin expandir. Con esta preferencia el cuadro de dialogo se muestra expandido por defecto.
defaults write -g PMPrintingExpandedStateForPrint -bool true
Por defecto el cuadro de dialogo imprimir se muestra sin expandir. Con esta preferencia el cuadro de di?logo se muestra expandido por defecto.
sudo defaults write /System/Library/LaunchDaemons/com.apple.WindowServer EnvironmentVariables -dict-add CI_NO_BACKGROUND_IMAGE 1
sudo plutil -convert xml1 /System/Library/LaunchDaemons/com.apple.WindowServer.plist
sudo chmod 644 /System/Library/LaunchDaemons/com.apple.WindowServer.plist
En Mac OS X 10.5 elimina la transparencia del menú. Para que tenga efecto es necesario reiniciar el sistema para que se vuelva a cargar el servidor de ventanas.
defaults write NSGlobalDomain NSAutomaticWindowAnimationsEnabled -bool NO
Elimina el efecto 3D de animación al abrir una ventana introducido en Mac OS X 10.7.
defaults write com.apple.dock no-glass -boolean YES
killall Dock
En Mac OS X 10.5 elimina el efecto 3D que tiene el Dock cuando se sitúa en la parte de abajo.
defaults write com.apple.dock mouse-over-hilte-stack -boolean yes
killall Dock
Crea un efecto que permite trazar la posición del ratón en los stack de Mac OS X 10.5.
defaults write com.apple.iTunes AutomaticDeviceBackupsDisabled -bool true
Deshabilita el lento backup que iTunes hace cada vez que sincronizados con iPhone
defaults write com.apple.iTunes hide-ping-dropdown 1
Oculta el botín de Ping en iTunes. Poner a 0 para volver a mostrarlo.
defaults write com.stuffit.Expander allowVersionChecking -bool NO
Deshabilita la comprobación de versión (llamada a casa) que hace StuffItExpander capa vez que se ejecuta.
defaults write com.apple.CrashReporter DialogType none
Deshabilita el diálogo de CrashReporter que sale cada vez que una aplicación explota.
defaults write com.apple.dashboard devmode YES
Permite ejecutar Widgests fuera de Dashboard.

Thumbnails en imágenes

Este truco enseña cómo asociar un icono a una imagen con su thumbnail. Si para guardar sus imágenes no usa ningún software como iPhoto, sino que guarda sus imágenes directamente en carpetas, quizá este truco le resulte útil. El truco enseña a asociar un icono personalizado (con un thumbnail de la propia imagen) a cada fichero de imagen. De esta forma le resultará más fácil identificar el contenido de cada imagen.

Introducción

Finder muestra un icono por defecto como el de la Figura 1 (a) por cada imagen que encuentra. Podemos asociar un icono personalizado como el de la Figura 1 (b) a cada imagen con lo que la identificación de su contenido es mucho más fácil.



(a)



(b)

Figura 1: Icono por defecto e icono personalizado

En este truco veremos cómo crear un script bash que pone y quita iconos personalizados a las imágenes, y cómo crear un plug-in Automator que nos permita poner o quitar iconos personalizados desde Finder.

Poner y quitar thumbnails a imágenes

Podemos usar el comando /usr/bin/sips para poner un icono personalizado a una imágen de la forma:

$ sips -i fichero.jpg

Donde fichero.jpg es el fichero al que ponemos la imagen.

Para borrar el icono a una imagen, basta con borrar su resource fork:

$ echo -n "" > fichero.jpg/..namedfork/rsrc

El Listado 1 muestra un ejemplo de un script bash llamado poniconojpg que pone un icono personalizado a los ficheros recibidos. Para ejecutarlo podemos hacer:

$ poniconojpg fichero.jpg

En caso de recibir un directorio, el script busca los ficheros *.jpg (mayúsculas o minúsculas) que contenga ese directorio, y pone un icono personalizado a cada uno de ellos.

#!/bin/bash
# Este comando es un ejemplo escrito por Fernando Lopez
# para MacProgramadores

# Comprueba que se reciba al menos un argumento
if [ -z $1 ]; then
   echo "Indique fichero o directorio como argumento"
   exit 1
fi

# Ejecuta sips sobre cada argumento.
# Los argumentos pueden ser un fichero o directorio.
# Si un argumento es un directorio busca los *.jpg que contenga
for arg in "$@"
do
   for f in $(find $arg -iname "*.jpg")
   do
     if [ -a $f ]; then
        sips -i $f
     fi
   done
done

Listado 1: Script bash que pone iconos personalizados

El Listado 2 muestra otro script llamado quitaiconojpg. El script es parecido al Listado 1 pero, quita el icono personalizado a los ficheros de imagen recibidos (o a los ficheros de imagen contenidos en el directorio). Por ejemplo, si queremos quitar el icono personalizado a todas la imágenes contenidas en la carpeta album2006, hacemos:

$ quitaiconojpg album2006

#!/bin/bash
# Este comando es un ejemplo escrito por Fernando Lopez
# para MacProgramadores

# Comprueba que se reciba al menos un argumento
if [ -z $1 ]; then
   echo "Indique fichero o directorio como argumento"
   exit 1
fi

# Borra el resource fork de cada imagen. 
# Los argumentos pueden ser un fichero o directorio.
# Si un argumento es un directorio busca los *.jpg que contenga 
for arg in "$@"
do
   for f in $(find $arg -iname "*.jpg")
   do
     if [ -a $f ]; then
        echo -n > "$f/..namedfork/rsrc"
     fi
   done
done

Listado 2: Script bash que quita iconos personalizados

Crear un plug-in para poner iconos desde Finder

Automator, es una herramienta de programación (que se distribuye gratuitamente con las Developer Tools) la cual nos permite crear pequeñas aplicaciones en muy poco tiempo.

Podemos construir fácilmente un aplicación Automator, como la de la figura, que ejecute el script del Listado 1 al arrastrar ficheros con las imágenes (o bien una carpeta con las imágenes) sobre el icono de la aplicación.

Para construir esta aplicación ejecute Automator, concatene las acciones Get Selected Finder Items y Run Shell Script, tal como muestra la figura. La acción Get Selected Finder Items permite conocer los ficheros seleccionados en Finder cuando se ejecuta la aplicación Automator, o también, como va a ser nuestro caso, conocer los ficheros arrastrados sobre la aplicación Automator. Los ficheros seleccionados se pasan a la acción Run Shell Script que ejecuta el script sobre ellos. Para que los ficheros seleccionados se pasen como argumento, seleccione la opción Pass input as argument.

figura3.png

Cuando vaya a guardar la aplicación Automator con la opción File|Save As..., verá que está se puede guardar de dos formas:

  • Como un Workflow, lo cual le permite editar a posteriori la aplicación. Es decir, sería el equivalente al código fuente de un programa.
  • Como una Application, lo cual crea un ejecutable con un icono.

Guárdela como una aplicación con el nombre poniconojpg, para obtener una aplicación como la de la primera figura.

figura4.png

Un tercera opción es guardar la aplicación con la opción File|Save As Plug-in, en este caso puede generar un Plug-in de Finder como el de la figura que luego se podrá ejecutar sobre las imágenes o carpetas seleccionadas. Por desgracia Apple ha eliminado los Plug-in de Finder en Mac OS X 10.6 con lo que esta opción sólo está disponible en Mac OS X 10.5.

Análogamente puede crear usted otro plug-in automator para quitar los iconos a las imágenes.

HFS+

En este truco se estudian las distintas características de HFS+, el sistema de ficheros de Mac OS X. El estudio se hace tanto a nivel conceptual como a nivel práctico, utilizando para ello comandos de consola que ayudan a identificar estas características. Esperamos que conocer estas características le ayude a resolver y entender mejor problemas con los que los desarrolladores y usuarios avanzados se enfrentan a menudo.

Introducción

HFS Plus o HFS+ es el sistema de ficheros desarrollado por Apple para Mac OS X, y que reemplaza el antiguo HFS (Hierarchical File System). El nombre HFS+ es el usado en la documentación para programadores. En la documentación para usuarios suele usarse el nombre Mac OS Extended. Las principales ventajas que incluye HFS+ respecto a HFS son: dispone de un sistema de journaling, permisos al estilo UNIX, y los nombres de fichero se representan en Unicode (y no en Mac OS Roman). Como veremos, a partir de Mac OS X 10.4, además de permisos UNIX, se puede usar una ACL (Access Control List).

Resource fork y data fork

En Mac OS Classic cada fichero está compuesto por dos ficheros que comparten el mismo nombre: El resource fork y el data fork. El resource fork está formado por recursos, cada uno de los cuales se identifica con un código de cuatro letras que indica el tipo del recurso. El data fork es un fichero plano convencional. En Mac OS X se conservan estos dos fork, pero se utiliza con mucha más frecuencia el data fork. Podemos usar la herramienta ResKnife para consultar el resource fork y data fork de un fichero Mac OS X.

También podemos extraer el recurso de un fichero usando el comando /Developer/Tools/DeRez. Por ejemplo, para extraer el recurso de tipo icns del fichero donorfile.jpg, y guardarlo en el fichero tempicns.rsrc hacemos:

$ /Developer/Tools/DeRez -only icns donorfile.jpg > tempicns.rsrc

Si lo que queremos es guardar un recurso en el fichero podemos usar el comando /Developer/Tools/Rez. Por ejemplo, para poner un icono personalizado al fichero donorfile.jpg podemos usar los comandos:

$ /Developer/Tools/Rez -append tempicns.rsrc -o donorfile.jpg
$ /Developer/Tools/SetFile -a C donorfile.jpg

Más adelante veremos que el comando /Developer/Tools/SetFile sirve (entre otras cosas) para activar el atributo de fichero C (custom icon).

Por último podemos consultar el resource fork de un fichero con el comando /Developer/Tools/RezDet. Por ejemplo:

$ RezDet -l donorfile.jpg
"donorfile.jpg": 'icns' (-16455) [52110]
The resource fork of donorfile.jpg appears to be OK.

Desde la línea de comandos podemos acceder al data fork y al resource fork usando como nombre de fichero fichero/..namedfork/data y fichero/..namedfork/rsrc respectivamente. Por ejemplo, si tenemos el fichero cosas.txt con data y resource fork, podemos acceder al data fork de dos formas:

$ cat cosas.txt
Una prueba
$ cat cosas.txt/..namedfork/data
Una prueba

Y para acceder al resource fork usamos:

$ cat cosas.txt/..namedfork/rsrc
99'?T,2BNDL

Muchos comandos UNIX de Mac OS X (p.e. el comando cp) copian sólo el data fork. Si queremos que se copie el resource fork debemos usar el comando /usr/bin/ditto (disponible en cualquier sistema Mac OS X), o el comando /Developer/Tools/CpMac (disponible sólo con las Developer Tools).

Type code, Creator code, y Launch Services

En Mac OS Classic (y después lo heredó Mac OS X) cada fichero HFS tiene asociado un type code que es un código de cuatro letras indicando el tipo del fichero, y un creator code que es otro código de cuatro letras el cual indica qué aplicación creó el fichero. Podemos consultar estos códigos sobre un fichero de ejemplo con el comando:

$ /Developer/Tools/GetFileInfo P1010008.JPG
file: "/Volumes/Autor/home/Desktop/P1010008.JPG"
type: "JPEG"
creator: "Bwv2"
attributes: avbstclinmedz
created: 01/01/1904 00:00:00
modified: 03/18/2007 08:40:08

En el ejemplo el type code es JPEG, y el creator code es Bwv2 (Goldberg). También podemos usar el comando /Developer/Tools/SetFile para modificar estos valores.

Launch Services es el servicio de Mac OS X que se encarga de abrir un fichero o programa cuando hacemos doble click sobre ellos. Este servicio primero consulta el creator code, y si la aplicación con este creator code está disponible lanza esta aplicación. Si no usa alguna aplicación que se haya registrado como capaz de abrir el type code. En el ejemplo anterior, esto significa que, de estar disponible Goldberg (cuyo creator code es Bwv2), se usará esta aplicación para abrir el fichero, y en caso contrario se usará cualquier aplicación que pueda abrir ficheros de tipo JPEG.

La Tabla 1 muestra ejemplo de type code y creator code comunes.

Type code Descripción Creator code Descripción
TEXT Fichero de texto plano ttxt Text Edit
JPEG Imagen JPEG adrb Address Book
TIFF Imagen TIFF wrbt iCal
PDF Fichero PDF emal Mail
W8BN Microsoft Word MSWD Microsoft Word
XLS8 Microsoft Excel XCEL Microsoft Excel
APPL Aplicación DmWr Dream Weaver
BNDL Bundle MOZB FireFox

Tabla 1: Type code y creator code comunes

En Mac OS X se añadió también la posibilidad de que Launch Services tenga en cuenta la extensión del fichero. Esto permite trabajar con ficheros procedentes de otras plataformas (o de Internet), que no llevan asociado type code ni creator code. En general, las aplicaciones Carbon suelen usar el type code y creator code, mientras que las aplicaciones Cocoa suelen usar la extensión del fichero. Más especificamente, Launch Services sigue las siguientes reglas:

  1. Si el fichero tiene un creator code, y su aplicación está disponible, ésta será la aplicación que se use para abrir el fichero.
  2. Si el usuario ha especificado una aplicación preferida para abrir el fichero (usando el dialogo Get Info), ésta será la aplicación con la que se abrirá.
  3. Si no, Launch Services mira la extensión del fichero y usa la aplicación por defecto para abrir los ficheros con esta extensión. Esta aplicación por defecto también se configura desde el dialogo Get Info.
  4. Si no existe aplicación preferida para esta extensión consulta el type code, y en caso de existir usa la aplicación preferida para este type code.
  5. En caso contrario aparece un diálogo preguntando con qué aplicación abrir el fichero.

En el caso de las aplicaciones, estas siempre tienen el type code APPL, y su creator code no indica con qué aplicación abrirlas, sino qué creator code tienen los ficheros que generan (p.e. MooV para películas QuickTime). Además, en el caso de las aplicaciones el type code y creator code no se consultan con /Developer/Tools/GetFileInfo, sino que está información está dentro del bundle de la aplicación, en concreto puede estar en dos sitios:

  • Algunas aplicaciones usan el fichero PkgInfo para almacenar ocho bytes correspondientes al type code y creator code de la aplicación.
  • La forma más moderna usa el fichero Info.plist para almacenar el type code (en la propiedad CFBundlePackageType) y el creator code (en la propiedad CFBundleSignature). Esta segunda forma incorpora la ventaja de permitir indicar a Launch Services tanto las extensiones como los type codes de los ficheros que abre la aplicación (en la propiedad CFBundleDocumentTypes).

Información posicional e indexado

Cuando Finder pasa por una carpeta Mac OS X, crea un fichero .DS_Store donde almacena información posicional de los iconos en la carpeta. Este fichero no es visible desde Finder (ya que Finder nunca muestra los ficheros cuyo nombre empieza por punto), pero sí que es visibles desde el terminal.

La creación de este fichero ha sido muy criticada por los usuarios avanzados de Mac OS X. Especialmente se ha criticado que se crea este fichero cuando nos conectamos a un servicio de ficheros compartidos como Samba, AFP o NFS. Para evitar que Finder cree este fichero cuando nos conectamos a un servicio de red podemos cambiar la propiedad:

$ defaults write com.apple.desktopservices DSDontWriteNetworkStores true

Por desgracia no existe forma de evitar su creación en carpetas locales.

Spotlight permite realizar búsquedas tanto por nombre de fichero como por su contenido. Para poder realizar las búsquedas rápidamente es necesario indexar el contenido de todos los ficheros del sistema. En ocasiones conviene que Spotlight no indexe determinados directorios para lo cual disponemos de dos opciones.

  • Usar la opción System Preferences | Spotlight | Privacy para indicar directorios del disco que no queremos indexar.
  • En el caso de las unidades externas (como los discos USB) podemos crear un fichero llamado .metadata_never_index en la raíz de la unidad para indicar que no queremos que ésta se indexe.

En este último caso es recomendable ejecutar el comando mdutil con la opción -E para borrar los índices de la unidad que no vamos a indexar. Por ejemplo:

$ mdutil -E /Volumes/FER_PEN
/Volumes/FER_PEN:
Indexing and searching disabled.

Atributos de fichero

La mayoría de los sistemas de ficheros permiten asociar atributos a los ficheros. En este apartado vamos a ver qué atributos pueden tener los ficheros en HFS+, y con qué comandos podemos leer y modificar estos atributos.

La Tabla 2 resume los atributos de fichero que soporta HFS+. Podemos usar el comando /Developer/Tools/GetFileInfo para consultar los atributos de un fichero. Por ejemplo:

$ cd Desktop
$ /Developer/Tools/GetFileInfo Xcode
file: "/Volumes/Autor/home/Desktop/Xcode"
type: "fapa"
creator: "xcde"
attributes: AvbstClinmedz
created: 04/12/2006 21:55:32
modified: 04/12/2006 21:55:32

figura1.png
Los atributos que estén activos aparecen en mayúscula. En el ejemplo anterior Xcode es un fichero colocado en el escritorio con el atributo A (alias) y C (Icono personalizado) activamos. El hecho de ser un alias hace que aparezca una fecha en la parte inferior izquierda como la de la figura.

Atributo Descripción
a
Alias
b
El directorio contiene un bundle
c
Icono personalizado (se permite en carpetas)
d
Fichero localizado en el escritorio (Mac OS Classic 6)
e
Extensión oculta (se permite en carpetas)
i

Inicializado. Finder ha dado una localización a este fichero. Este atributo lo usa sólo Finder. Cuando está activado indica que el fichero contiene recursos de base de datos ('BNDL', 'FREF', 'open', 'kind'...) que no han sido añadidos todavía a la base de datos del escritorio.

l
Bloqueado (locked)
m
Compartido. Si el fichero tiene desactivado este flag indica que puede tener datos en su resource fork, y en consecuencia no se puede compartir en una red. Si el flag está activado indica que está compartido en una red, y en consecuencia no se puede escribir en su resource fork.
n
El fichero no tiene recurso INIT. Indica que el fichero no contiene elementos que modifiquen el arranque de Mac OS Classic.
s
Fichero de sistema
t
Fichero stationery pad
v
Fichero invisible (se permite en carpetas)
z
Fichero ocupado (se permite en carpetas)

figura2.png
La forma de almacenar el icono personalizado es distinta en el caso de los ficheros que en el de los directorios. En ambos casos se activa el atributo C, pero en el caso de los ficheros se almacena en el resource fork un recurso de tipo icns con el icono. Aunque el tipo de recurso situado en el resource fork tiene cuatro letras, no debemos confundirlo con el type code o creator code del fichero. En el caso de las carpetas, se crea dentro de la carpeta un fichero Icon\n con los atributos C y V (invisible), y en el resource fork de este fichero se almacena un recurso de tipo icns con el icono.

El atributo B (bundle) lo usan las aplicaciones y bundles (add-ons) para que una carpeta sea vista por Finder como un único fichero.

Podemos pedir que no se muestre la extensión de un fichero activando el atributo E (extensión oculta). Para que estas extensiones se oculten es necesario desactivar la opción de Finder de mostrar las extensiones de todos los ficheros (situada en Preferences | Advanced). Algunas extensiones (p.e. .app) se ocultan incluso sin activar el flag E, pero para ello debemos haber indicado a Finder que no muestre las extensiones de todos los ficheros. Este atributo se puede modificar desde el diálogo Get Info.

El atributo L (que también se puede modificar desde el diálogo Get Info) permite crear ficheros cuyo contenido no se puede modificar.

En atributo T (que también se puede modificar desde el diálogo Get Info) permite crear un fichero que sirva como template. Si un fichero tiene este atributo, cuando se abre la aplicación crea una copia de su contenido en otro fichero, y esta copia es la que podemos modificar y guardar.

Existen tres situaciones en las que Finder no muestra algunos de los ficheros de la jerarquía de ficheros:

  • Los ficheros cuyo nombre empieza por punto (p.e. .profile) nunca los muestra Finder.
  • Los fichero que tiene el atributo V no se muestran en Finder.
  • Por último existen ciertos ficheros que están cableados dentro de Finder para que nunca se muestren (p.e. /automount).

Podemos desactivar el atributo V en algunos directorios de la raíz para que sí que los muestre Finder. Por ejemplo, los directorios /bin, /sbin y /usr tienen activo este atributo. Podemos desactivar este atributo ejecutando:

$ sudo SetFile -a V /bin /sbin /usr

Ahora (tras cerrar y volver a lanzar Finder), estos directorios serán accesibles desde Finder.

En Mac OS X Snow Leopard, Apple ha ocultado la carpeta Library del usuario. Los usuarios avanzados pueden desocultar esta carpeta con el comando:

$ SetFile -a v $HOME/Library

Nota: En Mac OS X Lion, Apple cambió la forma de ocultarlo, y para desocultarlo debemos usar:

$ chflags nohidden $HOME/Library

También es posible indicar a Finder que queremos ver todos los ficheros (aunque cumplan las reglas de ocultación anteriores) modifiando las preferencias de usuario, que no son más que ficheros de propiedades (de los cuales suele existir uno por cada aplicación) almacenados en la carpeta ~/Library/Preferences. En concreto, para pedir a Finder que muestre todos los ficheros modificamos esta preferencia de usuario, con el comando:

$ defaults write com.apple.finder AppleShowAllFiles TRUE

Atributos extendidos

A partir de Mac OS X 10.4 se han introducido los atributos extendidos, que son pares clave-valor que se pueden asociar a cualquier objeto del sistema de ficheros (ficheros, directorios, enlaces simbólicos, ...). La clave es una cadena UTF-8 acabada en NULL que puede tener hasta 128 bytes. El valor es un puntero a un buffer (textual o binario) cuya longitud no está limitada.

Cuando se escribió este truco sólo se podía acceder a los atributos extendidos a través de la capa BSD, en concreto con la familia de funciones getxattr(), setxattr(), removexattr() y listxattr(). Es de esperar que en un futuro se permita el acceso a estos atributos desde Carbon y Cocoa.

Apple proporciona unos comandos de ejemplo de uso de estos atributos aquí, que vamos a estudiar. Mac OS X 10.5 añadió la opción -@ al comando ls para poder listar los atributos extendidos. Mac OS X también introdujó el comando xattr que permite ver el contenido de los atributos extendidos. Para usar estos comandos, lo primero que tenemos que hacer es descomprimir este fichero, compilarlo, e instalar los comandos setx, lsx y rmx en algún directorio dentro del PATH. Por ejemplo:

$ make
$ sudo cp setx lsx rmx /usr/local/bin

Ahora podemos crear un fichero de prueba:

$ cat > prueba.txt
Este fichero sirve para probar los atributos extendidos
^D
$ cat prueba.txt
Este fichero sirve para probar los atributos extendidos

A continuación podemos usar setx para añadir atributos al fichero:

$ setx nombre Fernando prueba.txt
$ setx edad 33 prueba.txt

Y ahora podemos usar lsx , ls -l@ o xattr para ver los atributos extendidos:

$ lsx prueba.txt
3 edad 33
9 nombre Fernando
$ ls -@l prueba.txt
-rw-rw-r--@ 1 fernando staff 62 Jan 24 21:59 prueba.txt
edad 3
nombre 9
$ xattr -l prueba.txt
edad:
00000000 33 33 00 |33.|
00000003
nombre:
00000000 46 65 72 6E 61 6E 64 6F 00 |Fernando.|
00000009

El comando lsx nos muestra por cada atributo extendido: la longitud del valor, la clave y el valor. El comando xattr nos muestra el valor tanto en hexadecimal como en ASCII.

Tambien podemos usar rmx para borrar los atributos extendidos:

$ rmx edad prueba.txt
$ lsx prueba.txt
9 nombre Fernando

Los atributos extendidos forman parte del sistema de ficheros, con lo que no se crear ficheros adicionales:

$ ls -la
drwxr-xr-x 49 fernando admin 1666 Apr 1 .
drwxrwxr-x 11 root admin 476 Sep 2 ..
-rw-r--r-- 1 fernando admin 62 Apr 1 prueba.txt

Ni entradas en el resource fork:

$ ls -l prueba.txt/..namedfork/rsrc
-rw-r--r-- 1 fernando admin 0 Apr 1 prueba.txt/..namedfork/rsrc

Además, los comandos UNIX preservan los atributos extendidos al copiar un fichero:

$ cp prueba.txt prueba2.txt
$ lsx prueba2.txt
9 nombre Fernando

En sistemas de ficheros anteriores o distintos a HFS+, los metadatos (resource forks, flags, atributos de fichero), y ahora también los atributos extendidos, se guardan en ficheros con el prefijo "._". Pero en HFS+, todos estos metadatos se guardan en el propio sistema de ficheros. Por ejemplo, si creamos atributos extendidos en una unidad MS-DOS:

$ hdiutil create -size 50K -fs MS-DOS -volname DOS dos.dmg
$ hdiutil attach dos.dmg
/dev/disk1 /Volumes/DOS
$ cd /Volumes/DOS/
$ touch prueba.txt
$ setx autor "Fernando Lopez" prueba.txt
$ lsx prueba.txt
15 autor Fernando Lopez

Vemos que se ha creado un fichero ._prueba.txt para almacenar el atributo extendido:

$ ls -la
drwxrwxrwx 1 fernando fernando 16384 Apr 1 .
drwxrwxrwt 6 root admin 204 Apr 1 ..
-rwxrwxrwx 1 fernando fernando 4096 Apr 1 ._prueba.txt
-rwxrwxrwx 1 fernando fernando 0 Apr 1 prueba.txt

Podemos evitar que se copien estos ficheros (al usar cp) y que se guarden dentro de un .tar al crear el fichero comprimido. Para ello debemos exportar las siguientes variables de entorno:

$ export COPYFILE_DISABLE=true
$ export COPY_EXTENDED_ATTRIBUTES_DISABLED=true

Flags BSD

Además de los atributos de fichero y de los atributos extendidos, HFS+ soporta otro tipo de atributos heredados del mundo de BSD llamados flags de fichero. Estos flags de fichero se fijan con el comando chflags, y se resumen en la Tabla 3.

Flags Descripción
hidden Fichero oculto para Finder
nohidden Fichero visible para Finder
arch Fichero archivado
opaque Sólo es útil al usar la opción union al montar un sistema de ficheros.
nodump Sólo es útil en combinación con el comando dump
uchg Fichero inmutable por parte del usuario
uappnd Fichero en el que el usuario sólo puede añadir datos al final
schg Fichero inmutable por parte del superusuario
sappnd Fichero en el que el superusuario sólo puede añadir datos al final

Tabla 3: Flags de fichero

Los flags nohidden y hidden aparecen con Mac OS X 10.7 y permiten ocultar y desocultar un fichero para Finder. Estos flags BSD modifican el atributo de fichero V (accesible con GetFileInfo) activándolo o desactivándolo.

En Mac OS X 10.7, Apple ha ocultado la carpeta Library del usuario. Los usuarios avanzados pueden desocultar esta carpeta con el comando:

$ chflags nohidden $HOME/Library

El flag uchg es equivalente al atributo de fichero L (Lock), y de hecho activando uno se activa el otro. Su finalidad es evitar que el usuario pueda modificar un fichero con este flag activado. Para activarlo sobre un fichero documento.txt hacemos:

$ chflags uchg documento.txt

Podemos ver los flags BSD activos con el comando ls y la opción -lo:

$ ls -alo
drwxr-xr-x 51 fernando admin - 1734 Apr 2 .
drwxrwxr-x 11 root admin - 476 Sep 2 ..
-rw-r--r-- 1 fernando admin uchg 0 Apr 2 documento.txt

Para desactivar un flag ponemos un no delante del flag:

$ chflags nouchg documento.txt

El flag schg es similar a uchg, pero sólo puede ser fijado por root o por un usuario que ejecute sudo. Sin embargo es mucho más difícil desactivar este flags, ya que para hacerlo deberemos reiniciar la máquina en modo monousuario.

Si lo que queremos es que a un fichero (p.e. fichero de log) sólo se le puedan añadir datos al final, pero no modificar lo ya escrito podemos activar el flag de usuario uappnd o de sistema sappnd.

Permisos UNIX y ACL

Los permisos UNIX son una forma tradicional de indicar los permisos de acceso sobre un fichero que permite mayor grado de personalización que el modelo de permisos tradicional de UNIX: r (read), w (write), x (execute), a nivel de usuario, grupo y todos.

El comando umask permite consultar o cambiar una máscara de permisos que se restan a 777 para obtener los permisos efectivos con los que por defecto se crea un fichero:

$ umask
0022

Mac OS X viene preinstalado con la mácara 022 (el primer cero se ignora), que significa que los ficheros y directorios se crearán por defecto con los permisos rwxr-xr-x.

Por desgracia el comando umask sólo afecta a los ficheros y directorios creados desde el terminal. A partir de Mac OS X 10.5.3 es posible indicar la máscara de permisos con los que cualquier proceso crea los ficheros y directorios. Esto se consigue asignando una máscara de permisos a launchd (el proceso padre 1 que crea los demás procesos). Para ello debemos indicar los permisos de launchd en el fichero:

$ cat /etc/launchd-user.conf
umask 002

En este ejemplo hemos cambiado la máscara de permisos de 022 a 002 para que todos los usuarios de nuestro mismo grupo tengan permiso de escritura sobre los ficheros que creemos. Esto es muy útil si tenemos varias cuentas de usuario y queremos compartir el permiso de escritura entre las distintas cuentas.

Ojo: En man launchctl se explica el uso de los ficheros launchd.conf y launchd-user.conf. En el caso del comando umask Apple recomienda usarlo en launchd-user.conf. Su uso en launchd.conf implicaría modificar esta máscara en todos los procesos del sistema, lo cual es un riesgo de seguridad.

Muchos usuarios prefieren el modelo de permisos de UNIX porque lo consideran lo suficientemente flexible para sus necesidades, además d e ser más simple que el modelo las Access Control List (ACL) que vamos a ver a continuación. Uno de los motivos por los que se introdujeron las ACL en Mac OS X 10.4 fue para poder usar el modelo de permisos de Active Directory implementado en Microsoft Windows.

Una ACL es una lista ordenada de reglas que controlan el acceso a un fichero. Cada regla especifica tres cosas:

  1. Un actor (usuario o grupo).
  2. El acceso, que indica si el permiso se activa o se deniega (usando los valores allow o deny).
  3. Un permiso (las posibles permisos se resumen en la Tabla 4).

A cada regla también se la llama Access Control Entry (ACE).

Permiso Descripción Objetos
read Abrir para lectura Todos excepto directorios
write Abrir para escritura Todos excepto directorios
append Abrir para escritura al final Todos excepto directorios
execute Ejecutar script o programa Todos excepto directorios
delete Borrar el objeto del sistema de ficheros Todos
chown Cambiar los permisos del fichero Todos
readattr Leer atributos de fichero Todos
writeattr Escribir atributos de fichero Todos
readextattr Leer atributos extendidos Todos
writeextattr Escribir atributos extendidos Todos
readsecurity Leer la ACL Todos
writesecurity Escribir la ACL Todos
list Listar el contenido del directorio Directorios
search Buscar un fichero por nombre en el directorio Directorios
add_file Añadir un fichero al directorio Directorios
add_subdirectory Añadir un subdirectorio al directorio Directorios
delete_child Borrar un fichero del directorio Directorios

Tabla 4: Tipos de permisos de acceso de una ACE

Las reglas se evalúan en orden hasta que la regla se puede aplicar (es decir, el actor y el permiso coinciden). La primera regla que es aplicable determina la decisión. Si ninguna regla se puede aplicar, entonces se usan los permisos tradicionales de UNIX para decidir el acceso.

Los ficheros al crearse sólo tienen permisos UNIX. Esta precedencia de las ACL permite modificar los permisos UNIX sólo cuando definimos una ACE para el fichero. Téngase en cuenta que los permisos de UNIX no se tienen en cuenta a no ser que ninguna regla de la ACL se cumpla. Esto puede confundir al usuario ya que los permisos UNIX son ignorados si una regla de la ACL se cumple.

El que las reglas ACL se comprueben antes que los permisos UNIX tiene la ventaja de que podemos denegar el que una aplicación modifique un fichero. Por ejemplo, si queremos que los usuarios fernando y flh no puedan borrar el fichero de configuración VirtualBox.xml podemos hacer:

$ chmod +a "fernando deny delete" VirtualBox.xml
$ chmod +a "flh deny delete" VirtualBox.xml

Este truco permite que la aplicación VirtualBox no borre su fichero de configuración y lo recree con permisos de sólo escritura para el usuario que está ejecutando VirtualBox.

Las reglas se evalúan en orden hasta que la regla se puede aplicar (es decir, el actor y el permiso coinciden). La primera regla que es aplicable determina la decisión. Si ninguna regla se puede aplicar, entonces se usan los permisos tradicionales de UNIX para decidir el acceso.

Téngase en cuenta que los permisos de UNIX no se tienen en cuenta a no ser que ninguna regla de la ACL se cumpla. Esto puede confundir al usuario ya que los permisos UNIX son ignorados si una regla de la ACL se cumple.

En Mac OS X 10.4 las ACL están por defecto desactivadas. A partir de Mac OS X 10.5 las ACL están por defecto activadas. Si queremos activar o desactivar las ACL tenemos que ejecutar el comando fsaclctl sobre el sistema de ficheros en el que queramos activarlas. Por ejemplo, para activar las ACL sobre la raíz de nuestro disco hacemos:

$ sudo /usr/sbin/fsaclctl -p / -e

La opción -p indica el directorio donde está montada la unidad en la que queremos activar las ACL. La opción -e activa las ACL, y la opción -d desactivaría las ACL. En Mac OS X 10.6 las ACL están por defecto activadas y el comando fsaclctl ha sido eliminado.

Para estudiar el uso de las ACL, podemos crearnos un sistema de ficheros de prueba, y activar sobre este sistema de ficheros las ACL:

$ hdiutil create -size 1024K -fs HFS+ -volname ACLable acl.dmg
$ hdiutil attach acl.dmg
/dev/disk1s2 Apple_HFS /Volumes/ACLable
$ sudo /usr/sbin/fsaclctl -p /Volumes/ACLable/ -e

Después creamos un fichero en este sistema de ficheros, y vemos que el único que tiene permiso de escritura es el usuario fernando, aunque todos pueden leerlo:

$ cd /Volumes/ACLable/
$ touch documento.txt
$ ls -la
drwxr-xr-x 4 fernando fernando 170 Apr 1 .
drwxrwxrwt 6 root admin 204 Apr 1 ..
-rw-r--r-- 1 fernando fernando 0 Apr 1 documento.txt

Podemos usar el comando chmod con la opción +a para añadir ACEs al fichero. Por ejemplo, si queremos que el usuario carolina pueda escribir en el fichero documento.txt podemos crear la regla:

$ chmod +a "carolina allow write" documento.txt

Podemos listar las reglas de un fichero pasando al comando ls la opción -le:

$ ls -le documento.txt
-rw-r--r-- + 1 fernando fernando 4 Apr 2 documento.txt
0: user:carolina allow write

Obsérvese que no hace falta crear una ACE para que fernando pueda escribir en el fichero, ya que fernando es el dueño del fichero, y los permisos de UNIX (que se ejecutan cuando no se cumple ningún ACE) le conceden este permiso.

En este momento carolina puede escribir en el fichero, pero no puede borrar o añadir datos al fichero. Podemos añadir ACEs para que tenga también estos permisos:

$ chmod +a "carolina allow delete,append" documento.txt
$ ls -le documento.txt
-rw-r--r-- + 1 fernando fernando 44 Apr 2 documento.txt
0: user:carolina allow write,delete,append

Obsérvese que no necesitamos añadir un ACE que dé permiso de borrar ni añadir a fernando, ya que el permiso de escritura UNIX también implica poder borrar y añadir al final del fichero. Tampoco necesitamos dar permiso de lectura a carolina ya que los permisos UNIX se lo dan.

Un problema que tienen las ACL es que no existe un usuario comodín, con lo que si queremos crear una regla que a todos los demás usuarios no les permita leer el fichero tenemos un problema. Una solución sería denegar este permiso a los usuarios del grupo staff, pero un usuario podría salirse de este grupo, y poder así leer el fichero. Una solución mejor, que además es la recomendada, es usar las ACL sólo para conceder permisos, y denegar permisos desactivando los permisos de UNIX:

$ chmod -wr documento.txt

Ahora también deberíamos crear ACEs para que sólo fernando y carolina puedan leerlo y escribirlo:

$ chmod +a "fernando allow read,write,append,delete" documento.txt
$ chmod +a "carolina allow read" documento.txt
$ ls -le documento.txt
---------- + 1 fernando fernando 44 Apr 2 documento.txt
0: user:fernando allow read,write,delete,append
1: user:carolina allow read,write,delete,append

Para borrar una regla podemos usar la opción -a. Por ejemplo, si queremos quitar el permiso de lectura a fernando y carolina, y dárselo a todos los usuarios del grupo staff podemos hacer:

$ chmod -a "fernando allow read" documento.txt
$ chmod -a "carolina allow read" documento.txt
$ chmod +a "staff allow read" documento.txt
$ ls -le documento.txt
---------- + 1 fernando fernando 44 Apr 2 documento.txt
0: group:staff allow read
1: user:fernando allow write,delete,append
2: user:carolina allow write,delete,append

Obsérvese que las reglas se apilan, es decir, la última que añadimos es la primera en aplicarse.

También podemos indicar la posición de la regla a añadir con +a# n_regla, y de la regla a borrar con -a# n_regla. Por ejemplo, para borrar las tres reglas anteriores podemos hacer:

$ chmod -a# 2 documento.txt
$ chmod -a# 1 documento.txt
$ chmod -a# 0 documento.txt

Pero como las reglas se "mueven hacia arriba" cuando se borran, también podemos hacer:

$ chmod -a# 0 documento.txt
$ chmod -a# 0 documento.txt
$ chmod -a# 0 documento.txt

ACL soporta la herencia estática, que significa que cuando creamos un fichero en un directorio, éste hereda los ACEs del directorio. Si luego cambiamos los ACEs del directorio, no cambian los ACEs de los ficheros contenidos. La heréncia dinámica haría que al cambiar los ACEs del directorio cambiaran los ACEs de sus ficheros contenidos.

Para que los ficheros y subdirectorios contenidos en un directorio hereden los ACEs del directorio debemos de activan sobre el directorio alguno de los permisos de la Tabla 5.

Permiso Descripción Objetos
file_inherit Los pemisos del directorio los heredan los ficheros Directorios
directory_inherit Los permisos del directorio los heredan los subdirectorios Directorios
limit_inherit Los ACEs del directorio los heredan los ficheros y subdirectorios contenidos en el directorio, pero con el flag de herencia desactivado. Esto hace que si creamos un subdirectorio dentro de un subdirectorio, éste ya no herede el flag de herencia. Directorios
only_inherit Los permisos son heredados por los ficheros y subdirectorios contenidos en el directorio, pero no se aplican al propio directorio. Directorios

Por ejemplo, si tenemos un subdirectorio datos, podemos asignarle permiso de escritura para carolina, junto con el permiso de herencia para ficheros y subdirectorios haciendo:

$ chmod -rw datos
$ chmod +a "carolina allow write,file_inherit,directory_inherit" datos
$ ls -dle datos
d--x--x--x + 2 fernando fernando 68 Apr 2 datos/
0: user:carolina allow add_file,file_inherit,directory_inherit

Universal Type Identifiers (UTIs)

Mac OS Classic usa una combinación de dos enteros de 32 bits (representados como cuatro símbolos ASCII) para representar el tipo de un fichero: en concreto el type code y creator code del fichero.

Mac OS X mantiene el type code y creator code de un fichero, pero desde el año 2001 Apple empezó a recomendar el uso de la extensión de un fichero para identificar el tipo de un fichero. Podemos usar la utilidad RDDefaultApp para ver los tipos existentes en la base de datos de Finder. Esto permite trabajar con ficheros procedentes de otras plataformas (o de Internet), que no llevan asociado type code ni creator code, pero el uso de la extensión de un fichero para determinar su tipo presenta dos importantes inconvenientes:

  • La asignación de extensiones no está centralizada, y en consecuencia una misma extensión se puede usar para representar varios tipos de ficheros (ambigüedad). Por ejemplo los ficheros .doc pueden ser ficheros de Microsoft Word o de texto plano, o los ficheros .conf pueden tener configuraciones de distintos sistemas.
  • Al igual que ocurre con el type code y creator code, los tipos no tienen una organización jerárquica.

BeOS fue el pionero en introducir los tipos MIME para representar el tipo de los ficheros. MIME permitió organizar los tipos de los ficheros de forma estandarizada y jerárquica en dos niveles. Por ejemplo image/jpeg indica que se trata de un fichero JPEG. La organización jerárquica permite que una aplicación declare que es capaz de abrir todos los ficheros del primer nivel (p.e. image/*), o bién sólo determinados tipos (p.e. image/gif).

A partir de Mac OS X 10.3, Apple empezó a introducir lentamente un nuevo sistema de asignación de tipos llamado Uniform Type Identifiers (UTIs). UTI generaliza la idea de tipos MIME de BeOS. Las principales ventajas de este nuevo sistema de asignación de tipos son:

  • Es un sistema centralizado de asignación de tipos controlado por Apple, aunque extensible bajo solicitud a Apple, de forma parecida a como se hacía para definir nuevos type codes y creator codes.
  • Permite la organización jerárquica de tipos mediante relaciones de herencia (conforms to). Por ejemplo el tipo public.xml hereda de public.text, ya que un fichero XML es un tipo de fichero de texto.
  • Los tipos UTI no se aplican sólo a ficheros, sino a cualquier elemento del SO como puedan ser objetos en el portapapeles, unidades de disco, mensajes de correo, tarjetas vCard, etc.

Al igual que en BeOS, la organización jerárquica permite que, por ejemplo, si una aplicación puede abrir ficheros de tipo public.text, también pueda abrir ficheros de tipo derivado public.xml. El SO siempre elige la aplicación cuyo tipo es más específico para abrir un fichero. Por ejemplo, si un editor de texto es capaz de abrir ficheros public.text, y un editor de XML es capaz de abrir ficheros de tipo public.xml, lo ficheros XML se abrirán con la segunda aplicación.

La Figura 3 muestra un trozo de esta jerarquía de tipos en la que vemos que la jerarquía de tipos no coincide con la jerarquía de namespaces. Por ejemplo com.apple.quicktime.movie hereda de public.audiovisual.content. De hecho, no existe una única raíz en la jerarquía, sino que todo tipo que no hereda de otro tipo es en sí mismo una raíz.

figura3.png
Figura 3: Jerarquía de tipos UTI

Apple ha definido una lista bastante amplia de tipos UTI. Aquellos que empiezan por public representan estándares abiertos. En caso contrarío se usa el sistemas de namespaces inversos. Apple también ha definido tipos UTI para formatos de otras empresas como por ejemplo com.microsoft.windows-executable para ejecutables Windows, com.microsoft.word.doc para ficheros de Microsoft Word, o com.real.realmedia para vídeos de Real Media.

Además, un tipo puede heredar de varios tipos. Por ejemplo, en la Figura 4, el tipo de una aplicación Mac OS X es a su vez un bundle y un paquete.

figura4.png
Figura 4: Herencia múltiple en tipos UTI

Suponiendo que tenemos un fichero con el nombre carta.rtf, podemos consultar su tipo UTI preguntándoselo a Spotlight ejecutando el comando:

$ mdls -name kMDItemContentType carta.rtf
kMDItemContentType = "public.rtf"

Cuando creamos o copiamos un fichero en Mac OS X, Spotlight le asigna automáticamente un tipo UTI. En caso de que la extensión del fichero no sea conocida, Spotlight crea un nuevo tipo UTI con el prefijo dyn. De esta forma Spotlight garantiza que todos los ficheros tienen un tipo UTI.

Unir varios ficheros de vídeo

Muchas veces disponemos de varios ficheros de vídeo que queremos unir. Este truco muestra cómo hacer un pequeño programa Automator que realiza esta tarea.

El comando mencoder

El comando mencoder es un comando GPL que nos permite codificar los formatos de vídeo MPEG-1/2/4 y AVI. Por desgracia no codifica ni decodifica WMV, el formato de vídeo de Microsoft. Este comando no viene por defecto en Mac OS X, pero puede buscarlo en Internet.

En la web es muy común que los vídeos se distribuyen partidos en trozos más fáciles de bajar. Este comando permite volver a juntar varios vídeos que cumplan la condición de tener la misma resolución y formato.

Si tenemos los ficheros br01.mpg br02.mpg br03.mpg, podemos juntarlos en el fichero br_unido.mpg con el comando:

$ mencoder -oac copy -ovc copy -forceidx -of mpeg -o br_unido.mpg br01.mpg br02.mpg br03.mpg

Donde -oac copy y -ovc copy indican que no queremos transcodificar, sólo copiar los elementary stream de audio y vídeo a la salida. La opción -of indica el formato de salida al que codificar (avi o mpeg), y -o indica el fichero de salida. La opción -forceidx, aunque no suele ser necesaria, es útil porque fuerza a que se reconstruya el índice de sistema.

Un script para unir los videos

Para facilitar la ejecución de este comando (y construir el programa del siguiente apartado), podemos crear un script como el siguiente:

#!/bin/bash

# Este comando es un ejemplo escrito por Fernando López
# para MacProgramadores

# Comprueba que se reciba al menos dos ficheros por argumento
if [ -z $2 ]; then
   echo "No se recibieron argumentos suficientes"
   exit 1
fi

# Obtiene el nombre y extension del primer fichero
# (todos los ficheros deberian tener la misma extension)
# El nombre sirve para crear el nombre del fichero final
# La extension sirve para conocer el formato a que convertir
nombre=${1%.*}
ext=${1##*.}

# Determina el tipo de la extension
case $ext in
     mpeg|mpg) ext="mpg";;
     avi) ;;
     *) echo "Extension $ext no valida"; exit 1;;
esac

# Une los ficheros de video
nombre=${nombre}_unidos.${ext}
comando=/usr/local/bin/mencoder
if [ -x $comando ]; then
   $comando -oac copy -ovc copy -forceidx -of $ext -o $nombre $@   
else
   echo "No se encuentra $comando"
   exit 1; 
fi 

Puede descargar este script de aquí. El comando supone que mencoder se encuentra en la ruta /usr/local/bin/mencoder. Como argumento recibe los ficheros de vídeo a usar, y los une en otro fichero cuyo nombre es el mismo que el del primer fichero pasado, pero con el sufijo _unidos. Por ejemplo, para unir los ficheros de vídeo anteriores, ponga el permiso de ejecución a el fichero de script, y ejecute el script de la forma:

$ chmod +x unirvideos.sh
$ unirvideos.sh br01.mpg br02.mpg br03.mpg

El script generará el fichero br01_unidos.mpg.

Puede colocar este script en algún directorio que esté en el PATH, y ya podrá unir ficheros de vídeo desde la línea de comandos. Pero en el siguiente apartado veremos cómo ejecutar este script desde Finder.

Ejecutar mencoder desde Automator

unirvideos.pngAutomator, es una herramienta de programación (que se distribuye gratuitamente con las Developer Tools) la cual nos permite crear pequeñas aplicaciones, de este tipo, en muy poco tiempo.

Podemos construir fácilmente un aplicación Automator, como la de la figura, que al arrastrar sobre ella varios ficheros de vídeo los una, para lo cual se ejecuta el script anterior.

Para ello ejecute Automator, concatene las acciones Get Selected Finder Items y Run Shell Script, tal como muestra la figura. La acción Get Selected Finder Items permite conocer los ficheros seleccionados en Finder cuando se ejecuta la aplicación Automator, o también, como va a ser nuestro caso, conocer los ficheros arrastrados sobre la aplicación Automator. Los ficheros seleccionados se pasan a la acción Run Shell Script que ejecuta el script sobre ellos. Para que los ficheros seleccionados se pasen como argumento, seleccione la opción Pass input as argument.

automator.png

Cuando vaya a guardar la aplicación Automator con la opción File|Save As..., verá que está se puede guardar de dos formas:

  • Como un Workflow, lo cual le permite editar a posteriori la aplicación. Es decir, sería el equivalente al código fuente de un programa.
  • Como una Application, lo cual crea un ejecutable con un icono.

Guárdela como una aplicación con el nombre unirvideos, para obtener una aplicación como la de la primera figura.

plug-in.png

Un tercera opción es guardar la aplicación con la opción File|Save As Plug-in, en este caso puede generar un Plug-in de Finder como el de la figura que luego se podrá ejecutar sobre los ficheros de vídeo seleccionados.

dropscript.pngPor último comentar existe una aplicación GPL llamada DropScript que también permite crear iconos que, al arrastar sobre ella ficheros, también ejecuta un script. La figura muestra la forma que tienen las aplicaciones generadas por DropScript.

Para crear la aplicación de la última figura basta con que arrastre el fichero unirvideos.sh sobre la aplicación DropScript, para obtener otra aplicación llamada Dropunirvideos.

Lanzar y parar MLDonkey con Automator

Este truco muestra cómo hacer un pequeño programa Automator que arranque y pare el servidor de MLDonkey.

El demonio mlnet

Los demonios son programas (generalmente de consola) que quedan ejecutando en background. MLDonkey es un ejemplo de demonio muy utilizado en el mundo de Mac OS X para compartir datos y programas entre la comunidad. Lógicamente sólo se debe compartir datos y programas que no estén licenciados para explotación comercial.

El demonio de MLDonkey lo implementa el comando mlnet, el cual se puede obtener haciendo una sencilla búsqueda en Internet.

Suponiendo que el comando lo guardamos en el directorio /usr/local/bin, podemos ejecutar el comando así:

$ /usr/local/bin/mlnet
2006/09/17 19:39:35 Starting MLDonkey 2.7.7.CVS ...
2006/09/17 19:39:35 Language EN, locale UTF-8, ulimit for open files 256
2006/09/17 19:39:35 MLDonkey is working in /Users/fernando/.mldonkey
2006/09/17 19:39:35 [DNS] Resolving [ferbook] ...
2006/09/17 19:39:35 [DNS] Resolving [www.mldonkey.net] ...
2006/09/17 19:39:35 Logging in /Users/fernando/.mldonkey/mlnet.log
2006/09/17 19:39:36 Core started

El comando crea en $HOME/.mldonkey una carpeta con algunos ficheros de configuración, y carpetas donde depositar los datos y programas compartidos.

Una vez lanzado el demonio podremos acceder a el desde un browser usando la URL:

http://localhost:4080

Para parar el demonio basta con pulsar Ctrl+C sobre el terminal.

Por desgracia, si lo ejecutamos de la forma anterior, el comando no devuelve el control al terminal. Además produce una salida textual que puede, o no, interesarnos. Para evitarlo podemos lanzarlo de la forma:

$ nohup /usr/local/bin/mlnet >/dev/null 2>&1 &

Ahora se nos devuelve el control al terminal inmediatamente, y además no obtendremos mensajes por consola.

Al haber perdido el control del proceso, para pararlo podemos usar el comando:

$ killall mlnet

Tener que entrar en el terminal cada vez que queremos lanzar mlnet se vuelve un dolor. Para evitarlo podemos crear dos pequeñas aplicaciones en el escritorio como las que muestra la figura.

Lanzar y parar mlnet con Automator

lanzapara.png
Automator, es una herramienta de programación (que se distribuye gratuitamente con las Developer Tools) la cual nos permite crear pequeñas aplicaciones, de este tipo, en muy poco tiempo.

Nosotros vamos a crear dos aplicaciones llamadas lanza y para que ejecuten las operaciones de lanzar y parar el demonio mlnet.

Para ello ejecute Automator, elija la acción Run Shell Script, y cree un script como el de la figura, el cual ejecutará el comando nohup /usr/local/bin/mlnet >/dev/null 2>&1 &.
automator.png

Cuando vaya a guardar la aplicación Automator (p.e. con el nombre lanza), verá que está se puede guardar de dos formas:

  • Como un Workflow, lo cual le permite editar a posteriori la aplicación. Es decir, sería el equivalente al código fuente de un programa.
  • Como una Application, lo cual crea un ejecutable con un icono.

Análogamente puede crear otra aplicación Automator con el nombre para que ejecute el comando killall mlnet.

Control de versiones en Xcode con CVS

Introducción

Los sistemas de control de versiones usan el modelo cliente/servidor donde un servidor almacena los ficheros de uno o más proyectos, y varios clientes se conectan a él para bajar los ficheros (check out), modificarlos, y subir los cambios (check in).

Actualmente Xcode proporciona acceso a varias herramientas de gestión de versiones (Perforce, Subversions y CVS), en este truco sólo veremos como utilizar Xcode en CVS, que actualmente es la herramienta de control de versiones más utilizada en todo el mundo. Xcode no proporciona una interfaz para el servidor de CVS, sólo actúa como una interfaz gráfica de acceso a los comandos cliente de CVS.

En este truco supondremos que el lector sabe manejar la interfaz de comandos de CVS (en caso contrario le recomendamos leer primero el tutorial sobre Gestión de versiones con CVS y Subversion). Aun así a lo largo de este documento vamos a ir detallando los pasos para crear un repositorio CVS de ejemplo (usando la línea de comandos). De esta forma, un lector que no conozca (o que no recuerde) la interfaz de comandos de CVS debería poder seguir este truco.

Un repositorio de ejemplo

Para empezar necesitamos disponer de un repositorio donde aprender a manejar CVS desde Xcode. Aunque si el lector forma parte de una organización es posible que ya tenga uno configurado, en este truco vamos a crear un pequeño repositorio donde realizar nuestras pruebas.

Inicializar el repositorio

Un repositorio puede estar en la misma máquina o en otra máquina, en ambos casos la ubicación del servidor CVS se indica en la variable de entorno CVSROOT1. Para nuestros ejemplos bastará con disponer de un repositorio local.

Una vez tomada esta decisión vamos a proceder a crear un repositorio. En nuestro caso hemos decidido crear el directorio llamado repositorio directamente en el directorio home del usuario fernando. Ahora debemos exportar la variable de entorno CVSROOT con la ubicación del repositorio:

$ export CVSROOT=/Users/fernando/repositorio/

E inicializamos el repositorio:

$ cvs init

En el directorio repositorio deberá de haberse creado el subdirectorio CVSROOT con metainformación sobre el recién creado repositorio:

$ ls repositorio
CVSROOT

Crear un proyecto de ejemplo

El siguiente paso es crearnos una carpeta para el proyecto que queremos exportar. Debido a que CVS es independiente del lenguaje de programación podríamos crear un proyecto en cualquier lenguaje, pero en este caso hemos elegido el lenguaje Java para nuestros ejemplos. En concreto hemos creado un directorio llamado Mate con un sólo fichero Aritmetica.java donde vamos a implementar varias operaciones aritméticas:

$ cd Mate
$ cat Aritmetica.java
public class Aritmetica {
 public static double suma(int a, int b) {
    return a+b;
    }
}

Importar el proyecto

Una vez tenemos nuestro proyecto de ejemplo debemos de exportarlo al repositorio, para lo cual desde el directorio Mate ejecutamos el comando:

$ cvs import Matematicas rama_principal version_inicial
N Matematicas/Aritmetica.java
No conflicts created by this import

El comando import importa todos los ficheros del directorio actual y sus subdirectorios al repositorio creando en el repositorio un proyecto con el nombre Matematicas. Observe que el nombre del proyecto en el repositorio no tiene porque coincidir con el nombre de la carpeta donde tenemos guardado el proyecto. Además al comando debemos pasarle dos tag, el primero rama_principal es el nombre de la rama dentro del proyecto, el segundo version_inicial es el nombre de un tag que ponemos a los ficheros exportados.

Crear un sandbox para el repositorio

Una vez tengamos exportado el proyecto hemos acabado nuestro trabajo como administrador, ahora pasamos a ejecutar el role de un programador que se baja el repositorio a su máquina para trabajar con él.

El lugar donde un programador se baja un proyecto del repositorio es una carpeta que se suele conocer como sandbox. Auque no es necesario que así sea, lo normal es que el nombre del directorio del sandbox coincida con el nombre que puso el comando import al proyecto del repositorio cuando lo creó.

Vamos a bajarnos el repositorio directamente al directorio home con los comandos:

$ cd
$ cvs checkout Matematicas
cvs checkout: Updating Matematicas
U Matematicas/Aritmetica.java

El comando checkout recibe como argumento el nombre del proyecto en el repositorio y lo baja a un directorio con el mismo nombre:

$ ls -l Matematicas
-rw-r--r-- 1 fernando admin 109 Apr 22 18:19 Aritmetica.java
drwxr-xr-x 5 fernando admin 170 Apr 22 18:34 CVS

En cada directorio del sandbox siempre existirá un subdirectorio con el nombre CVS donde se almacena metainformación sobre el sandbox.

Crear un proyecto Xcode que accede al sandbox

Ya tenemos en el sandbox el proyecto, ahora debemos de crear un proyecto con Xcode que debe crearse sobre la carpeta del sandbox. Esto es así porque el subdirectorio CVS es el que le sirve a Xcode para poder conectarse al sandbox. Actualmente Xcode no es capaz de crear un sandbox haciendo algo equivalente a lo que el comando checkout ha hecho.

Para proceder a crear el proyecto desde Xcode, use la opción de menú File|New Project...|Java Tool, y cree un proyecto llamado igual que el sandbox para que se cree en la misma carpeta (véase Figura 1).

xcodecvs1.png
Figura 1: Crear un proyecto en el sandbox

Configurar el acceso al repositorio

Una vez tengamos creado el proyecto Xcode en el sandbox, lo siguiente que debemos hacer, antes de poder acceder a las opciones de repositorio desde Xcode, es configurar el SCM (Source Code Managenment). Para acceder a las opciones de SCM desde Xcode tiene una persiana de menú llamada SCM.

Antes de estar configurado el SCM la única opción de menú que tenemos es SCM|Configure SCM... Usando esta opción debemos de activar la opción Enable SCM e indicar el tipo de sistema de SCM en el campo SCM System. La Figura 2 muestra estas opciones.

También muchas veces resulta útil apartar los ficheros intermedios y los ficheros finales del sandbox, en este caso puede usar las opciones Place Build Product In y Place Intermediate Build Files para indicar otra ruta donde depositar estos ficheros.

xcodecvs2.png
Figura 2: Activar SCM en un proyecto

Activar o desactivar el acceso al repositorio

Si está trabajando en un lugar donde no tiene red quizá le convenga desactivar temporalmente el SCM usando la opción de menú SCM|Go Offline. Cuando vuelva a tener acceso al repositorio puede volver a activar el SCM con SCM|Go Online.

Trabajar con el repositorio

Ver el estado del repositorio

El smart group SCM (véase Figura 3) nos muestra el estado de los ficheros usando una sola letra para indicar su estado de acuerdo a la nomenclatura común de CVS (blanco actualizado, ? desconocido, A listo para añadir, U hay una versión más moderna en el repositorio, M ha sido modificado en local y puede subirse al repositorio, C conflicto debido a que ha sido modificado en local y por alguien más en el repositorio, R Listo para ser borrado del repositorio). De momento todos los ficheros aparecen marcados con ? porque ninguno de ellos forma parte del repositorio (el subdirectorio CVS le sirve a Xcode para conocer esto).

xcodecvs3.png
Figura 3: Estado de los ficheros del repositorio

Como muestra la Figura 4, también podemos ver la información de SCM de un fichero en las columnas de detalle del fichero. Pero en este caso la columna que da esta información no aparece visible por defecto y debemos usar la opción de menú View|Detail View Columns|SCM para que aparezca.

xcodecvs4.png
Figura 4: Vista de detalle de un fichero con la columna SCM activada

Nota: Puede que Xcode no le actualice correctamente la vista del estado de los ficheros, en ese caso puede usar la opción de menú SCM|Refresh Entire Project.

Añadir ficheros al repositorio

En este momento el repositorio está activo, pero el único fichero que ha generado el proyecto de Xcode (el fichero Matematicas.java) no está en el repositorio. Para añadirlo podemos seleccionar el fichero y usar la opción de menú SCM|Add to Repository. En este momento el fichero aparecerá marcado con una A, que significa que el fichero está listo para ser añadido al repositorio la próxima vez que hagamos un commit.

A continuación puede seleccionar el fichero y usar la opción de menú SCM|Commit Changes... para subir el fichero al repositorio. Se le pedirá que introduzca un comentario de commit que describa los cambios. Este comentario se almacena junto a la versión inicial del fichero. Más abajo veremos como consultar estos comentarios.

Una vez añadido el fichero al repositorio el campo de detalle de SCM aparecerá banco indicando que el fichero está actualizado y el fichero habrá desaparecido del SCM smart group. Si se pregunta por qué Apple ha implementado el extraño comportamiento de que los ficheros actualizados desaparecen del smart group SCM, la razón procede de que el comando cvs -n update no devuelve información sobre los ficheros actualizados, es decir en nuestro ejemplo el comando devuelve1:

$ cvs -n update
? Manifest
? Matematicas.1
? Matematicas.xcodeproj

Recuerde que en el repositorio inicial que creamos al principio de este documento creamos un fichero llamado Aritmetica.java que actualmente no forma parte del proyecto. Para que pase a formar parte del proyecto podemos usar la opción de menú Project|Add to project... El fichero debería aparecer marcado como actualizado ya que estaba correctamente subido al repositorio.

Bajar ficheros del repositorio

Cuando un fichero de nuestro proyecto aparece marcado con U significa que otro programador ha modificado el fichero y en este caso necesitamos actualizar los cambios en nuestro sandbox. Podemos actualizar el fichero de dos formas:

  • Seleccionando el fichero y usando la opción SCM|Update To|Latest...
  • Usando la opción SCM|Update Entire Project que actualiza todos los ficheros del proyecto existentes en el CVS.

Consultar las operaciones realizadas por Xcode sobre CVS

Podemos usar la opción de menú SCM|SCM Results para ver las operaciones a nivel de interfaz de comandos que Xcode ha realizado sobre el CVS (véase Figura 5). Para obtener una vista detallada de los comandos ejecutados puede necesitar tener que usar el botón que aparece abajo a la derecha. Observe que el comando que Xcode ejecuta no es cvs sino ocvs. El comando ocvs se creó cuando CVS no soportaba wrappers, los cuales permitían tratar una carpeta marcada con el atributo de paquete como un sólo fichero. Actualmente CVS soporta esta opción con lo que ocvs y cvs son equivalentes.

xcodecvs5.png
Figura 5: Vista de SCM Results

Ver las revisiones

Puede consultar las revisiones de un fichero del repositorio seleccionándolo y usando la combinación de teclas Command+I, o bien con la opción de menú SCM|SCM Info (véase Figura 7). En el panel de SCM aparecerá para cada revisión información sobre el número de revisión, autor, fecha y mensaje de commit. Si selecciona una determinada revisión debajo obtendrá una información más detallada.

Subir los cambios

Vamos a ver cómo se suben cambios a un fichero del proyecto. Para ello, tal como aparece en la Figura 6, vamos a eliminar los comentarios del fichero Matematicas.java, que por defecto introdujo Xcode cuando creó el proyecto.

Luego podemos subir los cambios al repositorio con la opción de menú SCM|Commit Changes...

xcodecvs6.png
Figura 6: Fichero Matematicas.java modificado

Si ahora volvemos a ver las revisiones del fichero Matematicas.java (con Command+I), la Figura 7 muestra el resultado, donde apreciamos que existen dos revisiones.

xcodecvs7.png
Figura 7: Revisiones de un fichero

Comparar revisiones

Xcode nos permite ver las diferencias entre dos revisiones de un fichero. Para ello podemos usar dos herramientas: O bien la opción SCM|Compare With..., o bien la opción SCM|Diff With... Ambas opciones de comparación se pueden ejecutar también desde el panel de propiedades de la Figura 7. En ambos casos la forma de comparar es la misma, seleccionamos un fichero y pedimos comparar la versión actual del sandbox con otra revisión.

La opción de comparar es la más visual (véase Figura 8). Por defecto se ejecuta una herramienta visual que viene con Xcode llamada FileMerge. También podemos modificar la herramienta de comparación a usar en las preferencias de Xcode, por ejemplo para usar BBedit.

xcodecvs8.png
Figura 8: Comparación de revisiones con FileMerge

La otra forma de comparar es obteniendo el resultado del comando cvs diff1, tal como muestra la Figura 9.

xcodecvs9.png
Figura 9: Comparación de revisiones con Diff

Borrar ficheros del repositorio

Si pedimos borrar un fichero del proyecto (usando la opción Edit|Delete) aparecerá un diálogo como el de la Figura 10 (a), entonces tenemos dos opciones:

  • Delete References nos permite borrar sólo la referencia que hace el proyecto al fichero, pero no borra el fichero del disco.
  • Delete References & Files borraría tanto la referencia que hace el proyecto al fichero como el propio fichero.

En este segundo caso, si el fichero está bajo control de un SCM aparecerá un segundo diálogo como el de la Figura 10 (b) donde se nos preguntará si queremos borrar también el fichero del repositorio.

Si pedimos borrar el fichero del repositorio el fichero quedará marcado con una R y sombreado en gris, como muestra la Figura 10 (c), de forma que para borrarlo definitivamente del repositorio deberemos hacer un commit (con la opción SCM|Commit Changes...), o bien podremos cancelar el borrado y recuperar el fichero con la opción SCM|Add to repository.

xcodecvs10a.png
(a)

xcodecvs10b.png
(b)

xcodecvs10c.png
(c)
Figura 10: Borrar ficheros del repositorio

Renombrar ficheros

Cuando renombramos un fichero bajo control de CVS, el fichero original es marcado con R indicando que será borrado del repositorio y el fichero nuevo será marcado con A indicando que el fichero será añadido al repositorio. Además renombrar un fichero inevitablemente hace que se pierda la información de log del fichero antiguo.

Para renombrar un fichero del proyecto puede usar la opción de menú File|Rename. En esta caso un mensaje de advertencia como el de la Figura 11 (a) le indicará que el fichero está bajo control de un SCM y que si renombra el fichero inevitablemente la información histórica de revisiones del fichero se perderá. Si aceptamos, y por ejemplo cambiamos el nombre de Aritmetica.java por Algebra.java, obtendremos el fichero antiguo marcado con R y el nuevo marcado con A, tal como muestra la Figura 11 (b). Después podemos usar la opción de menú SCM|Commit changes... para que los cambios se ejecuten definitivamente en el repositorio.

xcodecvs11a.png
(a)

xcodecvs11b.png
(b)

Figura 11: Renombrar un fichero bajo control de CVS

Subir el proyecto al repositorio

No sólo es posible subir los ficheros de código fuente a un repositorio, sino que otros ficheros como los de documentación también es muy común tenerlos en el repositorio.

Si usted trabaja en un proyecto donde algunos programadores usan Xcode y otros usan otra herramienta quizá no convenga que coloque el proyecto en el repositorio, pero si todos los programadores trabajan con Xcode sí que puede resultar útil compartir el proyecto. De esta forma cuando un programador añade un fichero al proyecto o cambia una opción de éste, todos los programadores se beneficiarán automáticamente del cambio. Debido a que los proyectos de Xcode (ficheros del bundle .xcodeproj) están escritos en texto plano, CVS gestiona bien los cambios cuando más de un programador cambia el proyecto a la vez. En este último apartado vamos a ver cómo se comparten los ficheros de proyecto en el repositorio.

El paquete de proyecto

Xcode guarda metainformación sobre el proyecto en un directorio con el atributo de paquete con la extensión .xcodeproj2. Por ejemplo, en nuestro ejemplo el proyecto Matematicas.xcodeproj tiene los ficheros que muestra la Figura 123.

xcodecvs12.png
Figura 12: Ficheros de un paquete de proyecto

Este paquete contiene dos ficheros a los que debemos prestar especial atención si queremos colocar un proyecto en el repositorio4: El fichero de proyecto y el fichero de usuario.

  • El fichero de proyecto (que tiene el nombre project.pbxproj) almacena información referente al proyecto como los ficheros que le componen, los targets, y opciones de compilación. Este fichero puede ser compartido por todos los programadores, y normalmente sí que se deberá poner en el repositorio si queremos compartir el proyecto.
  • El fichero de usuario (que tiene el nombre fernando.pbxuser) almacena información de personalización del usuario, como por ejemplo sus bookmarks, su target activo, o sus preferencias de edición. Cuando creamos un proyecto Xcode crea un fichero como éste con el nombre de la cuenta del usuario. Este fichero no debe ser compartido por los programadores, aunque opcionalmente se puede colocar en el repositorio si queremos poder trabajar con el mismo proyecto desde varias máquinas. Al existir uno por cada nombre de usuario no deberían de producirse conflictos.

Referencias

"Xcode User Guide". Apple Inc.

1 Puede consultar el tutorial sobre Gestión de versiones con CVS y Subversion para ver cómo se hace esto.

2 En versiones anteriores estos ficheros tuvieron las extensiones .xcode, .pbproj, .pbxproj.

3 Puede abrir un directorio con el atributo de paquete desde Finder pulsando con el botón derecho y eligiendo la opción Show Package Contents.

4 Todos estos ficheros pueden ser editados con la herramienta Property List Editor.

Usar cabeceras precompiladas

Los compiladores de C y C++ actualmente pasan la mayoría de su tiempo compilando una y otra vez cabeceras mucho más grandes que el código fuente del fichero .c o .cpp en sí. El compilador gcc de GNU a partir de la versión 3.3 incluye la posibilidad de usar cabeceras precompiladas, lo cual acelera mucho la compilación de programas C y C++. En este truco se explica cómo aprovechar esta nueva característica

Durante la explicación de este truco vamos a suponer que nuestros ficheros fuente incluyen en su mayoría el fichero <iostream> con las operaciones típicas de entrada/salida C++, y el fichero <math.h> con las operaciones matemáticas más normales.

En consecuencia hemos decidido crear un fichero precompilado con estos ficheros de cabecera con el fin de acelerar la compilación de nuestro proyecto.

El fichero de cabecera en general deberá incluir sólo ficheros de cabecera que cambien poco, preferiblemente sólo los que vienen con el compilador (los que se invluyen de la forma #include <...>), y no los ficheros de cabecera de nuestro programa (que se incluyen de la forma #include "..."), ya que si no tendría que recompilarse el fichero de caberera cada vez que modificáramos uno de nuestros ficheros .h

Los ficheros de cabecera precompilados tienen el mismo nombre que el fichero .h correspondiente, pero con el sufijo .gch Por ejemplo si creamos el fichero precompiled.h con las cabeceras comunes que incluye nuestro proyecto el fichero de cabecera precompilado se llamará precompiled.h.gch

El fichero que nosotros hemos creado como ejemplo es el siguiente:

$ cat precompiled.h
#include <iostream>
#include <math.h>
using namespace std;

Lo siguiente que tenemos que hacer es precompilar este fichero para lo cual ejecutamos:

$ g++ -c precompiled.h -o precompiled.h.gch

Lo cual nos crea el fichero precompiled.h.gch con todos los ficheros incluidos por precompiled.h precompilados.

Ahora si, por ejemplo, el fichero encuadre.cpp incluye el fichero precompiled.h cuando ejecutemos:

$ g++ -c encuadre.cpp -o encuadre.o

El compilador de GNU buscará en el directorio actual un fichero llamado precompiled.h.gch. Si lo encuentra lo usará, y sólo si no lo encuentra incluirá precompiled.h

Aquí conviene hacer varias apreciaciones: La primera es que para que el compilador de GNU use el fichero .gch que encuentre, éste deberá estar compilando exactamente con las mismas opciones con las que hemos lanzado la compilación de encuadre.cpp, es decir basta con que hubiéramos hecho:

$ g++ -O1 -c encuadre.cpp -o encuadre.o

Para que no nos acepte el fichero precompilado y use el fichero de cabecera sin precompilar.

La segunda es que el compilador de GNU requiere un fichero precompilado para cada dialecto de C (C, C++, Objective-C). Si quisiésemos que un fichero precompilado se usase por distintos dialectos de C necesitaríamos crear uno distinto para cada dialecto (usando la opción -x c-header, -x c++-header y -x objective-c-header, respectivamente). En este caso la forma de proceder es crear un directorio con el nombre precompiled.h.gch y dentro de él meter todos los ficheros precompilados para todos los dialectos que estemos usando (da lo mismo el nombre que demos a estos ficheros, gcc examina todos los ficheros del directorio en busca del que necesite).

La tercera apreciación es que si vamos a usar ficheros precompilados en un fichero Makefile conviene crear una regla que actualice los ficheros de cabecera como la siguiente:

encuadre.o: encuadre.cpp encuadre.h Matriz.h Punto.h precompiled.h.gch
precompiled.h.gch: precompiled.h
       $(CXX) $^ $(CXXFLAGS) -o $@

Desgraciadamente actualmente make no soporta el uso de reglas implícitas para los ficheros precompilados.

precompiled.png

Por último conviene comentar que Xcode también soporta el designar a un fichero como fichero que actúe como cabecera precompilada, para ello debemos de activar dos opciones del proyecto o del target que son:

  • Prefix Header (GCC_PRIFIX_HEADER) Indica que fichero de cabecera es el que debe precompilarse (en principio sólo soporta uno por proyecto que de hecho es lo normal). Por ejemplo aquí pondríamos precompiled.h. Esta opción no aparece por defecto en las opciones de Xcode con lo que debemos de usar el botón de añadir nueva opción y añadir la opción con clave GCC_PREFIX_HEADER y con valor precompiled.h
  • Precompile Prefix Header (GCC_PRECOMPILE_PREFIX_HEADER) Debemos de activar esta opción para que funcionen las cabeceras precompiladas dentro del proyecto o del target.

Apoderarse del superusuario de una máquina UNIX

Aquí se explica un truco que aprovecha un error en la configuración del PATH, por parte del administrador de una máquina UNIX, para apoderarse de su sistema. Este truco es válido para cualquier máquina UNIX incluida, como no, Mac OS X.

Nota: Este truco se explica con el fin de que los administradores de una máquina eviten que un usuario hostil viole la seguridad de su máquina, y nunca con el fin de que los usuarios aprendan a violar la seguridad de un sistema. En cualquier caso MacProgramadores no se hace responsable del mal uso que se pueda hacer de la información aquí suministrada.

Es muy típico que los administradores de las máquinas UNIX añadan al PATH de su máquina un "." con le fin de poder ejecutar los ficheros del directorio actual donde se encuentran. Si es este su caso recuerde que debe de hacerlo siempre al final del PATH y nunca al principio, es decir, en sus ficheros de configuración del shell (p.e. /etc/profile) debe de poner:

export PATH=/usr/local/bin:/usr/local/lib:/bin:/usr/local/sbin:/usr/sbin:/sbin:.

Y nunca:

export PATH=.:/usr/local/bin:/usr/local/lib:/bin:/usr/local/sbin:/usr/sbin:/sbin

Vamos a poner un ejemplo de como un usuario llamado judas se apodera del control de una máquina UNIX en la que su administrador no tuvo en cuenta este consejo.

En primer lugar al entrar judas en su nueva cuenta en la universidad se da cuenta de que le han asignado una cuenta de usuario en la que el primer campo del PATH es el directorio ".", como judas conoce este truco se dirige al fichero /etc/profile (del cual sólo tiene permiso de lectura) y comprueba eufórico que el administrador ha colocado de la forma no recomendada el PATH de la máquina.

Lo siguiente que hace judas es preparar una trampa al administrador para lo cual coloca en le directorio /tmp (en le que tiene permiso de lectura y escritura) un fichero con permiso de ejecución al que llama ls como el que sigue:

#!/bin/sh
if cp /bin/sh /usr/bin/.superdude >/dev/null 2>/dev/null
then
  chmod 4555 /usr/bin/.superdude
  rm -f $0
fi
exec /bin/ls ${1+$@}

Y finalmente modifica el permiso de ejecución de este script para que todo el mundo lo pueda ejecutar:

$ chmod a+x /tmp/ls

En este momento la trampa esta tendida. Ahora lo único que tiene que tiene que hacer judas es esperar a que el ingenuo administrador pase por el directorio /tmp y ejecute el comando ls. Si algún usuario se pasea por estos lares al estar el "." como primer campo del PATH se ejecutara el script de judas y no el verdadero /bin/ls, el comando cp fallará (ya que los usuarios no tienen permiso para escribir en el directorio /usr/bin) y simplemente ese usuario obtendrá el resultado de un ls en pantalla. Pero cuando el administrador pase por ahí y ejecute este comando ls, el comando cp funcionará, lo cual permitirá que se ejecute el cuerpo del bloque if y al fichero .supersede se le activará el bit de setuid, se borrará el malvado script de judas y el administrador obtendrá el resultado de un ls como normalmente.

Cuando judas descubra la existencia del nuevo fichero /usr/bin/.superdude lo único que tiene que hacer es ejecutarlo y boala, acaba de logarse como superusuario en la máquina.

Fink, gestión de paquetes GNU

Multitud de paquetes del mundo de GNU se están portando a Mac OS X. Un problema con el que se puede encontrar el usuario es el de buscar, compilar e instalar estos paquetes en su sistema, problema que se puede solucionar fácilmente usando el gestión de paquetes Fink.

El proyecto Fink es un proyecto que encontramos en la web:

http://fink.sourceforge.net/

Se trata de un gestor de paquetes que se encarga de todo el proceso de búsqueda, compilación, configuración, instalación y desinstalación de paquetes directamente de Internet.

De esta forma el usuario nunca tiene que preocuparse de buscar e instalarse el mismo manualmente estos paquetes.

Internamente Fink se basa en los gestores de paquetes de Debian dselect, dpkg y apt-get, aunque el usuario Mac OS X, si quiere, el único comando que tiene que usar es el comando fink.

Instalación de fink

Una vez que nos bajamos el fichero fink-0.4.0a-installer.dmg lo único que tenemos que hacer es doble click en el para montarlo como una unidad. Una vez montado, dentro de él encontramos el fichero FinkInstaller.pkg que al hacer doble click sobre él, ejecuta un asistente que instala fink y todos sus ficheros en el directorio /sw de nuestro disco.

Lo otro que tenemos que hacer es configurar las variables de entorno de Fink, para lo cual si usamos lal shell bash debemos añadir al fichero de configuración ~/.profile la entrada:

. /sw/bin/init.sh

Que llama a este script el cual carga todas las variables de entorno que necesita Fink. Una vez reiniciamos el terminal, el entorno de Fink está ya configurado.

Si por contra usamos tcsh debemos de añadir al fichero ~/.tcsh la entrada:

source /sw/bin/init.csh

Instalar y desinstalar paquetes

Una vez Fink está operativo podemos empezar usando el comando fink list para sacar un listado de todos los paquetes con que cuenta Fink.

$ fink list
Reading package info...
Information about 427 packages read in 2 seconds.
a2ps 4.12-4 Any to PostScript filter.
aalib 1.4rc4-5 Ascii art library
aalib-bin 1.4rc4-5 Ascii art library
aalib-shlibs 1.4rc4-5 Ascii art library
agqt 0.9.1-1 6's Spiffy AudioGalaxy Query Tool
amaya 5.3-2 W3C's Editor/Browser
·······················
·······················

Después podemos instalar o desinstalar paquetes usando los comandos fink install [paquete] y fink remove [paquete].

Por ejemplo podemos hacer:

$ fink install lynx

Y ya Fink se encarga de buscar el paquete en la red, bajárselo e instalarlo.

El lector puede usar man fink para ver que más opciones trae el comando fink.

Actualización de Fink

Una última observación, para actualizar Fink no debemos de bajarnos y instalar el programa de instalación de la última versión. los pasos correctos son:

1) Comprobar la versión de Fink que tenemos instalada con:

$ sudo fink --version
Package manager version: 0.10.0
Distribution version: 0.4.1

2) Si queremos instalar la última versión podemos usar el comando:

$ fink selfupdate

Si no tenemos la última versión de Fink, el la buscará en Internet y nos la instalará.

FinkCommander

Por último comentar que existe una buena herramienta freeware llamada FinkCommander que nos permite acceder a Fink desde una interfaz gráfica. Lo único que necesitamos para poder usar esta herramienta es haber instalado previamente Fink.

fink.png
Podemos bajar FinkCommander de:

http://finkcommander.sourceforge.net/

Combinaciones de teclas útiles durante el arranque de Mac OS X

Existen multitud de combinaciones de teclas que podemos usar durante el arranque de la máquina para cambiar su comportamiento. Por desgracia estas combinaciones están mal documentadas, con lo que hemos decidido reunir aquí todas las que encontremos. Si alguien conoce más combinaciones de teclas que no aparezcan aquí, por favor póngase en contacto con nostros

Esta tabla resume las combinaciones de teclas que hemos encontrado, algunas de las cuales son especialmente útiles:

Combinación de teclas Descripción
C Arrancar desde CD-ROM. Esta tecla se usa cuando por ejemplo queremos instalar o reinstalar el sistema operativo
H Arrancar desde disco duro. La opción por defecto si no se pulsa ninguna tecla
N Arrancar desde una unidad de red. Open Firmware debe de haber sido configurado correctamente para que funcione esta opción
T Modo "Target". Al hacerlo veréis el logo de firewire saltando por la pantalla, no es mas que nuestra máquina convertida en un disco Firewire. Estando en este modo, le enchufamos un cable desde otro ordenador y veremos un disco externo.
Z Arrancar desde la unidad Zip. Útil si estamos haciendo nuestro propio sistema operativo en esta unidad
Expulsar CD Si se mantiene pulsada durante el arranque expulsa el CD-ROM de la unidad de CD. Esto es especialmente útil cuando un CD-ROM se atasca y no hay forma de sacarlo. Alternativamente se puede dejar el botón del ratón pulsado mientras arranca la máquina
Shift Permite arrancar en modo a prueba de fallos. La tecla debe pulsarse justo después del campanazo inicial y hasta que sale el spin giratorio en pantalla. Deshabilita los login items y las extensiones del kernel no esenciales
Option Se nos muestra una lista de los sistemas operativos instalados, y nosotros podemos indicar con cuál arrancar. Útil si tenemos instalados otros sistemas operativos como Darwin o Linux
Command+V Muestra mensajes descriptivos de todo el proceso de arranque de Mac OS X (modo "verbose"). Se recomienda probarlo al menos una vez para ver como arranca Mac OS X "al estilo UNIX"
Command+S "Single User Mode". Arranca en modo consola monousuario. Especialmente útil para ejecutar comandos que sólo se puedan ejecutar en este modo como fsck
Command+Option+
Shift+Delete
Elude el arranque con el disco duro y arranca con CD o unidad de disco externa
Command+Option+
O+F
Nos permite acceder al Open Firmware de nuestra máquina. Después podemos usar el comando printenv para ver las variables de la configuración. Usando el comando setenv podemos cambiarlas.
"6"+"4"
"3"+"2"
Válidas para Mac OS X 10.6 en adelante. Permiten arrancar respectivamente el kernel en 64 bits y 32 bits. Por defecto Mac OS X 10.6 arranca en 32 bits (excepto Xserve).

Mostrar todos los ficheros en Finder

Con el fin de simplificar el uso de Mac OS X, Finder oculta los ficheros y directorios en los que normalmente el usuario no está interesado.

En este truco veremos como se pueden ver estos ficheros "ocultos".

Finder suele ocultar los ficheros más "UNIX" como puedan ser los directorios /etc, /bin, /lib, /usr, /var, etc, o bien los ficheros que empiezan por . (punto), y en general oculta todos los ficheros que considera no necesarios para el usuario. En concreto hay tres formas de que un fichero se oculte al Finder: Listarlo dentro del fichero /.hidden, que el nombre de fichero empiece por punto (p.e. .profile), o que el fichero tenga el atributo HFS+ de oculto activado.

Los usuarios avanzados pueden querer ver todos los ficheros en Finder, para lo cual simplemente hay que modificar el fichero de configuración com.apple.Finder.plist que se encuentra en el directorio ~/Library/Preferences. Este fichero es un fichero de configuración .plist (XML Property List) que se puede editar o bien a mano desde un editor de texto, o bien desde el Property List Editor, un programa que viene con las herramientas de desarrollo de Mac OS X, que sirve para editar estos ficheros.

En concreto debemos de poner la propiedad AppleShowAllFiles a true:
finder1.png

Otra posible forma de modificar esta propiedad es con el comando /usr/bin/defaults, un comando que permite modificar los ficheros de configuración que tiene el usuario en ~/Library/Preferences.

Podemos ejecutar este comando así:

$ defaults write com.apple.Finder AppleShowAllFiles -bool true

Una vez modificada esta propiedad debemos de reiniciar Finder, o bien volviéndonos a logar, o bien reiniciando Finder desde Command+Alt+Esc

Y ya podremos ver todos los ficheros y directorios de nuestro disco duro:

finder2.png

Como seguramente ya conozca el lector, las aplicaciones en Mac OS X, también son directorios (con la extensión .app) que aparecen en Finder al usuario como si fueran un único fichero.

Este truco que hemos comentado no permite que veamos el contenido de estos directorios, pero sí podemos verlo si pulsamos sobre la aplicación con el botón derecho del ratón con la tecla Ctrl apretada. Entonces aparecerá una opción llamada Show Package Contents que nos permite ver los ficheros de este directorio.

finder3.png

También hay otras formas de poder ver los directorios ocultos sin necesidad de cambiar esta opción de Finder. Una de ellas consiste en usar la opción de ménu de Finder Go|Go to Folder... que nos pregunta por el directorio que queremos abrir en Finder, y nos los abre aunque sea oculto:

finder4.png

Por último, comentar que tambien podemos usar el comando /usr/bin/open que en caso de que le pasemos el directorio de una aplicación lo que hace es ejecutarla:

$ open Applications/Internet/Internet\ Explorer.app

Pero si le pasamos un directorio nos los lo abre en Finder.

$ open /usr/include

Generar ficheros PDF con Mac OS X

En este truco se trata como podemos generar ficheros PDF con Mac OS X sin necesidad de más software que el propio Mac OS X.

Mac OS X utiliza un motor gráfico llamado Quartz, que renderiza todas las salidas a pantalla e impresora en formato PDF (Portable Data Format), una evolución de PostScript.

Podemos aprovechar esta característica para capturar una salida de impresora y mandarla a un fichero PDF. A continuación se indica como hacer esto.

En Mac OS X todos los cuadros de dialogo de imprimir tienen un botón Preview que permite mostrar el documento a imprimir en Preview, la aplicación Mac OS X que nos permite visualizar documentos PDF, además de otros formatos como JPG, GIF, PNG PICT y TIFF.

Preview tiene la opción de menú File|Save as PDF que nos permite guardar el documento en formato PDF.
pdf.png

Aunque programas como PDF Writer de Adobe tienen características adicionales, como firma digital de documentos o marcas de agua, este truco es suficiente para la mayoría de los usuarios.

Nota: Las Aplicaciones Classic no pueden aprovechar esta característica, pero si las aplicaciones Carbon.

Conexión desde Mac OS X a Windows con Samba

Mac OS X tiene la posibilidad de acceder al sistema de ficheros e impresoras compartidas de Windows. En este artículo se explica cómo realizar la interconexión del mejor sistema operativo del mundo con el ... vamos, con Windows.

El protocolo que utiliza Windows para compartir archivos e impresoras se llama SMB (Server Message Block), y ha sido implementado ya desde hace tiempo en los sistemas UNIX por el proyecto de código fuente abierto Samba. Actualmente Samba permite compartir ficheros y impresoras, dar servicio de nombres WINS, y actuar como primary domain controler de Windows NT. Recientemente Microsoft ha cambiado el nombre de SMB por el de CIFS (Common Internet File System). Cosas de que esté de moda Internet, porque este protocolo sólo funciona medio bien en redes locales, así que a través de Internet mejor ni intentarlo.

Nota: Windows XP en adelante utilizar un protocolo de envío de password firmado completo que da problemas con Mac OS X. Para conectar Windows a Mac OS X recomendamos deshabilitar esta opción como se explica aquí.

Antes de empezar a describir como usar Samba, vamos a presentar algunos términos importantes:

Workgroup. Es la forma en que Windows agrupa a sus usuarios en grupos de trabajos o dominios.

Nombre NetBIOS. Es un nombre que pone Windows a cada máquina conectada a través del protocolo NetBIOS de Microsoft.

Servidor WINS: Es un ordenador que actúa resolviendo nombres NetBIOS. En caso de no existir un servidor WINS los nombres se resuelven haciendo broadcast por la red local. El broadcast puede incrementar el tiempo que se tarda en encontrar otra máquina, si la segunda máquina tarda en responder a la consulta. Para evitarlo es útil disponer de un servidor WINS.

Recurso. Es una carpeta o impresora compartida.

Vamos a empezar viendo cómo conectarse a una carpeta compartida, para luego ver cómo configurar el servidor Samba. Para conectarse a una carpeta compartida en Windows tenemos dos formas: Usar Finder, o usar el terminal.

Usar Finder para acceder una carpeta compartida

Esta es la forma más fácil. Simplemente desde Finder usamos la opción Go|Connect to server..., o bien la tecla Command+K.

conectarsmb.png

Esto abre un diálogo como el de la figura donde indicamos la URL del recurso al que queremos conectarnos que tiene la forma:

Esto abre un diálogo como el de la figura donde indicamos la URL del recurso al que queremos conectarnos que tiene la forma:

smb://workgroup;usuario@nombrenetbios/recurso

workgroup es el grupo de trabajo Windows, en mi caso es GTI

usuario a de ser un nombre de usuario válido en Windows. Por ejemplo yo uso el usuario FERNANDO

nombrenetbios es el nombre de la máquina. Por ejemplo mi PC se llama WINBOX

recurso Es la carpeta compartida en Windows a la que queremos acceder. En mi caso es AUTOR

Con lo que la URL que usaré es:

smb://GTI;FERNANDO@WINBOX/AUTOR

Windows no diferencia mayúsculas de minúsculas en los nombres SMB, pero en este documento vamos a escribir los nombres siempre en mayúsculas.

Después aparece otro diálogo que nos pide el password, y si todo va bien en la raíz de Finder aparecerá una nueva unidad, que representa la unidad de red.

Usar el terminal para acceder a una carpeta compartida en Windows

Antes de conectarnos a una máquina conviene empezar comprobando que la máquina es alcanzable por la red haciéndola un ping:

$ ping 192.168.1.3

Si no conocemos la IP de un nombre NetBIOS podemos usar el comando:

$ smbutil lookup WINBOX
Got response from 192.168.1.3
IP address of WINBOX: 192.168.1.3

Podemos descubrir el nombre NetBIOS y workgroup usando el comando smbutil status así:

$ smbutil status 192.168.1.3
Workgroup: GTI
Server: WINBOX

Podemos comprobar los recursos compartidos en una máquina usando el comando smbutil view:

$ smbutil view '//GTI;FERNANDO@192.168.1.3'
Password: *****
Share Type Comment
-------------------------------
AUTOR disk
IPC$ pipe Comunicación remota entre procesos

Obsérvese que hemos usado la dirección IP de la máquina y no su nombre NetBIOS (lo cual evita el problema que se produce cuando no se resuelve bien el nombre NetBIOS). El comando nos informa de que en la máquina hay una carpeta compartida llamada AUTOR.

Desde el terminal podemos montar la unidad de red usando el comando mount. Para ello primero nos hemos creardo un directorio llamado autor donde montar la unidad. Para poder montar la unidad de red en el directorio autor debemos de estar logados como root (para ello debemos de usar el comando su). Después montamos la unidad con el comando:

# mount_smbfs -W GTI //FERNANDO@WINBOX/AUTOR ./autor

-W sirve para especificar el workgroup, y después va el recurso al que nos queremos conectar.

Tras ejecutar estos comandos, el directorio autor pasará a ser una unidad de red montada, y podremos acceder a ella desde Finder o desde el terminal.

Para desmontar la unidad tenemos el comando:

# umount ./autor

Configurar el servidor Samba

Dentro de System Preferences|Sharing disponemos de la opción File Sharing, la cual debemos de activar para que nuestra máquina actúe como servidor de ficheros. En el botón Options debemos activar la opción SMB.

servidorsmb.png

Como muestra la figura, en la parte superior aparece el nombre de la máquina, que será el nombre NetBIOS que usará nuestra máquina. En Shared Folders indicamos las carpetas a compartir y los usuarios que pueden acceder a ellas. Necesitaremos conocer el usuario y password de alguna de estas cuentas para acceder a los recursos compartidos por Samba.

Por defecto es servidor Samba usa el nombre de workgroup WORKGROUP. A partir deMac OS X 10.5, dentro de System Preferences|Network|Advanced tenemos un cuadro de diálogo que nos permite configurar el nombre del workgroup y el servidor WINS.

wins.png

En Mac OS X 10.4, para configurar el nombre del workgroup y el servidor WINS, necesitamos usar la utilidad Directory Service.app, situada en la carpeta /Applications/Utilities.

directoryservice.png

Si desea que los usuarios puedan conectarse a un recurso compartido sin identificarse, deberá indicarlo en System Preferences|Accounts tal como muestra la siguiente figura.

guest.png

Además de estos diálogos, en el fichero /etc/smb.conf permite configurar otras opciones del servidor Samba. El fichero tiene un grupo [global] con opciones globales de configuración de Samba y un grupo para cada recurso compartido (directorios o impresoras).

En este fichero es donde el panel de preferencias escribe la configuración de Samba y los recursos compartidos. Pero para evitar interferir con las modificaciones que nosotros hagamos al fichero /etc/smb.conf, este fichero incluye los ficheros que el panel de preferencias modifica:

; Pull in system-wide preference settings. These are managed
; by smb-sync-preferences.
include = /var/db/smb.conf

; Pull in system share configuration. These are managed
; by smb-sync-shares.
include = /var/db/samba/smb.shares

Estas inclusiones aparecen al final del fichero /etc/smb.conf, con lo que sobrescriben las preferencias que nosotros hagamos antes de su aparición. Si no queremos que una opción pueda ser modificada por el panel de preferencias debemos ponerla después de la inclusión de estos ficheros.

Par más información:

http://freax.be/files/osxsmb.html
http://www.macdevcenter.com/pub/a/mac/2003/03/18/samba.html
http://www.samba.org

Habilitar el usuario root

Mac OS X no nos permite modificar todos los ficheros del sistema a pesar de ser administradores de nuestro ordenador. En este truco se comenta como poder tener permiso a esas partes que Apple nos ha "prohibido" tocar.

Para evitar que dañemos ficheros que podrían echar abajo todo el sistema, Apple a reservado el acceso a determinados ficheros y operaciones a un usuario root, que es distinto al usuario que nos asigna Mac OS X al instalar Mac OS X.

Advertimos ya aquí de los daños que podemos causar desde la cuenta de root, con lo que debe usarse sólo sabiendo bien lo que hacemos. P.e. basta con cambiar el permiso de directorio del grupo others del directorio raíz:

$ chmod o-x /

Para que Mac OS X se caiga y no vuelva a levantarse nunca más hasta que formateemos el disco (con la consiguiente perdida de datos). Esto es así porque los procesos que arrancan Mac OS X pierden el permiso de acceso al directorio raíz, y en consecuencia al resto de los directorios del disco duro.

Dicho esto vamos a empezar intentando entrar como root en el sistema usando:

$ su
Password: ********
Sorry

Vamos que el sistema nos dice que no podemos ser root de nuestro ordenador por muy nuestro que sea.

En Mac OS X 10.5 y siguientes, para habilitar el usuario root basta con ejecutar el comando:

$ dsenableroot -u fernando
user password: ********
root password: ********
verify root password:
dsenableroot:: ***Successfully enabled root user.

Donde fernando es el nombre de un usuario con permisos de administración.

Apple tiene más información sobre cómo configurar el usuario root aquí.

Ahora podemos ir al usuario root y borrar el * que hay en el campo de password, lo cual nos permite entrar como root con sólo ejecutar el comando su:

$ su
root#

Ya está, ya tenemos el control de todo nuestro ordenador, ahora lo mejor que podemos hacer es poner un password a root para evitar que otros usuarios puedan entrar como root, para ello ejecutamos el comando:

root# passwd
New password: *******
Reype password: *******

Videocursos


Fundamentos de Objective-C: El Framework Foundation VI




Desarrollo de aplicaciones para iPhone y iPad: Controles de texto y booleanos




Videos puesto a disposición de la comunidad de MacProgramadores: por Videocursos

Bibliografía

Esta bibliografía está clasificada por las tecnologías que consideramos necesarias para dominar la programación del sistema operativo Mac OS X.

Terminal

Para dominar OS X se hace imprescindible saber usar el terminal UNIX que trae. Aquí encontrará información útil de como aprender a manejar a fondo este terminal.

¿Qué shell usa Mac OS X?

Mac OS X, como un tipo de UNIX que es también dispone de un terminal. El shell es el programa que controla el terminal y que permite ejecutar otros programas.

En los sistemas UNIX no hay un shell, sino muchos. Los shells más conocidos son:

Shell Descripción
sh (bourne SHell) Es el shell original de UNIX, es el más simple de todos, con lo que casi nadie lo utiliza. Sin embargo si que lo utilizan muchas veces los programas de instalación, ya que por ser el mínimo común divisor de todos los shells, sus comandos ejecutan bien en todos los shells.
bash (Bourne Again SHell) El shell de GNU. Es el que utiliza por defecto Mac OS X y Linux.
csh (C SHell) Es un shell desarrollado en la Universidad de Berkeley con una sintaxis más parecida a la de el lenguaje C.
tcsh (Tenex C SHell) es un csh mejorado. Fue usado por Mac OS X hasta la versión 10.2
chs (Ch Shell) Posiblemente el shell más completo y potente que existe. Tiene un lenguaje de script con sintaxis muy parecida a la de C++. Por desgracia está poco extendido.
ksh (Korn SHell) Un shell usado en sistemas UNIX como AIX de IBM.

El shell que ejecuta Mac OS X por defecto es bash.

¿Donde conseguir documentación?

En MacProgramadores disponemos de un buen tutorial:

El shell Bash

Si quiere aprender el shell bash sin centrarse en las peculiaridades de Mac OS X puede leer este libro:

terminal1.png
Learning the bash Shell, Third Edition
Cameron Newham
Ed. O'Reilly

Si por el contrario quiere aprender muchos trucos propios del terminal de Mac OS X puede elegir mejor este otro libro:

terminal2.png
Mac OS X for Unix Geeks (Leopard), Fourth Edition
Ernest E. Rothman, Brian Jepson, Rich Rosen
Ed. O'Reilly

Herramientas de desarrollo

A continuación se indican cuales son las principales herramientas de desarrollo de Mac OS X y iOS

Apple's Developer Connection (ADC)

La principal herramienta de desarrollo para Mac OS X y iOS es este kit, que proporciona de forma gratuita Apple a los miembros del ADC. Si quiere conseguir estas herramientas regístrese como usuario del ADC aquí.

Este kit incluye las siguientes herramientas:

Xcode. Un IDE desde el que podemos realizar aplicaciones C, C++, Java y Objective-C para Mac OS X y iOS.

Interface Builder. Herramienta que nos permite realizar la interfaz gráfica de las aplicaciones cómodamente. A partir de Xcode 4.0 está integrado con Xcode. La interfaz gráfica de las aplicaciones, además de poder crearse programáticamente, se puede crear en un fichero XML con la extensión .xib que se compila en un .nib. Cuando se ejecuta una aplicación se carga en memoria este fichero en base al cual se crea la interfaz gráfica. Esto es mucho más cómodo que tener que hacer llamadas al API, y para crear este fichero se usa esta herramienta.

Instruments. Una herramienta que nos permite perfilar nuestras aplicaciones y encontrar errores en tiempo de ejecución.

Package Maker. Una herramienta que nos permite hacer instaladores de aplicaciones Mac OS X de forma rápida y con una interfaz homogénea para todas las aplicaciones. Esta herramienta nos permite crear ficheros .pkg, que al hacer el usuario doble click sobre ellos se ejecuta el instalador.

Dashcode. Es una herramienta que nos permite crear fácilmente widgets para Dashboard.

PropertyListEditor. En Mac OS X muchos ficheros de configuración usan el formato XML, para poder visualizar de forma cómoda (jerárquicamente) estos ficheros tenemos esta herramienta.

Icon Composer. Estas herramientas nos permiten crear y visualizar ficheros .icns de forma cómoda.

Documentación. La gran mayoría de la documentación y tutoriales que encontramos en la web de Apple, la podemos encontrar también aquí.

Ejemplos. Cuando tenemos dudas sobre como se hace "exactamente" algo de lo que nos habla la ayuda, lo mejor es buscar en estos ejemplos.

Un muy buen artículo que resume el funcionamiento de Xcode es el siguiente:

Understanding Xcode Projects

Para profundizar mucho más podemos leer este otro documento:

A Tour of Xcode

Otras herramientas de desarrollo

Terceras partes están desarrollando excelentes herramientas de desarrollo que recomendamos evaluar.

  • Eclipse es un IDE desarrollado en Java por IBM bajo licencia abierta que permite trabajar con distintos lenguajes, tiene ayudas para completar código, para depurar y para trabajar contra un gestor de versiones.
  • NetBeans es un IDE de desarrollo visual para Java desarrollado por Sun y de código fuente abierto y publicado en:
  • JBuilder es un IDE de desarrollo visual para Java desarrollado por Embarcadero (sucesor de Borland).
  • IntelliJ es un IDE Java para profesionales con multitud de opciones de personalización que permiten ejecutar y depurar aplicaciones gráficas, JSP, J2EE así como centralizar el trabajo con un gestor de versiones.
  • TextMate es un gran IDE para Mac OS X. Es rápido, permite desarrollar para muchísimos lenguajes y es totalmente personalizable mediante scripts. Permite ejecutar comandos como gcc o javac con una combinación de teclas. O bien podemos crear ficheros Makefile o Ant y ejecutarlos. Además consume poca memoria. No es gratuito pero tiene un precio muy asequible.

Objective-C

Qué es Objective-C

Objective-C es un lenguaje orientado a objetos creado como un superconjunto de C con un estilo muy parecido al de Smalltalk. Originalmente fue escrito por Brad Cox y la corporación StepStone en 1980. En 1988 fue adoptado como lenguaje de programación de NeXTSTEP y en 1992 fue liberado bajo licencia GNU para el compilador gcc. Actualmente se usa como lenguaje principal de programación en Mac OS X y GNUStep.

Podemos obtener un compilador de Objective-C en:

  • Si tenemos un Mac OS X ya tenemos el gcc de Apple que viene con Darwin
  • Si tenemos otro SO podemos conseguir el compilador gcc de GNU aquí.

Aprender Objective-C

Para aprender Objective-C, básicamente hay tres pasos:

1. Aprender C

Para ello se puede usar uno de los miles de libros que hay sobre la materia. También se puede consultar esta web con buenos manuales gratuitos en castellano sobre C.

2. Aprender Objective-C

Para aprender Objective-C recomendamos el siguiente libro:

OBJECTIVE-C. Curso práctico para Programadores Mac OS X, iPhone y iPad
Objective-C. Curso práctico para Programadores Mac OS X, iPhone y iPad
Autor: Fernando López Hernández
Editorial: RC Libros
lSBN: 978-84-938312-7-1
560 páginas.

3. Aprender libobjects

libobjects son las librerías de clases de GNU para Objective-C. En concreto se trata de librerías de uso general no gráfica. Se puede decir que libobjects son para GNU's Objective-C lo que libc++ para GNU's C++. En un futuro se pretende cambiar el nombre de estas librerías por el de "GNUStep Base Library". Estas librerías están todavía sin acabar.

Objective-C++

Objective-C++ es un lenguaje que surgió en los tiempos de NeXTSTEP. Este lenguaje permite mezclar código fuente C++ y Objective-C en el mismo fichero fuente, así como llamar a objetos C++ desde Objective-C y viceversa. Lo cual permite al programador Objective-C utilizar todas las librerías de C++ existentes, y al programador C++ acceder a toda la libraría de Cocoa. Los ficheros Objective-C++ llevan las extensión .mm ó .M (extensión antigua que se mantiene por compatibilidad).

Cocoa

¿Qué es Cocoa?

Cocoa es la nueva API de programación de aplicaciones de Mac OS X. Existe otra API llamada Carbon que permite la compatibilidad con las aplicaciones de Mac OS Classic, que no vamos a tratar en esta web. En el caso de iOS la API se llama Cocoa Touch.

Cocoa es una API totalmente orientada a objetos a la que principalmente se accede desde Objective-C. Apple ha creado Cocoa Brigdges para poder acceder a Cocoa desde otros lenguajes como AppleScript, Java, Python o Ruby.

Apple's Cocoa Developer Documentation

La principal fuente de referencia sobre esta API es la documentación publicada por Apple en:

Cocoa Fundamental Guide

Los programadores Windows pueden consultar esta guía que tiene publicada Apple sobre como migrar desde Win32 a Mac OS X:

Porting to Mac OS X from Win32 API

Libros de programación Cocoa

Por desgracia esta documentación más que un tutorial es un manual de referencia, con lo que es útil como fuente de consulta, pero no tanto para aprender a programar. Por esta razón proponemos los siguientes libros.

cocoa1.png
Cocoa(R) Programming for Mac(R) OS X (3rd Edition)
Aaron Hillegass
Ed. Addison-Wesley Professional
cocoa2.png
Learn Cocoa on the Mac
Jack Nutting, David Mark, Jeff LaMarche
Ed. Apress

iOS

¿Qué es iOS?

iOS es un sistema operativo para PDAs y teléfonos móviles desarrollado por Apple. iOS está basado en el sistema operativo Mac OS X y sus herramientas de programación son similares a las de Mac OS X. En concreto ambos sistemas operativos comparten el mismo núcleo Mach/FreeBSD, y utilizan como lenguajes de programación principales C y Objective-C.

Distintos dispositivos utilizan iOS. iPhone es un teléfono móvil con capacidades multimedia desarrollado por Apple. iPod Touch es la versión reducida de iPhone que no tiene teléfono. iPad es un dispositivo con el mismo sistema operativo y arquitectura hardware que iPhone, pero al que se ha quitado las características propias de teléfono móvil y se le ha añadido una pantalla más grande.

Programación

Para la programación de iOS, Apple proporciona una API de programación llamada Cocoa Touch. Esta API comparte muchas similitudes con Cocoa de Mac OS X y también tiene diferencias. La las clases base de Foundation Framework son comunes entre Mac OS X y iOS. Las principales diferencias se encuentran la UIKit, que son las clases de programación de interfaz de usuario de iOS . El equivalente a UIKit en Mac OS X es Application Kit.

Bibliografía

Actualmente existe bastante bibliografía para aprender a programar iOS. En el sitio web de Apple dedicado a iOS encontramos guías de programación como:

iOS Application Programming Guide

iOS Development Guide

Además existen ya bastantes libros destinados a programar con iOS. Entre ellos destacamos los siguientes:

ios1.png
Beginning iPhone Development: Exploring the iPhone SDK
Dave Mark, Jeff LaMarche
Ed. Apress
ios2.png
Phone SDK Application Development: Building Applications for the AppStore
Jonathan Zdziarski
Ed. O'Reilly

Kernel

¿Qué es Darwin?

Darwin es la parte open source de Mac OS X que han desarrollado los ingenieros de Apple. Darwin consta de multitud de paquetes (Compiler Tools, Kerberos, Open Directory, X11, CUPS, XNU...).

¿Qué es XNU?

Un paquete importante de Darwin es el núcleo de Mac OS X, el cual se llama XNU (XNU is not UNIX). Dentro de Darwin encontramos el paquete XNU con el código fuente tanto para x86 como para PowerPC y ARM.

Las principales partes que componen XNU son básicamente dos: Mach 3.0, un microkernel desarrollado en la Universidad de Carnegie Mellon, y el núcleo BSD 4.4 (Berkeley Software Distribution) de FreeBSD.

XNU consta de seis componentes principales:

Mach El "núcleo del núcleo" XNU. Realiza las operaciones críticas de un microkernel, como son la gestión de procesador, la gestión de memoria, la gestión de procesos y hilos (protección de memoria, scheduling), soporte para el reloj real-time (p.e. usado por las aplicaciones multimedia) y el soporte para depuración del kernel.

Aunque el microkernel Mach 3.0 fue el núcleo en el que se basaron los ingenieros de Apple, XNU no es en si un microkernel puro, ya que su espacio de memoria está compartido con una parte de BSD y con las Kernel Extensions.

BSD Una capa por encima de Mach que permite a los programadores usar las conocidas llamadas al sistema POSIX de los sistemas UNIX. Estas funciones nos permiten entre otras cosas la gestión de procesos por ID, dar permisos a estos procesos, gestión de señales, o el uso de sockets BSD. La principal ventaja que aporta BSD es que permite migrar fácilmente aplicaciones UNIX a Mac OS X.

Kernel Extensions (también llamados kexts) Son bundles que extienden la funcionalidad del núcleo de Mac OS X y que se pueden cargar y descargar dinámicamente. Dentro del bundle encontramos el kernel módule (también llamado kmod) que es una imagen binaria Mach que se instala en el kernel. Los kext se programan en C. Para aprender a desarrollar Kernel Extensions, puede consultar:

Kernel Extensions Programming Topics

I/O Kit Proporciona un framework C++ para el desarrollo de drivers de dispositivos mediante kexts. En concreto, usa un subconjunto del lenguaje C++ llamado Embedded C++. Un I/O Kit driver es una kext que, en vez de estar programada en C, está programada en Embeded C++. El I/O Kit está formado por tres componentes principales:

  • Families. Define una colección de abstracciones software comunes a todos los dispositivos de una categoría. Apple proporciona familias para protocolos como USB, SCSI y FireWire, así como para dispositivos de almacenamiento y frame buffers. Nosotros debemos en general basarnos en las familias ya hechas, y no crear nuevas familias.
  • Nubs. Es un objeto que representa un dispositivo o servicio lógico (p.e. un bus, un disco, una partición de disco o el teclado).
  • Drivers. Es un objeto que se encarga de gestionar una determinada pieza hardware, implementando las operaciones de E/S para ese dispositivo. Mac OS X ya proporciona una colección de drivers que gestionan los dispositivos más comunes, como puedan ser discos duros o teclados. Si un nuevo dispositivo cumple con un estándar industrial, pero tiene más funcionalidad, entonces simplemente tendremos que crear una subclase que maneje esas características adicionales.

Si vamos a trabajar con el I/O Kit conviene leerse:

I/O Kit fundamentals

I/O Kit Device Driver Design Guidelines

File System El sistema de ficheros de XNU se basa en el diseño de VFS (Virtual File System), el cual se caracteriza porque nos permite añadir fácilmente nuevos sistemas de ficheros, así como añadir capas a un sistema de ficheros existentes (p.e. compresión, encriptación). Mac OS X viene con los sistemas de ficheros HFS, HFS+, UFS (Universal File System) y ISO 9660

Networking Mac OS X lleva implementada la pila de red en el núcleo, la cual también tiene un sistema extensible que nos permite añadir nuevos protocolos llamado NKE (Network Kernel Extensions).

¿Donde conseguir el código fuente de Darwin?

Apple tiene un repositorio open source destinados a almacenar el código fuente de Darwin en:

http://developer.apple.com/opensource/

Este es un repositorio del que se saca directamente el código fuente que lleva Mac OS X, con lo que su contenido debe de ser de calidad. Por eso para que un programador pueda modificar este repositorio debe superar unos controles de calidad que establece Apple (en su mayoría acceden a el sólo los empleados de Apple), aunque todo el mundo puede bajarse el código fuente de este repositorio a través de CVS.

Documentación

Todo aquel que quiera programar en el kernel, debería empezar leyéndose este documento:

Should You Program in the Kernel?

Después podemos bajarnos el código fuente de XNU de aquí:

Darwin Source Code

Para iniciarse en la programación del kernel es recomendable empezar leyéndose:

Kernel Programming

El mejor libro que conocemos para aprender a programar en el kernel de Mac OS X es:

kernel1.png
Mac OS X Internals: A Systems Approach
Amit Singh
Ed. Addison-Wesley Professional

Otro buen libro con multitud de trucos es:

kernel2.png
The Mac Hacker's Handbook
Charles Miller, Dino Dai Zovi
Ed. Wiley