static bool RegisterHandlerExtension()

in src/utils/extension_utils/src/extension_utils.c [189:329]


static bool RegisterHandlerExtension(
    const char* handlerId,
    const char* handlerFilePath,
    const char* handlerExtensionDir,
    const char* handlerRegistrationFileName)
{
    bool success = false;
    STRING_HANDLE folderName = NULL;
    STRING_HANDLE dir = NULL;
    STRING_HANDLE content = NULL;
    STRING_HANDLE outFilePath = NULL;
    FILE* outFile = NULL;
    char* hash = NULL;

    Log_Debug("Registering handler for '%s', file: %s", handlerId, handlerFilePath);

    if (IsNullOrEmpty(handlerId))
    {
        Log_Error("Invalid handler identifier.");
        goto done;
    }

    if (IsNullOrEmpty(handlerFilePath))
    {
        Log_Error("Invalid handler extension file path.");
        goto done;
    }

    folderName = PathUtils_SanitizePathSegment(handlerId);
    if (folderName == NULL)
    {
        Log_Error("Cannot generate a folder name from an Update Type.");
        goto done;
    }

    dir = STRING_construct_sprintf("%s/%s", handlerExtensionDir, STRING_c_str(folderName));
    if (dir == NULL)
    {
        goto done;
    }

    // Note: the return value may point to a static area,
    // and may be overwritten by subsequent calls to getpwent(3), getpwnam(), or getpwuid().
    // (Do not pass the returned pointer to free(3).)
    struct passwd* pwd = ADUCPAL_getpwnam(ADUC_FILE_USER);
    if (pwd == NULL)
    {
        Log_Error("Cannot verify credential of 'adu' user.");
        goto done;
    }
    uid_t aduUserId = pwd->pw_uid;
    pwd = NULL;

    // Note: The return value may point to a static area,
    // and may be overwritten by subsequent calls to getgrent(3), getgrgid(), or getgrnam().
    // (Do not pass the returned pointer to free(3).)
    struct group* grp = ADUCPAL_getgrnam(ADUC_FILE_GROUP);
    if (grp == NULL)
    {
        Log_Error("Cannot get 'adu' group info.");
        goto done;
    }
    gid_t aduGroupId = grp->gr_gid;
    grp = NULL;

    Log_Debug("Creating the extension folder ('%s'), uid:%d, gid:%d", STRING_c_str(dir), aduUserId, aduGroupId);
    int dir_result = ADUC_SystemUtils_MkDirRecursive(STRING_c_str(dir), aduUserId, aduGroupId, S_IRWXU | S_IRWXG);
    if (dir_result != 0)
    {
        Log_Error("Cannot create a folder for registration file. ('%s')", STRING_c_str(dir));
        goto done;
    }

    struct stat bS;
    if (stat(handlerFilePath, &bS) != 0)
    {
        goto done;
    }

    long fileSize = bS.st_size;
    if (!ADUC_HashUtils_GetFileHash(handlerFilePath, SHA256, &hash))
    {
        goto done;
    }

    content = STRING_construct_sprintf(
        "{\n"
        "   \"fileName\":\"%s\",\n"
        "   \"sizeInBytes\":%lld,\n"
        "   \"hashes\": {\n"
        "        \"sha256\":\"%s\"\n"
        "   },\n"
        "   \"handlerId\":\"%s\"\n"
        "}\n",
        handlerFilePath,
        fileSize,
        hash,
        handlerId);

    if (content == NULL)
    {
        Log_Error("Cannot compose the handler registration information.");
        goto done;
    }

    outFilePath = STRING_construct_sprintf("%s/%s", STRING_c_str(dir), handlerRegistrationFileName);
    outFile = fopen(STRING_c_str(outFilePath), "w");
    if (outFile == NULL)
    {
        Log_Error("Cannot open file: %s", STRING_c_str(outFilePath));
        goto done;
    }

    int ref = fputs(STRING_c_str(content), outFile);
    if (ref < 0)
    {
        Log_Error(
            "Failed to write the handler registration information to file. File:%s, Content:%s",
            STRING_c_str(dir),
            STRING_c_str(content));
        goto done;
    }

    // Print directly to stdout. Since this will be seen by customer,
    // we don't want to show any 'log' info (e.g., time stamp, log level.)
    printf(
        "Successfully registered a handler for '%s'. Registration file: %s.\n", handlerId, STRING_c_str(outFilePath));
    success = true;

done:
    if (outFile != NULL)
    {
        fclose(outFile);
    }

    STRING_delete(outFilePath);
    STRING_delete(dir);
    free(hash);

    return success;
}