HTTP Cookie属性列表

版本0

cookie-v0(1)

cookie-v0(1)

cookie-v0(2)

cookie-v0(2)

版本1

cookie-v1(1)

cookie-v1(1)

cookie-v1(2)

cookie-v1(2)

ref: 《HTTP权威指南》

Android OTA 升级中的一些零碎知识

OTA升级脚本build/tools/releasetoolsrecovery-resource.dat

# Recovery is generated as a patch using both the boot image
# (which contains the same linux kernel as recovery) and the file
# /system/etc/recovery-resource.dat (which contains all the images
# used in the recovery UI) as sources.  This lets us minimize the
# size of the patch, which must be included in every OTA package.
#
# For older builds where recovery-resource.dat is not present, we
# use only the boot image as the source. ref: build/tools/releasetools/ota_from_target_files

source of imgdiff and bsdiffbootable/recovery/applypatch

Android端的升级脚本两步策略中的第二步,升级重启后执行的脚本(包括建立软链接和权限设置)。 META-INF/com/google/android/updater-script

imgdiff的参数

imgdiff是android提供的用来生成binary patch的工具,android同时还提供了另一个binary patch工具是bsdiff。

usage: -z <src-img> <tgt-img> <patch-file>

-z: 输入文件是否是ZIP格式

-b: 额外的二进制文件,在OTA中,这个文件就是recovery-resource.dat

imgdiff和bsdiff的区别

看下下面这段摘自imgdiff.c的说明就明白了:

- This program(imgdiff) constructs binary patches for images -- such as boot.img
- and recovery.img -- that consist primarily of large chunks of gzipped
- data interspersed with uncompressed data.  Doing a naive bsdiff of
- these files is not useful because small changes in the data lead to
- large changes in the compressed bitstream; bsdiff patches of gzipped
- data are typically as large as the data itself

生成全包和差分包生成全包命令

生成全包命令

ota_from_target_files -f 0 -d "MMC"  -p  out/host/linux-x86/   -k  build/target/product/security/testkey   -v  product-target_files-eng.hostname.zip  ~/tmp/full_OTA.zip

生成差分包命令

ota_from_target_files -f 0 -d "MMC" -p out/host/linux-x86 -k build/target/product/security/testkey -v -i product-target_files-eng-old.host.zip  product-target_files-eng-new.host.zip   ~/tmp/increment_OTA.zip

相关的代码调用

ota_from_target_files中

  if OPTIONS.incremental_source is None:

WriteFullOTAPackage(input_zip, output_zip, OPTIONS.fota)

if OPTIONS.package_key is None:

  OPTIONS.package_key = OPTIONS.info_dict.get(

  "default_system_dev_certificate",

  "build/target/product/security/testkey")

  else:

print "unzipping source target-files..."

OPTIONS.source_tmp, source_zip = common.UnzipTemp(OPTIONS.incremental_source)

OPTIONS.target_info_dict = OPTIONS.info_dict

OPTIONS.source_info_dict = common.LoadInfoDict(source_zip, OPTIONS.device_type)

if OPTIONS.package_key is None:

  OPTIONS.package_key = OPTIONS.source_info_dict.get(

  "default_system_dev_certificate",

  "build/target/product/security/testkey")

if OPTIONS.verbose:

  print "--- source info ---"

  common.DumpInfoDict(OPTIONS.source_info_dict)

WriteIncrementalOTAPackage(input_zip, source_zip, output_zip, OPTIONS.fota)

生成OTA步骤

  • unzip
  • imgdiff / bsdiff
  • zip
  • openssl
  • signapk

OTA原始包

可用于生成OTA的文件一版在目录out/target/product/somename/obj/PACKAGING/target_files_intermediates下。

OTA中system下文件的权限设置

ota_from_target_files中:

@classmethod

  def GetMetadata(cls, input_zip):

The target_files contains a record of what the uid,

gid, and mode are supposed to be.

output = input_zip.read("META/filesystem_config.txt")

