Skip to content

Instantly share code, notes, and snippets.

@sck
Created April 28, 2012 16:56
Show Gist options
  • Select an option

  • Save sck/2520212 to your computer and use it in GitHub Desktop.

Select an option

Save sck/2520212 to your computer and use it in GitHub Desktop.
Reads DTrace output to fix Adobe's filenames on OS X with case-sensitive volumes
#! /usr/bin/env ruby
# About
#
# This program tries to fix Adobe's issues with case-sensitive volumes by
# using DTrace to log which files cannot be opened and then trying to
# generate a shell script which will rename the files to the names as
# Adobe wants them.
#
# USAGE:
# 1. Open a shell and execute the following dtrace command (change
# missing.files.for.photoshop at the end to illustrator, etc.):
# % sudo dtrace -n 'syscall::*stat*:entry,syscall::*open*:entry /strstr(execname, "Adobe")!=0/ { self->filename = arg0; } syscall::*stat*:return,syscall::*open*:return /strstr(execname, "Adobe")!=0 && errno != 0/ { printf("<%s> %d", copyinstr(self->filename), errno); }' >> missing.files.for.photoshop
# 2. Open the Adobe program you are trying to fix
# 3. (Keep dtrace running)
# 4. Run this script
# % ruby fixAdobeCaseInsensitivePaths.rb < missing.files.for.photoshop
# It should print out something like:
# | correct_name="[...]"
# | existing_name="[...]"
# | if test -d "$existing_name"; then
#
# Save the output:
# % ruby fixAdobeCaseInsensitivePaths.rb < missing.files.for.photoshop
# > fixAdobePhotoshop1.sh
#
# 5. Run the generated shell script as root (You may want to look at the
# script before running it as root)
# % sudo sh fixAdobePhotoshop1.sh
# 6. Repeat from step 2, now call the script fixAdobePhotoshopN.sh.
# Repeat until Adobe program runs again without errors
#
$adobe_cache={}
$have_moved={}
$all_adobe_files=[]
$true_name_in_current_fs = {}
#$all_locales=`locale -a`.split(/\n/).map {|l| l.gsub(/\..*/, "") }.sort.uniq
class String
def split_path; split(File::SEPARATOR); end
def fixify
es = split_path
es.each_with_index{|e,i|
np = $have_moved[File.join(es[0..i])]
if np
es[i] = np.split_path[-1]
end
}
File.join(es)
end
end
def fill_adobe_cache(dir)
return if $adobe_cache[dir]
files = Dir["#{dir}/**/*"]
files.each {|f|
$all_adobe_files.push(f)
$true_name_in_current_fs[f.downcase] = f
}
$adobe_cache[dir] = files.inject({}) {|h,v| h[v.downcase] = v; h}
end
def fix_paths(existing, correct)
ee = existing.split_path
ce = correct.split_path
raise "different sizes!" if ce.size != ee.size
c = 0
fixed = false
begin
if ee[c] != ce[c]
correct_name = File.join(ce[0..c])
existing_name = File.join(ee[0..c])
ee[c] = ce[c]
if !$have_moved.has_key?(existing_name)
fixed = true
$have_moved[existing_name] = correct_name
puts <<EOFIX1
correct_name=#{correct_name.inspect}
existing_name=#{existing_name.inspect}
EOFIX1
true_existing_name = $true_name_in_current_fs[existing_name.downcase]
if File.exists?(true_existing_name)
if File.directory?(true_existing_name)
puts <<EOFIX2
if test -d "$existing_name"; then
echo "DIR: $correct_name"
mv "$existing_name" "$correct_name"
elif test \! -d "$correct_name"; then
echo "Missing correct DIR: $correct_name"
fi
EOFIX2
else
puts <<EOFIX3
if test -f "$existing_name"; then
echo "FILE: $correct_name"
mv "$existing_name" "$correct_name"
elif test \! -f "$correct_name"; then
echo "Missing correct FILE: $correct_name"
fi
EOFIX3
end
end
end
end
c += 1
end while c <= ce.size
fixed
end
def generic_fix(_existing_name)
existing_name = _existing_name.fixify
ee = existing_name.split_path
fix_paths(existing_name, File.join(ee[0..-2], "A")) if
ee[-2] == "Versions" && ee[-1] == "a"
fix_paths(existing_name, File.join(ee[0..-2], "Resources")) if
ee[-1] == "resources"
#if ee[-2].downcase == "resources" && ee[-1] =~ /^([a-z]+)_([a-z]+)\.lproj$/
# locale1 = $1
# locale2 = $2
# fix_paths(existing_name,
# File.join(ee[0..-2], "#{locale1}_#{locale2.upcase}.lproj"))
#end
if ee[-2].downcase == "lmresources" && ee[-1] =~ /^([a-z]+)_([a-z]+)/
locale1 = $1
locale2 = $2
fix_paths(existing_name,
File.join(ee[0..-2], "#{locale1}_#{locale2.upcase}"))
end
if ee[-3].downcase == "lmresources" && ee[-1] == "Main.zdct"
fix_paths(existing_name, File.join(ee[0..-2], "main.zdct"))
end
end
#f = File.open(STDIN, "r")
while line = STDIN.gets
line.chomp!
m = /<([^>]*)>/.match(line)
next if !m
correct_name = File.expand_path(m[1])
next if File.exists?(correct_name)
if /(^.*?Adobe [^\/]*)/.match(correct_name)
adobe_dir = $1
correct_name_dc = correct_name.downcase
fill_adobe_cache(adobe_dir)
existing_name = $adobe_cache[adobe_dir][correct_name_dc]
fix_paths(existing_name, correct_name) if existing_name
end
end
$all_adobe_files.each{|f| generic_fix(f) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment