Сценарий - в Outlook 2011 открываю приатаченный к письму файл

Изображение открывается в Preview. Посмотрел, убедился, что всё в порядке и нажимаю "Save As..." для сохранения его в нужный мне каталог, например, в ~/Downloads. К удивлению получаю сообщение "No permission":

У меня уже возникла мысль о том, что SSD накрывается. Нужно разобраться, что происходит.

Пожалуй, применю dtruss. Смотрю название бинарного файла Preview.app:

$ ps ax | grep Previe
 1794   ??  S      0:16.37 /Applications/Preview.app/Contents/MacOS/Preview -psn_0_598162

Найденный "Preview" подставляю в dtruss:

$ sudo dtruss -n Preview -f

Повторяю попытку сохранения. Для того, чтобы очистить историю в терминале (так проще искать), нажимаю Cmd+K (Clear Scrollback). Получаю снова ошибку "You don't have permission", прерываю dtruss, медитирую на логи. Процесс очень короткий в отличие от многих других случаев.

Что делает Preview.app при попытке записи?

1. getattrlist("/Users/ctrld/Downloads/Image001[3].jpg\0", 0x7FFF5FBFDB30, 0x7FFF5FBFD760)		 = -1 Err#2
2. getattrlist("/Users/ctrld/Downloads\0", 0x7FFF5FBFDB30, 0x7FFF5FBFD760)		 = 0 0
3. mkdir("/private/var/folders/X4/X4vtQdxYFpOj0O2ozpm4Wk+++TI/TemporaryItems/(A Document Being Saved By Preview)\0", 0x1FF, 0x100864680)		 = -1 Err#17
4. mkdir("/private/var/folders/X4/X4vtQdxYFpOj0O2ozpm4Wk+++TI/TemporaryItems/(A Document Being Saved By Preview 2)\0", 0x1FF, 0x100864698)		 = -1 Err#17
5. mkdir("/private/var/folders/X4/X4vtQdxYFpOj0O2ozpm4Wk+++TI/TemporaryItems/(A Document Being Saved By Preview 3)\0", 0x1FF, 0x1008646B0)		 = 0 0
6. lstat64("/private/var/folders/X4/X4vtQdxYFpOj0O2ozpm4Wk+++TI/TemporaryItems/(A Document Being Saved By Preview 3)/Image001[3].jpg\0", 0x7FFF5FBFE310, 0x1F8100)		 = -1 Err#2
7. rename("/private/var/folders/X4/X4vtQdxYFpOj0O2ozpm4Wk+++TI/TemporaryItems/(A Document Being Saved By Preview 2)/Image001[3].jpg\0", "/private/var/folders/X4/X4vtQdxYFpOj0O2ozpm4Wk+++TI/TemporaryItems/(A Document Being Saved By Preview 3)/Image001[3].jpg\0")		 = -1 Err#1
8. lstat64("/private/var/folders/X4/X4vtQdxYFpOj0O2ozpm4Wk+++TI/TemporaryItems/(A Document Being Saved By Preview 3)/Image001[3].jpg\0", 0x118468948, 0x0)		 = -1 Err#2

Отступление. Как распознать код ошибки? Нужно посмотреть /usr/include/sys/errno.h.

$ grep 2 /usr/include/sys/errno.h

Err#2 = ENOENT = "No such file or directory", Err#17 = EEXIST = "File exists", Err#1 = EPERM = "Operation not permitted".

Можно ещё посмотреть секцию ERRORS в "man getattrlist", но там указаны имена констант, а не коды. Сами же коды - в errno.h.

  1. Есть ли файл Image001[3].jpg в указанном для записи каталоге? Нет (ENOENT), продолжаем.
  2. А каталог, куда мы указали записать файл существует? Да (0).
  3. Есть ли во временном каталоге подкаталог "(A Document Being Saved By Preview)", куда можно писать временный файл (проверяем созданием этого каталога)? Есть (EEXIST).
  4. Добавляем единицу к индексу. Есть ли "(A Document Being Saved By Preview 2)"? Да, есть (EEXIST).
  5. Добавляем единицу к индексу. Есть ли "(A Document Being Saved By Preview 3)"? Не было, но уже есть.
  6. Есть ли файл Image001[3].jpg в нашем последнем временном каталоге? Нет (ENOENT)
  7. Перемещаем Image001[3].jpg из "(A Document Being Saved By Preview 2)" в "(A Document Being Saved By Preview 3)". Доступ запрещён (EPERM)