for line in output.split("\n"):

  if not line: continue

  columns = line.split()

  name, uid, gid, mode = columns[:4]

  selabel = None

  capabilities = None

After the first 4 columns, there are a series of key=value

pairs. Extract out the fields we care about.

  for element in columns[4:]:
key, value = element.split("=")
if key == "selabel":
  selabel = value
if key == "capabilities":
  capabilities = value
    i = cls.ITEMS.get(name, None)

  if i is not None:
i.uid = int(uid)
i.gid = int(gid)
i.mode = int(mode, 8)
i.selabel = selabel
i.capabilities = capabilities
if i.dir:
  i.children.sort(key=lambda i: i.name)
  set metadata for the files generated by this script.

i = cls.ITEMS.get("system/recovery-from-boot.p", None)

if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0644, None, None

i = cls.ITEMS.get("system/etc/install-recovery.sh", None)

if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0544, None, None

从上面的代码可以看到脚本读取的是META/filesystem_config.txt中的内容,这个文件是有源码编译的生成的。所以如果你增加了一些apk到image中,然后制作OTA,你需要自己赋予你的apk相应的权限,否则在生成OTA的时候就会出错(找不到 uid, gid, mode …),不要试图随意赋这些值。

filesystem_config.txt

这个文件是在build/core/Makefile中生成的:

$(hide) zipinfo -1 [email protected] | awk 'BEGIN { FS="SYSTEM/" } /^SYSTEM\// {print "system/" $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/filesystem_config.txt

$(hide) zipinfo -1 [email protected] | awk 'BEGIN { FS="BOOT/RAMDISK/" } /^BOOT\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/boot_filesystem_config.txt

$(hide) zipinfo -1 [email protected] | awk 'BEGIN { FS="RECOVERY/RAMDISK/" } /^RECOVERY\/RAMDISK\// {print $$2}' | $(HOST_OUT_EXECUTABLES)/fs_config -C -S $(SELINUX_FC) > $(zip_root)/META/recovery_filesystem_config.txt

