From e44794706eeb57f2ee38ed1604821aa38b8ad9d2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Apr 2005 22:26:31 -0700 Subject: [PATCH] Be much more liberal about the file mode bits. We only really care about the difference between a file being executable or not (by its owner). Everything else we leave for the user umask to decide. --- cache.h | 3 +++ checkout-cache.c | 15 +++++++++++++-- read-cache.c | 3 ++- read-tree.c | 2 +- update-cache.c | 4 ++-- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/cache.h b/cache.h index 88c2fa8d9..efeb82b6d 100644 --- a/cache.h +++ b/cache.h @@ -72,6 +72,9 @@ struct cache_entry { #define ce_size(ce) cache_entry_size(ce_namelen(ce)) #define ce_stage(ce) ((CE_STAGEMASK & ntohs((ce)->ce_flags)) >> CE_STAGESHIFT) +#define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644) +#define create_ce_mode(mode) htonl(S_IFREG | ce_permissions(mode)) + #define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7) const char *sha1_file_directory; diff --git a/checkout-cache.c b/checkout-cache.c index 8d5e4cd14..09b36b9c7 100644 --- a/checkout-cache.c +++ b/checkout-cache.c @@ -52,11 +52,14 @@ static void create_directories(const char *path) static int create_file(const char *path, unsigned int mode) { - int fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0600); + int fd; + + mode = (mode & 0100) ? 777 : 666; + fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode); if (fd < 0) { if (errno == ENOENT) { create_directories(path); - fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0600); + fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode); } } if (fd >= 0) @@ -104,6 +107,14 @@ static int checkout_entry(struct cache_entry *ce) fprintf(stderr, "checkout-cache: %s already exists\n", ce->name); return 0; } + + /* + * We unlink the old file, to get the new one with the + * right permissions (including umask, which is nasty + * to emulate by hand - much easier to let the system + * just do the right thing) + */ + unlink(ce->name); } return write_entry(ce); } diff --git a/read-cache.c b/read-cache.c index 5b4ab03d2..21f6e8e4d 100644 --- a/read-cache.c +++ b/read-cache.c @@ -303,7 +303,8 @@ int cache_match_stat(struct cache_entry *ce, struct stat *st) if (ce->ce_uid != htonl(st->st_uid) || ce->ce_gid != htonl(st->st_gid)) changed |= OWNER_CHANGED; - if (ce->ce_mode != htonl(st->st_mode)) + /* We consider only the owner x bit to be relevant for "mode changes" */ + if (0100 & (ntohs(ce->ce_mode) ^ st->st_mode)) changed |= MODE_CHANGED; if (ce->ce_dev != htonl(st->st_dev) || ce->ce_ino != htonl(st->st_ino)) diff --git a/read-tree.c b/read-tree.c index c4ca86f48..f507f1633 100644 --- a/read-tree.c +++ b/read-tree.c @@ -15,7 +15,7 @@ static int read_one_entry(unsigned char *sha1, const char *base, int baselen, co memset(ce, 0, size); - ce->ce_mode = htonl(mode); + ce->ce_mode = create_ce_mode(mode); ce->ce_flags = create_ce_flags(baselen + len, stage); memcpy(ce->name, base, baselen); memcpy(ce->name + baselen, pathname, len+1); diff --git a/update-cache.c b/update-cache.c index 134ba7439..7d1d8e512 100644 --- a/update-cache.c +++ b/update-cache.c @@ -106,7 +106,7 @@ static int add_file_to_cache(char *path) memset(ce, 0, size); memcpy(ce->name, path, namelen); fill_stat_cache_info(ce, &st); - ce->ce_mode = htonl(st.st_mode); + ce->ce_mode = create_ce_mode(st.st_mode); ce->ce_flags = htons(namelen); if (index_fd(path, namelen, ce, fd, &st) < 0) @@ -260,7 +260,7 @@ static int add_cacheinfo(char *arg1, char *arg2, char *arg3) memcpy(ce->sha1, sha1, 20); memcpy(ce->name, arg3, len); ce->ce_flags = htons(len); - ce->ce_mode = htonl(mode); + ce->ce_mode = create_ce_mode(mode); return add_cache_entry(ce, allow_add); } -- 2.30.2