pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


lockincfile1.c - lock file, read last line with "<tag> <value>", and write a new line "<mytag> <value+1>", unlock file
Posted by Anonymous on Tue 30th Sep 2025 18:46
raw | new post

  1. /*
  2.  * MIT License
  3.  *
  4.  * Copyright (c) 2025 Roland Mainz <roland.mainz@nrubsig.org>
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  7.  * of this software and associated documentation files (the "Software"), to deal
  8.  * in the Software without restriction, including without limitation the rights
  9.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10.  * copies of the Software, and to permit persons to whom the Software is
  11.  * furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included in
  14.  * all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22.  * SOFTWARE.
  23.  */
  24.  
  25. /*
  26.  * lockincfile1.c - lock file, read last line with "<tag> <value>", and write a new line "<mytag> <value+1>", unlock file
  27.  *
  28.  * Usage:
  29.  * $ clang -Wall -Wextra -O -g lockincfile1.c -o lockincfile1.exe
  30.  * $ rm -f contestedfile1.txt ; touch contestedfile1.txt
  31.  *
  32.  * Test run
  33.  * # on machine 1:
  34.  * $ time bash -c 'set -o errexit ; (for ((i=0 ; i < 400 ; i++)) ; do ./lockincfile1 contestedfile1.txt "aaa"; done) ; echo $?'
  35.  * # on machine 2:
  36.  * $ time bash -c 'set -o errexit ; (for ((i=0 ; i < 400 ; i++)) ; do ./lockincfile1 contestedfile1.txt "bbb"; done) ; echo $?'
  37.  * When both machines are finished the last line should match eregex ".+800"
  38.  */
  39. #include <windows.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <stdint.h>
  43. #include <string.h>
  44. #include <ctype.h>
  45.  
  46. #define EXIT_USAGE (2) /* Traditional UNIX exit code for usage */
  47.  
  48. int main(int argc, char *av[])
  49. {
  50.     if (argc != 3) {
  51.         (void)fprintf(stderr, "Usage:\n%s <filename> <tag>\n", av[0]);
  52.         return EXIT_USAGE;
  53.     }
  54.  
  55.     int retval = EXIT_FAILURE;
  56.     const char *fileName = av[1];
  57.     const char *tag = av[2];
  58.     long last_val = 0;
  59.     HANDLE h;
  60.     LARGE_INTEGER liFileSize;
  61.     char buffer[256];
  62.     char writeBuffer[256];
  63.     DWORD bytesRead, bytesWritten;
  64.     OVERLAPPED ov = { 0 };
  65.  
  66.     h = CreateFileA(fileName,
  67.         GENERIC_READ | GENERIC_WRITE,
  68.         FILE_SHARE_READ | FILE_SHARE_WRITE,
  69.         NULL,
  70.         OPEN_EXISTING,
  71.         /*FILE_ATTRIBUTE_NORMAL*/FILE_FLAG_NO_BUFFERING,
  72.         NULL);
  73.     if (h == INVALID_HANDLE_VALUE) {
  74.         (void)fprintf(stderr, "%s: Cannot open file '%s', lasterr=%ld\n",
  75.             av[0],
  76.             av[1],
  77.             (long)GetLastError());
  78.         (void)CloseHandle(h);
  79.         return EXIT_FAILURE;
  80.     }
  81.    
  82.     ov.hEvent = 0;
  83.     ov.Offset = 0;
  84.     ov.OffsetHigh = 0;
  85.     if (!LockFileEx(h, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &ov)) {
  86.         (void)fprintf(stderr,
  87.             "%s: Locking failed, lasterr=%ld\n",
  88.             av[0], (long)GetLastError());
  89.         (void)CloseHandle(h);
  90.         return EXIT_FAILURE;
  91.     }
  92.  
  93.     (void)GetFileSizeEx(h, &liFileSize);
  94.  
  95.     if (liFileSize.QuadPart > 0LL) {
  96.         LARGE_INTEGER liSeekPos;
  97.         if (liFileSize.QuadPart > (long long)(sizeof(buffer)-1))
  98.             liSeekPos.QuadPart = (liFileSize.QuadPart - (sizeof(buffer)-1));
  99.         else
  100.             liSeekPos.QuadPart = 0LL;
  101.  
  102.         (void)SetFilePointerEx(h, liSeekPos, NULL, FILE_BEGIN);
  103.  
  104.         if (!ReadFile(h, buffer, sizeof(buffer)-1, &bytesRead, NULL) || (bytesRead == 0)) {
  105.             (void)fprintf(stderr,
  106.                 "%s: ReadFile() failed, lasterr=%ld\n",
  107.                 av[0], (long)GetLastError());
  108.             goto cleanup;
  109.         }
  110.         buffer[bytesRead] = '\0';
  111.  
  112.         char *line_start = buffer;
  113.         char *p = buffer + bytesRead - 1;
  114.  
  115.         while ((p >= buffer) &&
  116.             isspace((unsigned char)*p)) {
  117.             p--;
  118.         }
  119.  
  120.         if (p >= buffer) {
  121.             line_start = p;
  122.             while (line_start > buffer && *(line_start - 1) != '\n') {
  123.                 line_start--;
  124.             }
  125.  
  126.             char *separator = NULL;
  127.             char *temp_p = p;
  128.             while (temp_p >= line_start) {
  129.                 if (*temp_p == ' ' || *temp_p == '\t') {
  130.                     separator = temp_p;
  131.                     break;
  132.                 }
  133.                 temp_p--;
  134.             }
  135.            
  136.             if (separator && isdigit((unsigned char)*(separator + 1))) {
  137.                 last_val = strtol(separator + 1, NULL, 10);
  138.             }
  139.         }
  140.     }
  141.    
  142.     LARGE_INTEGER liEndPos = { .QuadPart = 0LL };
  143.     (void)SetFilePointerEx(h, liEndPos, NULL, FILE_END);
  144.    
  145.     if (liFileSize.QuadPart > 0) {
  146.         char lastChar;
  147.         LARGE_INTEGER liLastCharPos;
  148.         liLastCharPos.QuadPart = -1;
  149.         (void)SetFilePointerEx(h, liLastCharPos, NULL, FILE_END);
  150.         if (ReadFile(h, &lastChar, 1, &bytesRead, NULL) && (bytesRead == 1)) {
  151.             if (lastChar != '\n') {
  152.                  (void)WriteFile(h, "\n", 1, &bytesWritten, NULL);
  153.             }
  154.         }
  155.     }
  156.  
  157.     int len = snprintf(writeBuffer, sizeof(writeBuffer),
  158.         "%s\t%ld\n", tag, (last_val + 1));
  159.     (void)WriteFile(h, writeBuffer, len, &bytesWritten, NULL);
  160.  
  161.     (void)FlushFileBuffers(h);
  162.     retval = EXIT_SUCCESS;
  163.  
  164. cleanup:    
  165.     (void)UnlockFileEx(h, 0, MAXDWORD, MAXDWORD, &ov);
  166.     (void)CloseHandle(h);
  167.  
  168.     return retval;
  169. }

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at