- if ((infd = open (msgfile, O_RDONLY)) == -1) {
- advise (msgfile, "unable to open message %s", msgfile);
- return -1;
- }
- fstat (infd, &st1);
- if ((outfd = creat (newmsg, (int) st1.st_mode & 0777)) == -1) {
- advise (newmsg, "unable to create");
- close (infd);
+ linkerr = errno;
+
+ /*
+ ** Check if the file in our desired location is
+ ** the same as the source file. If so, then just
+ ** leave it alone and return. Otherwise, we will
+ ** continue the main loop and try again at another
+ ** slot (hghmsg+1).
+ */
+ if (linkerr == EEXIST) {
+ if (stat(msgfile, &st2) == 0 && stat(newmsg, &st1) == 0
+ && st2.st_ino == st1.st_ino) {
+ return msgnum;
+ } else {
+ continue;
+ }
+ }
+
+ /*
+ ** If link failed because we are trying to link
+ ** across devices, then check if there is a message
+ ** already in the desired location. If so, then return
+ ** error, else just copy the message.
+ */
+ if (linkerr == EXDEV) {
+ if (stat(newmsg, &st1) == 0) {
+ advise(NULL, "message %s:%s already exists", mp->foldpath, newmsg);
+ return -1;
+ } else {
+ if ((infd = open(msgfile, O_RDONLY)) == -1) {
+ advise(msgfile, "unable to open message %s", msgfile);
+ return -1;
+ }
+ fstat(infd, &st1);
+ if ((outfd = creat(newmsg, (int) st1.st_mode & 0777)) == -1) {
+ advise(newmsg, "unable to create");
+ close(infd);
+ return -1;
+ }
+ cpydata(infd, outfd, msgfile, newmsg);
+ close(infd);
+ close(outfd);
+
+ if (deleting) {
+ snprintf(oldmsg, sizeof oldmsg,
+ "%s/%s",
+ from_dir,
+ msgfile);
+ ext_hook("ref-hook", oldmsg, newmsg);
+ } else
+ ext_hook("add-hook", newmsg, NULL);
+
+ return msgnum;
+ }
+ }
+
+ /*
+ ** Else, some other type of link error,
+ ** so just return error.
+ */
+ advise(newmsg, "error linking %s to", msgfile);