{"thread":{"id":"9231","subject":"[PATCH 1/5] Add is_absolute_path(), make_absolute_path() and normalize_path()","startedAt":"2007-07-26T06:24:28Z","lastAt":"2007-07-26T19:02:37Z","messageCount":5,"participants":["Johannes Schindelin","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"48648","messageId":"Pine.LNX.4.64.0707260724010.14781@racer.site","threadId":"9231","inReplyTo":null,"subject":"[PATCH 1/5] Add is_absolute_path(), make_absolute_path() and normalize_path()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-26T06:24:28Z","receivedAt":"2007-07-26T06:24:28Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis patch adds convenience functions to work with absolute paths.\nThe function is_absolute_path() should help the efforts to integrate\nthe MinGW fork.\n\nNote that make_absolute_path() returns a pointer to a static buffer.\n\nGiven a path which possibly contains \"/../\" and \"/./\", or which end\nin \"/\", normalize_path() returns a normalized path.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n cache.h |    6 ++++++\n path.c  |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 60 insertions(+), 0 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 53801b8..b242147 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -358,6 +358,12 @@ int git_config_perm(const char *var, const char *value);\n int adjust_shared_perm(const char *path);\n int safe_create_leading_directories(char *path);\n char *enter_repo(char *path, int strict);\n+static inline int is_absolute_path(const char *path)\n+{\n+\treturn path[0] == '/';\n+}\n+const char *make_absolute_path(const char *path);\n+char *normalize_path(char *path);\n \n /* Read and unpack a sha1 file into memory, write memory to a sha1 file */\n extern int sha1_object_info(const unsigned char *, unsigned long *);\ndiff --git a/path.c b/path.c\nindex c4ce962..92ce688 100644\n--- a/path.c\n+++ b/path.c\n@@ -292,3 +292,57 @@ int adjust_shared_perm(const char *path)\n \t\treturn -2;\n \treturn 0;\n }\n+\n+const char *make_absolute_path(const char *path)\n+{\n+\tstatic char buf[PATH_MAX];\n+\tconst int size = sizeof(buf);\n+\tint len;\n+\n+\tif (is_absolute_path(path))\n+\t\treturn path;\n+\n+\tif (!getcwd(buf, size))\n+\t\tdie (\"Could not get current working directory\");\n+\tif (!strcmp(path, \".\"))\n+\t\treturn buf;\n+\n+\tlen = strlen(buf);\n+\tif (snprintf(buf + len, size - len, \"/%s\", path) > size - 1)\n+\t\tdie (\"Could not make absolute path from '%s'\", path);\n+\treturn normalize_path(buf);\n+}\n+\n+/* strip out .. and . */\n+char *normalize_path(char *path)\n+{\n+\tint i, j;\n+\n+\tfor (i = 0, j = 0; path[i]; i++, j++) {\n+\t\tif (path[i] == '.') {\n+\t\t\tif (path[i + 1] == '/') {\n+\t\t\t\ti++; j--;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (path[i + 1] == '.' && (path[i + 2] == '/' ||\n+\t\t\t\t\t\t!path[i + 2])) {\n+\t\t\t\ti += 1 + !!path[i + 2];\n+\t\t\t\tj--;\n+\t\t\t\twhile (j > 0 && path[--j] != '/')\n+\t\t\t\t\t; /* do nothing */\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t}\n+\t\tfor (; path[i + 1]; i++, j++) {\n+\t\t\tpath[j] = path[i];\n+\t\t\tif (path[i] == '/')\n+\t\t\t\tbreak;\n+\t\t}\n+\t\tpath[j] = path[i];\n+\t}\n+\tif (j > 0 && path[j - 1] == '/')\n+\t\tj--;\n+\tpath[j] = '\\0';\n+\n+\treturn path;\n+}\n-- \n1.5.3.rc2.42.gda8d-dirty\n"},{"id":"48661","messageId":"7v1wevac63.fsf@assigned-by-dhcp.cox.net","threadId":"9231","inReplyTo":"Pine.LNX.4.64.0707260724010.14781@racer.site","subject":"Re: [PATCH 1/5] Add is_absolute_path(), make_absolute_path() and normalize_path()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-07-26T06:53:24Z","receivedAt":"2007-07-26T06:53:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> +/* strip out .. and . */\n> +char *normalize_path(char *path)\n> +{\n\nThis always makes one worry what should happen when foo/../bar\nis _not_ bar in reality (i.e. foo is symlink to a directory\nelsewhere).\n\nIt depends on what kind of \"path\" you feed to the function (and\nits caller, make_absolute_path()).  If you always feed a path\nfrom the index (or a path obtained by recursively reading a\ntree), it is Ok.  If it is arbitrary path obtained from the user\nor the filesystem, it is not.\n"},{"id":"48703","messageId":"Pine.LNX.4.64.0707261456040.14781@racer.site","threadId":"9231","inReplyTo":"7v1wevac63.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 1/5] Add is_absolute_path(), make_absolute_path() and normalize_path()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-26T13:58:59Z","receivedAt":"2007-07-26T13:58:59Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 25 Jul 2007, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > +/* strip out .. and . */\n> > +char *normalize_path(char *path)\n> > +{\n> \n> This always makes one worry what should happen when foo/../bar\n> is _not_ bar in reality (i.e. foo is symlink to a directory\n> elsewhere).\n> \n> It depends on what kind of \"path\" you feed to the function (and\n> its caller, make_absolute_path()).  If you always feed a path\n> >from the index (or a path obtained by recursively reading a\n> tree), it is Ok.  If it is arbitrary path obtained from the user\n> or the filesystem, it is not.\n\nAgree.  Maybe a comment above the function, like\n\n\t/*\n\t * The function normalize_path() converts \"..\" and \".\" names in \n\t * the given path so that \"foo/../bar/./\" will come out as \"bar\".\n\t *\n\t * Note: normalize_path() does not follow symlinks, so if \"foo\" is\n\t * a symlink in the example above, the result will not work as \n\t * expected.\n\t */\n\nHmm?\n\nCiao,\nDscho\n"},{"id":"48728","messageId":"7v4pjr80lr.fsf@assigned-by-dhcp.cox.net","threadId":"9231","inReplyTo":"Pine.LNX.4.64.0707261456040.14781@racer.site","subject":"Re: [PATCH 1/5] Add is_absolute_path(), make_absolute_path() and normalize_path()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-07-26T18:46:08Z","receivedAt":"2007-07-26T18:46:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> Agree.  Maybe a comment above the function, like\n>\n> \t/*\n> \t * The function normalize_path() converts \"..\" and \".\" names in \n> \t * the given path so that \"foo/../bar/./\" will come out as \"bar\".\n> \t *\n> \t * Note: normalize_path() does not follow symlinks, so if \"foo\" is\n> \t * a symlink in the example above, the result will not work as \n> \t * expected.\n> \t */\n>\n> Hmm?\n\nThat comment only states the obvious and does not give a clue to\nthe callers when it should not be used, I am afraid.  For\nexample, paths taken out of index or recursively reading trees\nare Ok because there will not be \"..\" and \".\" in them.  Making a\npath given by the user relative to the cwd by prepending what is\nreturned by setup_git_directory() may or may not be safe,\ndepending on how setup_git_directory() does things (I think the\noriginal one is safe; I am reasonably sure with the current one\nwhen GIT_WORK_TREE is not in use; I do not know when that\nenvironment variable is there with the current code with or\nwithout your patch series).\n"},{"id":"48731","messageId":"Pine.LNX.4.64.0707261955540.14781@racer.site","threadId":"9231","inReplyTo":"7v4pjr80lr.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 1/5] Add is_absolute_path(), make_absolute_path() and normalize_path()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-26T19:02:37Z","receivedAt":"2007-07-26T19:02:37Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 26 Jul 2007, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > Agree.  Maybe a comment above the function, like\n> >\n> > \t/*\n> > \t * The function normalize_path() converts \"..\" and \".\" names in \n> > \t * the given path so that \"foo/../bar/./\" will come out as \"bar\".\n> > \t *\n> > \t * Note: normalize_path() does not follow symlinks, so if \"foo\" is\n> > \t * a symlink in the example above, the result will not work as \n> > \t * expected.\n> > \t */\n> >\n> > Hmm?\n> \n> That comment only states the obvious and does not give a clue to\n> the callers when it should not be used, I am afraid.\n\nI am afraid, that it was unobvious enough to yours truly to forget about \nthat when writing the patch.\n\n> For example, paths taken out of index or recursively reading trees are \n> Ok because there will not be \"..\" and \".\" in them.  Making a path given \n> by the user relative to the cwd by prepending what is returned by \n> setup_git_directory() may or may not be safe, depending on how \n> setup_git_directory() does things (I think the original one is safe; I \n> am reasonably sure with the current one when GIT_WORK_TREE is not in \n> use; I do not know when that environment variable is there with the \n> current code with or without your patch series).\n\nI am afraid that already GIT_DIR can contain symlinks, and is not checked \nby setup_git_env().\n\nSo I think some concrete comment is needed in _addition_:\n\n\tget_git_dir() is not safe, and therefore git_path(), too.\n\nHmm.\n\nMaybe the easiest way _is_ to getcwd(); chdir() getcwd(); chdir(back); \nUgly.\n\nCiao,\nDscho\n"}]}