From owner-freebsd-hackers@FreeBSD.ORG Tue Jan 27 08:57:55 2015 Return-Path: Delivered-To: hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 65538847 for ; Tue, 27 Jan 2015 08:57:55 +0000 (UTC) Received: from mx.nsu.ru (mx.nsu.ru [84.237.50.39]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 113A2782 for ; Tue, 27 Jan 2015 08:57:54 +0000 (UTC) Received: from regency.nsu.ru ([193.124.210.26]) by mx.nsu.ru with esmtp (Exim 4.72) (envelope-from ) id 1YG1xs-000325-2z for hackers@freebsd.org; Tue, 27 Jan 2015 14:57:45 +0600 Received: from regency.nsu.ru (localhost [127.0.0.1]) by regency.nsu.ru (8.14.2/8.14.2) with ESMTP id t0R8woQG085669 for ; Tue, 27 Jan 2015 15:59:00 +0700 (NOVT) (envelope-from danfe@regency.nsu.ru) Received: (from danfe@localhost) by regency.nsu.ru (8.14.2/8.14.2/Submit) id t0R8wiK0085648 for hackers@freebsd.org; Tue, 27 Jan 2015 14:58:44 +0600 (NOVT) (envelope-from danfe) Date: Tue, 27 Jan 2015 14:58:44 +0600 From: Alexey Dokuchaev To: hackers@freebsd.org Subject: Bug in ln(1), its manpage, or just misunderstanding? Message-ID: <20150127085844.GA83566@regency.nsu.ru> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.1i X-KLMS-Rule-ID: 1 X-KLMS-Message-Action: clean X-KLMS-AntiSpam-Lua-Profiles: 72372 [Jan 27 2015] X-KLMS-AntiSpam-Version: 5.5.4 X-KLMS-AntiSpam-Envelope-From: danfe@regency.nsu.ru X-KLMS-AntiSpam-Rate: 0 X-KLMS-AntiSpam-Status: not_detected X-KLMS-AntiSpam-Method: none X-KLMS-AntiSpam-Moebius-Timestamps: 3339812, 3339855, 0 X-KLMS-AntiSpam-Info: LuaCore: 140 2015-01-26_18-33-17 983317d61d1ecd4ac9970a372a44da82bfc7124e, 193.124.210.26:4.0.2 X-KLMS-AntiSpam-Interceptor-Info: scan successful X-KLMS-AntiPhishing: Clean, 2015/01/26 15:19:49 X-KLMS-AntiVirus: Kaspersky Security 8.0 for Linux Mail Server, version 8.0.1.705, not scanned, license restriction X-Mailman-Approved-At: Tue, 27 Jan 2015 12:33:40 +0000 X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Jan 2015 08:57:55 -0000 Hi there, Per man ln(1), it has -F option which: -F If the target file already exists and is a directory, then remove it so that the link may occur. The -F option should be used with either -f or -i options. If none is specified, -f is implied. The -F option is a no-op unless -s option is specified. As I read it correctly, it basically removes empty directory so I can place a link of the same name there: $ mkdir foo $ ln -sF /etc foo # result should be: foo -> /etc However, in ln.c, static int linkit(const char *source, const char *target, int isdir) contains: /* * If the target is a directory (and not a symlink if hflag), * append the source's name. */ if (isdir || (lstat(target, &sb) == 0 && S_ISDIR(sb.st_mode)) || (!hflag && stat(target, &sb) == 0 && S_ISDIR(sb.st_mode))) { if (strlcpy(bbuf, source, sizeof(bbuf)) >= sizeof(bbuf) || (p = basename(bbuf)) == NULL || snprintf(path, sizeof(path), "%s/%s", target, p) >= ... It seems that this logic should be dependent on -F flag, as otherwise source name is always appended to target and condition that "target file already exists and is a directory" is impossible to specify and assess: $ mkdir foo $ ln -sF /etc foo # result is "foo/etc -> /etc", not "foo -> /etc" The code is even more bogus: it silently removes directory (and yet returns an error), which makes it idempotent: $ mkdir foo $ ln -sF / foo ; echo $? ln: foo//: No such file or directory 1 < no foo at this point > $ ln -sF / foo ; echo $? 0 < now foo -> / > $ ln -sF / foo ; echo $? ln: foo//: Is a directory 1 ./danfe