Так, проблема в "/private/var/folders/X4/X4vtQdxYFpOj0O2ozpm4Wk+++TI/TemporaryItems/(A Document Being Saved By Preview 2)/Image001[3].jpg". Смотрю, почему его нельзя переместить.

$ cd /private/var/folders/X4/X4vtQdxYFpOj0O2ozpm4Wk+++TI/TemporaryItems/
$ ls -al "(A Document Being Saved By Preview 2)/Image001[3].jpg"
-rw-r--r--@ 1 ctrld  staff  928886 Mar 24 17:10 (A Document Being Saved By Preview 2)/Image001[3].jpg

Права доступа верны, значит нужно сразу проверять флаги (ключ - буква "O", а не "ноль"):

$ ls -alO "(A Document Being Saved By Preview 2)/Image001[3].jpg"
-rw-r--r--@ 1 ctrld  staff  uchg 928886 Mar 24 17:10 (A Document Being Saved By Preview 2)/Image001[3].jpg

Понятно, стоит флаг uchg (user immutable flag), не дающий ничего сделать с файлом.

Хммм... Preview такие флаги не ставит. Аттачменты, открываемые во внешних программах, сохраняются в каталоге "~/Library/Caches/TemporaryItems/Outlook Temp". Как определил? При "Save As..." в Preview щёлкнул с Cmd на заголовок окна и увидел путь:

$ cd ~/Library/Caches/TemporaryItems/Outlook Temp
$ ls -alO
drwxr-xr-x@ 6 ctrld  staff  -       204 Mar 24 17:36 .
drwx------@ 4 ctrld  staff  -       136 Mar 24 16:42 ..
-rw-r--r--@ 1 ctrld  staff  uchg 766895 Mar 23 10:37 Image001.jpg
-rw-r--r--@ 1 ctrld  staff  -    766895 Mar 23 10:39 Image001[1].jpg
-rw-r--r--@ 1 ctrld  staff  uchg 928886 Mar 24 16:31 Image001[2].jpg
-rw-r--r--@ 1 ctrld  staff  uchg 928886 Mar 24 17:01 Image001[3].jpg

Хм... Почему три файла с uchg? Удаляю эти аттрибуты:

$ chflags nouchg Image001*

Открываю снова приатаченный файл из Outlook и вижу снова флаг uchg в новом файле:

$ ls -alO
drwxr-xr-x@ 7 ctrld  staff  -       238 Mar 24 17:45 .
drwx------@ 4 ctrld  staff  -       136 Mar 24 16:42 ..
-rw-r--r--@ 1 ctrld  staff  -    766895 Mar 23 10:37 Image001.jpg
-rw-r--r--@ 1 ctrld  staff  -    766895 Mar 23 10:39 Image001[1].jpg
-rw-r--r--@ 1 ctrld  staff  -    928886 Mar 24 16:31 Image001[2].jpg
-rw-r--r--@ 1 ctrld  staff  -    928886 Mar 24 17:01 Image001[3].jpg
-rw-r--r--@ 1 ctrld  staff  uchg 928886 Mar 24 17:45 Image001[4].jpg

Глюк Outlook? Выхожу из Outlook, удаляю файлы, захожу в Outlook, открываю приатаченный файл в Preview, снова uchg:

drwxr-xr-x@ 3 ctrld  staff  -       102 Mar 24 17:48 .
drwx------@ 4 ctrld  staff  -       136 Mar 24 16:42 ..
-rw-r--r--@ 1 ctrld  staff  uchg 928886 Mar 24 17:48 Image001.jpg

Выхожу из Outlook - временные файлы удалились. Начинаю понимать. Чтобы подтвердить догадку, захожу в Outlook, открываю приатаченный файл в Preview.app, выхожу из Outlook. Файл остаётся на месте и он уже без флага uchg:

$ ls -al
drwxr-xr-x@ 3 ctrld  staff     102 Mar 24 17:50 .
drwx------@ 4 ctrld  staff     136 Mar 24 16:42 ..
-rw-r--r--@ 1 ctrld  staff  928886 Mar 24 17:49 Image001.jpg

Делаю в Preview.app "Save As...". И всё работает, ошибки по правам доступа нет!

Итак, логика Outlook становится понятной - он не даёт изменять файлы, открытые из него. Но делает это неправильно, не давая сохранить даже копию файла. Что можно сказать... Бывает...

Workaround: если вы хотите поработать с приатаченным к письму файлом, то выйдите предварительно из Outlook.

Вот пример обычного и рутинного исследования странного поведения. Вот так я и разбираюсь с проблемами - будь то сбой программы или же странная работа сервера или непонятное поведение сети.