$(hide) (cd $(zip_root) && zip -q ../$(notdir [email protected]) META/*filesystem_config.txt)

fs_config

这个工具是生成上一步中的filesystem_config.txt的核心,其源码在build/tools/fs_config 参数说明:

// This program takes a list of files and directories (indicated by a

// trailing slash) on the stdin, and prints to stdout each input

// filename along with its desired uid, gid, and mode (in octal).

// The leading slash should be stripped from the input.

//

// After the first 4 columns, optional key=value pairs are emitted

// for each file.  Currently, the following keys are supported:

// * -S: selabel=[selinux_label]

// * -C: capabilities=[hex capabilities value]

//

// Example input:

//

//      system/etc/dbus.conf

//      data/app/

//

// Output:

//

//      system/etc/dbus.conf 1002 1002 440

//      data/app 1000 1000 771

//

//   or if, for example, -S is used:

//

//      system/etc/dbus.conf 1002 1002 440 selabel=u:object_r:system_file:s0

//      data/app 1000 1000 771 selabel=u:object_r:apk_data_file:s0

//

// Note that the output will omit the trailing slash from

// directories.

Windows Python 跨进程文件访问

OS: windows 7 python: 2.7

最近在把Android OTA的整套东西移植到windows上,涉及了很多python脚本,要疯了。暂不说没写过一行python了,就是windows系统也有很多年头没动过了,这个牛X的系统,居然还是那么难用。

问题描述:

temp_zip_file = tempfile.NamedTemporaryFile()

#同一线程访问temp_zip_file

#不同线程访问temp_zip_file

temp_zip_file.close()

运行时提示错误:

另一个程序正在使用此文件,进程无法访问。

靠啊,这么简单的一条语句还能出啥问题啊,在Linux上也是没有问题的,查查文档,发现下面这句话:

tempfile.NamedTemporaryFile([mode='w+b'[, bufsize=-1[, suffix=''[, prefix='tmp'[, dir=None[, delete=True]]]]]])

This function operates exactly as TemporaryFile() does, except that the file is guaranteed to have a visible name in the file system (on Unix, the directory entry is not unlinked). That name can be retrieved from the name attribute of the file object. Whether the name can be used to open the file a second time, while the named temporary file is still open, varies across platforms (it can be so used on Unix; it cannot on Windows NT or later). If delete is true (the default), the file is deleted as soon as it is closed.
The returned object is always a file-like object whose file attribute is the underlying true file object. This file-like object can be used in a with statement, just like a normal file.

一股浓烈的鄙视之情不由自主的直往上冒。。。。。。。

解决方法:

NamedTemporaryFile默认情况下在被调用close()后会自动删除掉(跟linux的unlink差不多),加上delete=False后可以改变这个行为,但是最后要记得手工去删除这个临时文件。最后代码就变成了这个样子:

temp_zip_file = tempfile.NamedTemporaryFile(delete = False)

#同一线程访问temp_zip_file后需要关闭该文件
temp_zip_file.close()

#不同线程访问temp_zip_file
temp_zip_file = open(temp_zip_file.name, 'rb')

#最后删除文件
os.remove(temp_zip_file.name)

ref: http://bugs.python.org/issue14243#msg164504 ref: https://docs.python.org/2/library/tempfile.html ref: http://stackoverflow.com/questions/15169101/how-to-create-a-temporary-file-that-can-be-read-by-a-subprocess/15235559#15235559

Java 判断符号链接

  /**
     * Determines whether the specified file is a Symbolic Link rather than an actual file.
     * <p>
     * Will not return true if there is a Symbolic Link anywhere in the path,
     * only if the specific file is.
     * <p>
     * <b>Note:</b> the current implementation always returns {@code false} if the system
     * is detected as Windows using {@link FilenameUtils#isSystemWindows()}
     * <p>
     * For code that runs on Java 1.7 or later, use the following method instead:
     * <br>
     * {@code boolean java.nio.file.Files.isSymbolicLink(Path path)}
     * @param file the file to check
     * @return true if the file is a Symbolic Link
     * @throws IOException if an IO error occurs while checking the file
     * @since 2.0
     */
    public static boolean isSymlink(final File file) throws IOException {
        if (file == null) {
            throw new NullPointerException("File must not be null");
        }
        if (FilenameUtils.isSystemWindows()) {
            return false;
        }
        File fileInCanonicalDir = null;
        if (file.getParent() == null) {
            fileInCanonicalDir = file;
        } else {
            final File canonicalDir = file.getParentFile().getCanonicalFile();
            fileInCanonicalDir = new File(canonicalDir, file.getName());
        }

        if (fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile())) {
            return false;
        } else {
            return true;
        }
    }

ref: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/FileUtils.java?view=markup

Android LinearGradient

Bitmap    mBitmap;
Matrix    mShadowPaint;
Matrix    mLinearGradientMatrix;
LinearGradient    mLinearGradient;

mBitmap = BitmapFactory.decodeResource(getResource, R.drawable.jobs);

mShadowPaint = new Paint();
mShadowPaint.setStyle(Style.FILL);
mShadowPaint.setAlpha((int)0.9 * 255);

//渐变范围从(0, 0)到(1.0, 0)
//渐变颜色从红色到透明
//TileMode.CLAMP重复边缘色,这里实际是拉伸透明
mLinearGradient = new LinearGradient(0, 0, 1.0f, 0, Color.red, Color.TRANSPARENT, TileMode.CLAMP); 

mLinearGradientMatrix = new Matrix();
mLinearGradientMatrix.setScale(mBitmap.getWidth(), 1);
//把线性渐变的范围扩大到整张图片
mLinearGradient.setLocalMatrix(mLinearGradientMatrix);

mShadowPaint.setShader(mLinearGradient);

canvas.drawBitmap(mBitmap, 0, 0, null);
canvas.drawRect(0, 0, mBitmap.getWidth(), mBitmap.getHeight(), mShadowPaint);